Add upload button and simulated progress to Mock Trial page
This commit is contained in:
parent
9cff752d40
commit
7999a3fa04
@ -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() {
|
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 (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold text-slate-900 dark:text-white">Mock Trial Simulator</h1>
|
<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>
|
</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>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
{isUploading && (
|
||||||
<div className="lg:col-span-2 space-y-6">
|
<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="bg-slate-900 rounded-2xl aspect-video relative overflow-hidden border-4 border-slate-800 shadow-2xl">
|
<div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white">
|
||||||
<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>
|
<Upload size={20} className="animate-bounce" />
|
||||||
<div className="absolute inset-0 flex flex-col items-center justify-center text-center p-8">
|
</div>
|
||||||
<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">
|
<div className="flex-1">
|
||||||
<Gavel size={40} />
|
<div className="flex justify-between items-center mb-1">
|
||||||
</div>
|
<p className="text-sm font-bold text-blue-900 dark:text-blue-100">Processing: {selectedFile?.name}</p>
|
||||||
<h2 className="text-2xl font-bold text-white mb-2">The Honorable AI Judge</h2>
|
<p className="text-xs font-bold text-blue-600">{uploadProgress}%</p>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-full bg-blue-200 dark:bg-blue-800 h-2 rounded-full overflow-hidden">
|
||||||
<div className="absolute bottom-6 left-6 right-6 flex justify-between items-center">
|
<div
|
||||||
<div className="flex gap-4">
|
className="bg-blue-600 h-full transition-all duration-300"
|
||||||
<div className="flex items-center gap-2 bg-slate-800/80 backdrop-blur px-3 py-1.5 rounded-lg border border-slate-700">
|
style={{ width: `${uploadProgress}%` }}
|
||||||
<div className="w-2 h-2 bg-red-500 rounded-full animate-pulse"></div>
|
></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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button onClick={() => setIsUploading(false)} className="text-blue-400 hover:text-blue-600">
|
||||||
|
<X size={20} />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-6">
|
<div className="flex flex-col md:flex-row gap-4">
|
||||||
<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">
|
<div className="relative flex-1">
|
||||||
<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">
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={18} />
|
||||||
<MessageSquare size={18} className="text-blue-500" />
|
<input
|
||||||
<h3 className="font-bold text-sm">Trial Log</h3>
|
type="text"
|
||||||
</header>
|
placeholder="Search mock trials..."
|
||||||
<div className="flex-1 p-4 space-y-4 min-h-[400px]">
|
value={searchQuery}
|
||||||
<div className="text-center py-10 text-slate-400">
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
<p className="text-sm italic">"The court is now in session..."</p>
|
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"
|
||||||
<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>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user