Add upload button and simulated progress to Mock Trial page

This commit is contained in:
gamvo74 2026-02-25 11:31:38 -05:00
parent 9cff752d40
commit 7999a3fa04

View File

@ -1,95 +1,179 @@
import { Gavel, Mic, Users, MessageSquare, Play, Info } from 'lucide-react';
"use client";
import { useState, useRef } from 'react';
import {
Plus,
Search,
Gavel,
User,
Mic,
Book,
MessageSquare,
Upload,
X,
FileAudio
} from 'lucide-react';
const mockTrials = [
{
id: '1',
title: 'Barden v. State Farm - Jurisdiction Challenge',
status: 'Ready for Play',
lastPractice: '2 days ago',
transcript: 'Plaintiff argues lack of personal jurisdiction...',
players: ['AI Judge', 'AI Opposing Counsel'],
},
{
id: '2',
title: 'Malveo Estate - Witness Testimony',
status: 'Drafting Script',
lastPractice: '1 week ago',
transcript: 'Witness deposition regarding estate assets...',
players: ['AI Judge'],
},
];
export default function MockTrialPage() {
const [searchQuery, setSearchQuery] = useState('');
const [isUploading, setIsUploading] = useState(false);
const [uploadProgress, setUploadProgress] = useState(0);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const handleUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
setSelectedFile(file);
simulateUpload();
}
};
const simulateUpload = () => {
setIsUploading(true);
let progress = 0;
const interval = setInterval(() => {
progress += 10;
setUploadProgress(progress);
if (progress >= 100) {
clearInterval(interval);
setTimeout(() => {
setIsUploading(false);
setUploadProgress(0);
alert('Simulated upload complete. Actual backend integration coming soon!');
}, 500);
}
}, 200);
};
return (
<div className="space-y-8">
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-slate-900 dark:text-white">Mock Trial Simulator</h1>
<p className="text-slate-500">Practice your arguments and receive real-time feedback from an AI Judge.</p>
<p className="text-sm text-slate-500">Practice your arguments against AI Judge & Opposing Counsel.</p>
</div>
<div className="flex gap-2">
<input
type="file"
ref={fileInputRef}
onChange={handleUpload}
className="hidden"
accept="image/*,audio/*,video/*,.pdf,.docx,.txt,.csv,.xlsx,.json,.html,.md,.zip" // All supported types
multiple // Allow multiple files for batch upload simulation
/>
<button
onClick={() => fileInputRef.current?.click()}
className="flex items-center gap-2 px-4 py-2 bg-slate-900 text-white rounded-lg font-bold hover:bg-slate-800 transition-colors shadow-lg"
>
<Upload size={18} />
Upload Files or Folder
</button>
<button className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg font-bold hover:bg-blue-700 transition-colors shadow-lg shadow-blue-500/20">
<Plus size={20} />
Create New Trial
</button>
</div>
<button className="flex items-center gap-2 px-6 py-3 bg-blue-600 text-white rounded-xl font-bold hover:bg-blue-700 transition-all shadow-xl shadow-blue-500/20 active:scale-95">
<Play size={20} fill="currentColor" />
Start Simulation
</button>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 space-y-6">
<div className="bg-slate-900 rounded-2xl aspect-video relative overflow-hidden border-4 border-slate-800 shadow-2xl">
<div className="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1589829545856-d10d557cf95f?auto=format&fit=crop&q=80&w=2000')] bg-cover bg-center opacity-20"></div>
<div className="absolute inset-0 flex flex-col items-center justify-center text-center p-8">
<div className="w-20 h-20 rounded-full bg-slate-800 flex items-center justify-center text-slate-400 mb-6 border-2 border-slate-700">
<Gavel size={40} />
</div>
<h2 className="text-2xl font-bold text-white mb-2">The Honorable AI Judge</h2>
<p className="text-slate-400 max-w-md mx-auto">Ready to hear your opening statement or oral argument. Click 'Start Simulation' to begin.</p>
{isUploading && (
<div className="mx-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-100 dark:border-blue-800 p-4 rounded-xl flex items-center gap-4">
<div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white">
<Upload size={20} className="animate-bounce" />
</div>
<div className="flex-1">
<div className="flex justify-between items-center mb-1">
<p className="text-sm font-bold text-blue-900 dark:text-blue-100">Processing: {selectedFile?.name}</p>
<p className="text-xs font-bold text-blue-600">{uploadProgress}%</p>
</div>
<div className="absolute bottom-6 left-6 right-6 flex justify-between items-center">
<div className="flex gap-4">
<div className="flex items-center gap-2 bg-slate-800/80 backdrop-blur px-3 py-1.5 rounded-lg border border-slate-700">
<div className="w-2 h-2 bg-red-500 rounded-full animate-pulse"></div>
<span className="text-xs font-bold text-white uppercase tracking-widest">Live</span>
</div>
</div>
<div className="flex gap-2">
<button className="p-3 bg-slate-800/80 backdrop-blur rounded-full text-white hover:bg-slate-700 border border-slate-700">
<Mic size={20} />
</button>
<button className="p-3 bg-slate-800/80 backdrop-blur rounded-full text-white hover:bg-slate-700 border border-slate-700">
<Users size={20} />
</button>
</div>
</div>
</div>
<div className="bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 p-6">
<h3 className="text-lg font-bold mb-4 flex items-center gap-2">
<Info size={18} className="text-blue-500" />
Simulation Settings
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<label className="text-xs font-bold text-slate-500 uppercase tracking-wider">Role</label>
<select className="w-full bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
<option>Plaintiff Counsel</option>
<option>Defendant Counsel</option>
<option>Witness (Direct/Cross)</option>
</select>
</div>
<div className="space-y-2">
<label className="text-xs font-bold text-slate-500 uppercase tracking-wider">Judge Persona</label>
<select className="w-full bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
<option>Strict & Formal</option>
<option>Helpful & Instructive</option>
<option>Skeptical & Challenging</option>
</select>
</div>
<div className="w-full bg-blue-200 dark:bg-blue-800 h-2 rounded-full overflow-hidden">
<div
className="bg-blue-600 h-full transition-all duration-300"
style={{ width: `${uploadProgress}%` }}
></div>
</div>
</div>
<button onClick={() => setIsUploading(false)} className="text-blue-400 hover:text-blue-600">
<X size={20} />
</button>
</div>
)}
<div className="space-y-6">
<div className="bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 flex flex-col h-full overflow-hidden shadow-sm">
<header className="p-4 border-b border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-800/50 flex items-center gap-2">
<MessageSquare size={18} className="text-blue-500" />
<h3 className="font-bold text-sm">Trial Log</h3>
</header>
<div className="flex-1 p-4 space-y-4 min-h-[400px]">
<div className="text-center py-10 text-slate-400">
<p className="text-sm italic">"The court is now in session..."</p>
<p className="text-xs mt-2">Logs will appear here during your simulation.</p>
</div>
</div>
<div className="p-4 border-t border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-800/50">
<button className="w-full py-2 bg-slate-200 dark:bg-slate-800 text-slate-600 dark:text-slate-400 rounded-lg text-xs font-bold hover:bg-slate-300 transition-colors uppercase tracking-widest">
Export Transcript
</button>
</div>
</div>
<div className="flex flex-col md:flex-row gap-4">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={18} />
<input
type="text"
placeholder="Search mock trials..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full pl-10 pr-4 py-2 rounded-lg border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all"
/>
</div>
</div>
<div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-xl overflow-hidden shadow-sm">
<table className="w-full text-left border-collapse">
<thead>
<tr className="bg-slate-50 dark:bg-slate-800/50 text-slate-500 text-xs uppercase tracking-wider font-bold">
<th className="px-6 py-4">Trial Name</th>
<th className="px-6 py-4">Status</th>
<th className="px-6 py-4">Players</th>
<th className="px-6 py-4">Last Practice</th>
<th className="px-6 py-4 text-right">Actions</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-100 dark:divide-slate-800">
{mockTrials.map((trial) => (
<tr key={trial.id} className="hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors cursor-pointer group">
<td className="px-6 py-4">
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-lg bg-red-50 dark:bg-red-900/30 flex items-center justify-center text-red-600">
<Gavel size={16} />
</div>
<span className="font-bold text-slate-900 dark:text-white group-hover:text-red-600 transition-colors">{trial.title}</span>
</div>
</td>
<td className="px-6 py-4 text-sm text-slate-600 dark:text-slate-400">{trial.status}</td>
<td className="px-6 py-4">
<div className="flex items-center -space-x-2">
{trial.players.map((player, index) => (
<span key={index} className="w-8 h-8 rounded-full bg-slate-100 dark:bg-slate-700 border-2 border-white dark:border-slate-900 flex items-center justify-center text-xs font-bold text-slate-600 dark:text-slate-300">
{player.includes('AI') ? <Bot size={16} /> : <User size={16} />}
</span>
))}
</div>
</td>
<td className="px-6 py-4 text-sm text-slate-500">{trial.lastPractice}</td>
<td className="px-6 py-4 text-right">
<button className="flex items-center gap-2 px-3 py-1 bg-blue-600 text-white rounded-lg text-sm font-bold hover:bg-blue-700 transition-colors">
<Play size={16} /> Play
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}