![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.quebec/private_html/src/components/ |
import React from 'react';
import { format } from 'date-fns';
import {
ArrowLeft,
Edit,
Users,
Calendar,
Scale,
FileText,
CheckCircle,
Clock,
XCircle,
AlertTriangle,
DollarSign,
MapPin,
User,
Target,
TrendingUp,
Heart,
MessageSquare,
MessageCircle,
Star,
Badge,
Eye,
Shield,
Award,
Pencil,
Plus,
Trash,
Share2,
Bookmark,
Bell,
ExternalLink,
ChevronRight,
Zap,
Award as Trophy,
Globe,
Building
} from 'lucide-react';
import LawyerRatingStars from './LawyerRatingStars';
import EnhancedComments from './EnhancedComments';
import CaseTimeline from './CaseTimeline';
import LiveCaseChat from './LiveCaseChat';
import Link from 'next/link';
import EnhancedShareButton from './EnhancedShareButton';
import { useState, useRef } from 'react';
interface CaseDetailProps {
caseData: any;
currentUser?: any;
mode: 'public' | 'admin';
onEdit?: () => void;
onManageTeam?: () => void;
onViewApplications?: () => void;
}
interface Document {
id: string;
name: string;
url: string;
type?: string;
fileSize: number;
createdAt?: string;
description?: string;
userId?: string;
user?: {
id: string;
name: string;
profilePicture?: string;
};
}
const getPriorityColor = (priority: string) => {
switch (priority) {
case 'urgent': return 'bg-red-100 text-red-800 border-red-200';
case 'high': return 'bg-orange-100 text-orange-800 border-orange-200';
case 'medium': return 'bg-blue-100 text-blue-800 border-blue-200';
case 'low': return 'bg-gray-100 text-gray-800 border-gray-200';
default: return 'bg-gray-100 text-gray-800 border-gray-200';
}
};
const getStatusColor = (status: string) => {
switch (status) {
case 'active': return 'bg-green-100 text-green-800';
case 'pending': return 'bg-yellow-100 text-yellow-800';
case 'closed': return 'bg-gray-100 text-gray-800';
default: return 'bg-blue-100 text-blue-800';
}
};
const getStatusIcon = (status: string) => {
switch (status) {
case 'active': return <CheckCircle className="h-5 w-5 text-green-500" />;
case 'pending': return <Clock className="h-5 w-5 text-yellow-500" />;
case 'closed': return <XCircle className="h-5 w-5 text-gray-500" />;
case 'suspended': return <AlertTriangle className="h-5 w-5 text-red-500" />;
default: return <Clock className="h-5 w-5 text-gray-400" />;
}
};
const getUpdateTypeIcon = (type: string) => {
switch (type) {
case 'procedural': return <Scale className="h-4 w-4 text-blue-600" />;
case 'settlement': return <DollarSign className="h-4 w-4 text-green-600" />;
case 'court_date': return <Calendar className="h-4 w-4 text-orange-600" />;
case 'evidence': return <Shield className="h-4 w-4 text-purple-600" />;
default: return <TrendingUp className="h-4 w-4 text-gray-600" />;
}
};
const CaseDetail: React.FC<CaseDetailProps> = ({ caseData, currentUser, mode, onEdit, onManageTeam, onViewApplications }) => {
const [userApplication, setUserApplication] = React.useState<any>(null);
const [checkingApplication, setCheckingApplication] = React.useState(false);
const [buttonTooltip, setButtonTooltip] = React.useState('');
const [isBookmarked, setIsBookmarked] = React.useState(false);
const [showLogoUpload, setShowLogoUpload] = React.useState(false);
const [logoFile, setLogoFile] = React.useState<File | null>(null);
const [logoPreview, setLogoPreview] = React.useState<string | null>(null);
const [isUploadingLogo, setIsUploadingLogo] = React.useState(false);
const router = require('next/router').useRouter ? require('next/router').useRouter() : null;
const [showUploadModal, setShowUploadModal] = useState(false);
const [uploading, setUploading] = useState(false);
const [uploadError, setUploadError] = useState<string | null>(null);
const [uploadDescription, setUploadDescription] = useState('');
const [uploadPublic, setUploadPublic] = useState(false);
const [uploadedFile, setUploadedFile] = useState<File | null>(null);
const [documents, setDocuments] = useState<any[]>([]);
const [componentError, setComponentError] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
// Error boundary for component
if (componentError) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center max-w-md mx-auto">
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
<h1 className="text-xl font-bold mb-2">Component Error</h1>
<p className="text-sm">{componentError}</p>
</div>
<button
onClick={() => setComponentError(null)}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
Try Again
</button>
</div>
</div>
);
}
const isLawyer = currentUser?.role === 'LAWYER';
const isVerified = currentUser?.isVerifiedLawyer || currentUser?.verificationStatus === 'VERIFIED_BARREAU';
React.useEffect(() => {
const fetchUserApplication = async () => {
if (!currentUser || !caseData?.id) return;
setCheckingApplication(true);
try {
const res = await fetch(
if (res.ok) {
const data = await res.json();
if (data && data.length > 0) {
setUserApplication(data[0]);
} else {
setUserApplication(null);
}
}
} catch (error) {
setComponentError('Failed to load application data');
} finally {
setCheckingApplication(false);
}
};
fetchUserApplication();
}, [currentUser, caseData?.id]);
React.useEffect(() => {
try {
if (!caseData?.isAcceptingApplications) {
setButtonTooltip('This case is not accepting applications at this time.');
} else if (userApplication && userApplication.status === 'PENDING') {
setButtonTooltip('Continue your application for this case.');
} else if (userApplication && userApplication.status === 'SUBMITTED') {
setButtonTooltip('View your submitted application for this case.');
} else {
setButtonTooltip('Start a new application for this case.');
}
} catch (error) {
}
}, [userApplication, caseData]);
const getRequiredDocuments = () => {
if (!caseData?.requiredDocuments) return [];
try {
if (Array.isArray(caseData.requiredDocuments)) {
return caseData.requiredDocuments;
}
if (typeof caseData.requiredDocuments === 'string') {
const parsed = JSON.parse(caseData.requiredDocuments);
return Array.isArray(parsed) ? parsed : [];
}
return [];
} catch (error) {
return [];
}
};
const handleDelete = async () => {
if (!window.confirm('Are you sure you want to delete this case? This action cannot be undone.')) return;
try {
const res = await fetch(`/api/cases/${caseData.id}
if (res.ok) {
alert('Case deleted successfully.');
if (router) {
router.push('/');
} else {
// Use history API instead of hard navigation
window.history.pushState({}, '', '/');
window.dispatchEvent(new PopStateEvent('popstate'));
}
} else {
const error = await res.text();
alert('Failed to delete case: ' + error);
}
} catch (err) {
alert('Error deleting case.');
}
};
const toggleBookmark = () => {
setIsBookmarked(!isBookmarked);
// You could add API call here to save bookmark
};
const getCaseProgress = () => {
// Calculate progress based on case status and updates
if (!caseData?.status) return 0;
if (caseData.status === 'closed') return 100;
if (caseData.status === 'active') return 75;
if (caseData.status === 'pending') return 25;
return 0;
};
// Logo change functionality
const handleLogoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
setLogoFile(file);
setLogoPreview(URL.createObjectURL(file));
}
};
const handleLogoUpload = async () => {
if (!logoFile || !caseData?.id) return;
setIsUploadingLogo(true);
try {
// Upload logo first
const formData = new FormData();
formData.append('file', logoFile);
const uploadRes = await fetch('/api/upload', {
method: 'POST',
body: formData
});
if (!uploadRes.ok) throw new Error('Failed to upload logo');
const uploadData = await uploadRes.json();
// Update case with new logo URL
const updateRes = await fetch(`/api/cases/${caseData.id}
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ logoUrl: uploadData.url })
});
if (updateRes.ok) {
// Update local state
caseData.logoUrl = uploadData.url;
setShowLogoUpload(false);
setLogoFile(null);
setLogoPreview(null);
// Force re-render
window.location.reload();
} else {
throw new Error('Failed to update case');
}
} catch (error) {
alert('Failed to update logo. Please try again.');
} finally {
setIsUploadingLogo(false);
}
};
const isCaseCreator = currentUser?.id === caseData?.createdBy;
// Upload handler
const handleDocumentUpload = async (e: React.FormEvent) => {
e.preventDefault();
if (!uploadedFile || !currentUser) return;
// Validate file size (10MB limit)
if (uploadedFile.size > 10 * 1024 * 1024) {
setUploadError('File size must be less than 10MB');
return;
}
// Validate file type
const allowedTypes = [
'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'text/plain', 'application/zip', 'application/x-rar-compressed'
];
if (!allowedTypes.includes(uploadedFile.type)) {
setUploadError('File type not allowed. Please upload images, PDFs, documents, or archives.');
return;
}
setUploading(true);
setUploadError(null);
try {
const formData = new FormData();
formData.append('file', uploadedFile);
formData.append('description', uploadDescription);
formData.append('public', String(uploadPublic));
const res = await fetch(`/api/cases/${caseData.id}/upload
method: 'POST',
body: formData,
});
if (!res.ok) {
const error = await res.json();
throw new Error(error.error || 'Failed to upload document');
}
setShowUploadModal(false);
setUploadedFile(null);
setUploadDescription('');
setUploadPublic(false);
// Refresh documents list
const res2 = await fetch(
if (res2.ok) {
const data = await res2.json();
setDocuments(data.documents || []);
}
} catch (err: any) {
setUploadError(err.message || 'Upload failed');
} finally {
setUploading(false);
}
};
// Fetch public documents for this case
React.useEffect(() => {
const fetchDocuments = async () => {
if (!caseData?.id) return;
try {
const res = await fetch(
if (res.ok) {
const data = await res.json();
setDocuments(data.documents || []);
}
} catch {}
};
fetchDocuments();
}, [caseData?.id, showUploadModal]);
const handleDeleteDocument = async (documentId: string) => {
if (!confirm('Are you sure you want to delete this document?')) return;
try {
const response = await fetch(`/api/cases/${caseData.id}/documents/${documentId}
method: 'DELETE',
});
if (response.ok) {
// Remove from local state
setDocuments(prev => prev.filter(doc => doc.id !== documentId));
alert('Document deleted successfully');
} else {
const error = await response.json();
alert(error.error || 'Failed to delete document');
}
} catch (error) {
alert('Failed to delete document');
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-indigo-50">
{/* Enhanced Hero Section - Inspired by Class Action Page */}
<div className="relative bg-gradient-to-br from-red-600 to-orange-600 text-white">
<div className="absolute inset-0 bg-black/10"></div>
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="flex items-center gap-4 mb-6">
<button
onClick={() => {
if (mode === 'admin') {
router?.push('/admin/case-management');
} else {
router?.back() || window.history.back();
}
}}
className="flex items-center gap-2 text-white/80 hover:text-white transition-colors"
>
<ArrowLeft className="h-5 w-5" />
{mode === 'admin' ? 'Back to Case Management' : 'Back to Cases'}
</button>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 items-start">
<div className="lg:col-span-2">
<div className="flex items-center gap-4 mb-6">
{/* Case Logo */}
<div className="flex-shrink-0 relative group">
{caseData.logoUrl ? (
<img
src={caseData.logoUrl}
alt={`${caseData.title} Logo
className="w-24 h-24 rounded-xl object-contain border-2 border-white/30 shadow-lg"
/>
) : (
<div className="w-24 h-24 rounded-xl bg-gradient-to-br from-white/20 to-white/10 border-2 border-white/30 flex items-center justify-center shadow-lg">
<FileText className="w-12 h-12 text-white" />
</div>
)}
{/* Hover overlay for case creator */}
{isCaseCreator && (
<div className="absolute inset-0 bg-black/50 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex items-center justify-center">
<button
onClick={() => setShowLogoUpload(true)}
className="text-white text-xs font-medium hover:text-red-200 transition-colors"
>
Change Logo
</button>
</div>
)}
</div>
<div className="flex items-center gap-3">
{getStatusIcon(caseData.status)}
<h1 className="text-4xl font-bold drop-shadow-lg">{caseData.title}</h1>
</div>
</div>
<div className="flex flex-wrap items-center gap-4 mb-6">
{caseData.caseNumber && (
<span className="text-red-100 bg-white/20 px-3 py-1 rounded-full text-sm font-medium">
#{caseData.caseNumber}
</span>
)}
<span className={`text-xs px-3 py-1 rounded-full border border-white/30 bg-white/10 ${getPriorityColor(caseData.priority || 'medium')}
{(caseData.priority || 'MEDIUM').toUpperCase()} PRIORITY
</span>
<span className={`text-xs px-3 py-1 rounded-full bg-white/20 ${getStatusColor(caseData.status || 'pending')}
{(caseData.status || 'PENDING').toUpperCase()}
</span>
</div>
<div className="flex flex-wrap items-center gap-6 text-red-100 text-sm">
<div className="flex items-center gap-2">
<MapPin className="h-4 w-4" />
{caseData.jurisdiction}
</div>
<div className="flex items-center gap-2">
<Eye className="h-4 w-4" />
{caseData.views || 0} views
</div>
<div className="flex items-center gap-2">
<Calendar className="h-4 w-4" />
{caseData.createdAt ? format(new Date(caseData.createdAt), 'MMM d, yyyy') : 'Unknown'}
</div>
<div className="flex items-center gap-2">
<Users className="h-4 w-4" />
{caseData._count?.registrations || 0} applications
</div>
</div>
{/* Case Description/Summary */}
{caseData.summary && (
<div className="mt-6 p-4 bg-white/10 rounded-lg border border-white/20">
<p className="text-red-50 leading-relaxed">{caseData.summary}</p>
</div>
)}
</div>
{/* Action Buttons */}
<div className="flex flex-col gap-3">
<div className="flex gap-2">
<EnhancedShareButton
url={typeof window !== 'undefined' ? window.location.href : ''}
title={caseData.title}
description={caseData.summary || caseData.description || ''}
hashtags={caseData.tags || []}
className="flex-1"
/>
<button
onClick={toggleBookmark}
className={
isBookmarked
? 'bg-yellow-500 hover:bg-yellow-600 text-white'
: 'bg-white/20 hover:bg-white/30 text-white'
}
>
<Bookmark className={`h-4 w-4 ${isBookmarked ? 'fill-current' : ''}
</button>
</div>
{/* Call to Action Buttons */}
<div className="flex flex-col gap-3 mt-4">
{caseData.isAcceptingApplications && (
<button
onClick={() => {
if (userApplication) {
router?.push(
} else {
router?.push(
}
}}
className="bg-white text-red-600 rounded-lg font-bold shadow-lg hover:scale-105 transition-all duration-200 px-6 py-3 text-center"
title={buttonTooltip}
>
{userApplication ? 'Continue Application' : 'Apply Now'}
</button>
)}
{mode === 'admin' && (
<div className="flex gap-2">
{onEdit && (
<button
onClick={onEdit}
className="bg-white/20 hover:bg-white/30 text-white rounded-lg transition-colors px-4 py-2 flex items-center gap-2"
>
<Edit className="h-4 w-4" />
Edit
</button>
)}
{onManageTeam && (
<button
onClick={onManageTeam}
className="bg-white/20 hover:bg-white/30 text-white rounded-lg transition-colors px-4 py-2 flex items-center gap-2"
>
<Users className="h-4 w-4" />
Team
</button>
)}
<Link
href={`/cases/${caseData.id}/showcase
className="bg-white/20 hover:bg-white/30 text-white rounded-lg transition-colors px-4 py-2 flex items-center gap-2"
>
<ExternalLink className="h-4 w-4" />
View Showcase
</Link>
</div>
)}
{/* Public Showcase Button */}
<Link
href={`/cases/${caseData.id}/showcase
className="bg-white/20 hover:bg-white/30 text-white rounded-lg transition-colors px-4 py-2 flex items-center gap-2"
>
<ExternalLink className="h-4 w-4" />
View Beautiful Profile
</Link>
</div>
</div>
</div>
</div>
</div>
{/* Enhanced Progress Bar - Inspired by Class Action Page */}
<div className="bg-white border-b border-gray-200 shadow-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div className="flex items-center justify-between mb-3">
<span className="text-sm font-bold text-gray-800">Case Progress</span>
<span className="text-sm font-semibold text-red-600">{getCaseProgress()}% Complete</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-3 shadow-inner">
<div
className="bg-gradient-to-r from-red-500 to-orange-500 h-3 rounded-full transition-all duration-700 ease-out shadow-lg"
style={{ width: `${getCaseProgress()}%
></div>
</div>
<div className="flex justify-between mt-2 text-xs text-gray-500">
<span>Started</span>
<span>In Progress</span>
<span>Completed</span>
</div>
</div>
</div>
{/* Key Statistics Section - Inspired by Class Action Page */}
<div className="bg-white border-b border-gray-200">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div className="bg-gradient-to-br from-red-50 to-orange-50 rounded-xl p-6 border border-red-200 shadow-sm">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-red-600">Total Applications</p>
<p className="text-2xl font-bold text-red-700">{caseData._count?.registrations || 0}</p>
</div>
<div className="w-12 h-12 bg-red-100 rounded-lg flex items-center justify-center">
<Users className="h-6 w-6 text-red-600" />
</div>
</div>
</div>
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl p-6 border border-blue-200 shadow-sm">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-blue-600">Case Views</p>
<p className="text-2xl font-bold text-blue-700">{caseData.views || 0}</p>
</div>
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center">
<Eye className="h-6 w-6 text-blue-600" />
</div>
</div>
</div>
<div className="bg-gradient-to-br from-green-50 to-emerald-50 rounded-xl p-6 border border-green-200 shadow-sm">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-green-600">Priority Level</p>
<p className="text-2xl font-bold text-green-700">{(caseData.priority || 'MEDIUM').toUpperCase()}</p>
</div>
<div className="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center">
<Target className="h-6 w-6 text-green-600" />
</div>
</div>
</div>
<div className="bg-gradient-to-br from-purple-50 to-pink-50 rounded-xl p-6 border border-purple-200 shadow-sm">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-purple-600">Status</p>
<p className="text-2xl font-bold text-purple-700">{(caseData.status || 'PENDING').toUpperCase()}</p>
</div>
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center">
<CheckCircle className="h-6 w-6 text-purple-600" />
</div>
</div>
</div>
</div>
</div>
</div>
{/* Enhanced Quick Navigation - Inspired by Class Action Page */}
<div className="sticky top-16 z-40 bg-white border-b border-gray-200 shadow-lg">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center space-x-6 overflow-x-auto py-4">
<button
onClick={() => document.getElementById('overview')?.scrollIntoView({ behavior: 'smooth' })}
className="flex items-center gap-2 px-4 py-3 text-gray-700 hover:text-red-600 hover:bg-red-50 rounded-lg transition-all duration-200 whitespace-nowrap font-semibold border-b-2 border-transparent hover:border-red-600"
>
<FileText className="h-4 w-4" />
<span className="text-sm">Overview</span>
</button>
<button
onClick={() => document.getElementById('lawyer')?.scrollIntoView({ behavior: 'smooth' })}
className="flex items-center gap-2 px-4 py-3 text-gray-700 hover:text-red-600 hover:bg-red-50 rounded-lg transition-all duration-200 whitespace-nowrap font-semibold border-b-2 border-transparent hover:border-red-600"
>
<User className="h-4 w-4" />
<span className="text-sm">Lead Lawyer</span>
</button>
<button
onClick={() => document.getElementById('updates')?.scrollIntoView({ behavior: 'smooth' })}
className="flex items-center gap-2 px-4 py-3 text-gray-700 hover:text-red-600 hover:bg-red-50 rounded-lg transition-all duration-200 whitespace-nowrap font-semibold border-b-2 border-transparent hover:border-red-600"
>
<Clock className="h-4 w-4" />
<span className="text-sm">Updates</span>
</button>
<button
onClick={() => document.getElementById('documents')?.scrollIntoView({ behavior: 'smooth' })}
className="flex items-center gap-2 px-4 py-3 text-gray-700 hover:text-red-600 hover:bg-red-50 rounded-lg transition-all duration-200 whitespace-nowrap font-semibold border-b-2 border-transparent hover:border-red-600"
>
<FileText className="h-4 w-4" />
<span className="text-sm">Documents</span>
</button>
<button
onClick={() => document.getElementById('comments')?.scrollIntoView({ behavior: 'smooth' })}
className="flex items-center gap-2 px-4 py-3 text-gray-700 hover:text-red-600 hover:bg-red-50 rounded-lg transition-all duration-200 whitespace-nowrap font-semibold border-b-2 border-transparent hover:border-red-600"
>
<MessageCircle className="h-4 w-4" />
<span className="text-sm">Comments & Discussion</span>
</button>
</div>
</div>
</div>
{/* Verification Banner for Unverified Lawyers */}
{isLawyer && !isVerified && (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-6">
<div className="bg-yellow-50 border-l-4 border-yellow-400 p-4 rounded-r-lg">
<div className="flex">
<AlertTriangle className="h-5 w-5 text-yellow-400 mr-3 mt-0.5" />
<div>
<p className="text-sm text-yellow-800">
<strong>Account Not Verified:</strong> You must complete Barreau verification to accept cases, upload files, or message clients. Sensitive actions are disabled until you are verified.
</p>
</div>
</div>
</div>
</div>
)}
{/* Enhanced Smart Application Button */}
{currentUser && (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-6">
<div className="bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl p-6 text-white">
<div className="flex items-center justify-between">
<div>
<h3 className="text-lg font-semibold mb-1">Ready to Apply?</h3>
<p className="text-blue-100 text-sm">Join this case and make a difference</p>
</div>
<div className="flex items-center gap-3">
{checkingApplication ? (
<button className="px-6 py-3 rounded-lg bg-white/20 text-white flex items-center" disabled>
<svg className="animate-spin h-5 w-5 mr-2" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" /><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z" /></svg>
Checking...
</button>
) : !caseData.isAcceptingApplications ? (
<button className="px-6 py-3 rounded-lg bg-white/20 text-white cursor-not-allowed" disabled title={buttonTooltip}>
<Plus className="h-4 w-4 mr-2 inline" /> Apply Now
</button>
) : userApplication ? (
userApplication.status === 'PENDING' ? (
<Link href={`/user/registrations/${userApplication.id}
<Pencil className="h-4 w-4 mr-2" /> Continue My Application
</Link>
) : (
<Link href={`/user/registrations/${userApplication.id}
<Eye className="h-4 w-4 mr-2" /> View My Application
</Link>
)
) : (
<Link href={`/user/registrations/new?caseId=${caseData.id}
<Plus className="h-4 w-4 mr-2" /> Apply Now
</Link>
)}
</div>
</div>
</div>
</div>
)}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Main Content */}
<div className="lg:col-span-2 space-y-6">
{/* Case Description */}
<div id="overview" className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
<FileText className="h-5 w-5 text-blue-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900">Case Overview</h2>
</div>
<p className="text-gray-700 leading-relaxed text-lg mb-6">{caseData.description}</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-4">
<div className="flex items-center gap-3">
<Scale className="h-5 w-5 text-blue-600" />
<div>
<span className="font-medium text-gray-900">Case Type:</span>
<span className="ml-2 text-gray-600 capitalize">{caseData.caseType.replace('_', ' ')}</span>
</div>
</div>
{caseData.court && (
<div className="flex items-center gap-3">
<Building className="h-5 w-5 text-blue-600" />
<div>
<span className="font-medium text-gray-900">Court:</span>
<span className="ml-2 text-gray-600">{caseData.court}</span>
</div>
</div>
)}
</div>
<div className="space-y-4">
{caseData.budget && (
<div className="flex items-center gap-3">
<DollarSign className="h-5 w-5 text-green-600" />
<div>
<span className="font-medium text-gray-900">Budget:</span>
<span className="ml-2 text-gray-600">${caseData.budget.toLocaleString()} CAD</span>
</div>
</div>
)}
{caseData.applicationDeadline && (
<div className="flex items-center gap-3">
<Calendar className="h-5 w-5 text-orange-600" />
<div>
<span className="font-medium text-gray-900">Deadline:</span>
<span className="ml-2 text-gray-600">
{format(new Date(caseData.applicationDeadline), 'PPP')}
</span>
</div>
</div>
)}
</div>
</div>
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="flex items-center p-3 bg-gray-50 rounded-lg">
<CheckCircle className={`h-5 w-5 mr-3 ${caseData.isAcceptingApplications ? 'text-green-500' : 'text-gray-400'}
<span className="text-sm text-gray-700">
{caseData.isAcceptingApplications ? 'Accepting Applications' : 'Not Accepting Applications'}
</span>
</div>
<div className="flex items-center p-3 bg-gray-50 rounded-lg">
<CheckCircle className={`h-5 w-5 mr-3 ${caseData.requiresApproval ? 'text-blue-500' : 'text-gray-400'}
<span className="text-sm text-gray-700">
{caseData.requiresApproval ? 'Requires Approval' : 'Auto-Approval'}
</span>
</div>
</div>
</div>
{/* Lead Lawyer */}
<div id="lawyer" className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center">
<User className="h-5 w-5 text-purple-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900">Lead Lawyer</h2>
</div>
<div className="flex items-start gap-6">
<div className="flex-shrink-0">
{caseData.leadLawyer?.profilePicture ? (
<img
src={caseData.leadLawyer.profilePicture}
alt={caseData.leadLawyer.name}
className="h-20 w-20 rounded-full object-cover border-4 border-purple-100"
/>
) : (
<div className="h-20 w-20 rounded-full bg-gradient-to-br from-purple-500 to-blue-600 flex items-center justify-center text-white text-2xl font-bold border-4 border-purple-100">
{caseData.leadLawyer?.name?.charAt(0)}
</div>
)}
</div>
<div className="flex-1">
<div className="flex items-center gap-3 mb-3">
<h3 className="text-xl font-bold text-gray-900">{caseData.leadLawyer?.name}</h3>
{caseData.leadLawyer?.isVerified && (
<div className="flex items-center gap-1 px-2 py-1 bg-blue-100 text-blue-800 rounded-full text-xs font-medium">
<Badge className="h-3 w-3" />
Verified
</div>
)}
{caseData.leadLawyer?.proBono && (
<span className="px-3 py-1 text-xs bg-green-100 text-green-800 rounded-full font-medium">
Pro Bono
</span>
)}
</div>
{caseData.leadLawyer?.title && (
<p className="text-lg text-gray-600 mb-2">{caseData.leadLawyer.title}</p>
)}
{caseData.leadLawyer?.specialization && (
<p className="text-gray-600 mb-3">{caseData.leadLawyer.specialization}</p>
)}
<LawyerRatingStars
rating={caseData.leadLawyer?.averageRating}
size="md"
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Success Rate:</span>
<span className="font-semibold text-gray-900">
{caseData.leadLawyer?.wonCases}/{caseData.leadLawyer?.totalCases} cases won
</span>
</div>
{caseData.leadLawyer?.hourlyRate && (
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Rate:</span>
<span className="font-semibold text-gray-900">${caseData.leadLawyer.hourlyRate}/hr</span>
</div>
)}
</div>
<div className="space-y-2">
{caseData.leadLawyer?.yearsOfExperience && (
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Experience:</span>
<span className="font-semibold text-gray-900">{caseData.leadLawyer.yearsOfExperience} years</span>
</div>
)}
{caseData.leadLawyer?.officeLocation && (
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Location:</span>
<span className="font-semibold text-gray-900 flex items-center gap-1">
<MapPin className="h-3 w-3" />
{caseData.leadLawyer.officeLocation}
</span>
</div>
)}
</div>
</div>
{caseData.leadLawyer?.bio && (
<p className="text-gray-700 mt-4 leading-relaxed">
{caseData.leadLawyer.bio}
</p>
)}
</div>
</div>
</div>
{/* Case Timeline */}
<CaseTimeline caseData={caseData} />
{/* Required Documents */}
{getRequiredDocuments().length > 0 && (
<div id="documents" className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center">
<FileText className="h-5 w-5 text-green-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900">Required Documents</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{getRequiredDocuments().map((doc: string, index: number) => (
<div key={index} className="flex items-center p-3 bg-gray-50 rounded-lg">
<CheckCircle className="h-5 w-5 text-green-500 mr-3" />
<span className="text-gray-700 font-medium">{doc}</span>
</div>
))}
</div>
</div>
)}
{/* Recent Updates */}
<div id="updates" className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-orange-100 rounded-lg flex items-center justify-center">
<Clock className="h-5 w-5 text-orange-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900">Recent Updates</h2>
</div>
{caseData.caseUpdates?.length === 0 ? (
<div className="text-center py-8">
<Clock className="h-12 w-12 text-gray-300 mx-auto mb-4" />
<p className="text-gray-500">No updates yet</p>
</div>
) : (
<div className="space-y-4">
{caseData.caseUpdates?.slice(0, 5).map((update: any) => (
<div key={update.id} className="border-l-4 border-blue-200 pl-6 py-4 hover:bg-gray-50 rounded-r-lg transition-colors">
<div className="flex items-center justify-between mb-2">
<h3 className="font-semibold text-gray-900">{update.title}</h3>
<span className="text-sm text-gray-500 bg-gray-100 px-2 py-1 rounded-full">
{format(new Date(update.createdAt), 'MMM d, yyyy')}
</span>
</div>
{update.description && (
<p className="text-gray-600 mb-2">{update.description}</p>
)}
<div className="flex items-center text-sm text-gray-500">
<User className="h-4 w-4 mr-1" />
{update.author?.name}
<span className="mx-2">•</span>
<span className="capitalize">{update.updateType}</span>
{update.isPublic && (
<>
<span className="mx-2">•</span>
<span className="text-green-600 font-medium">Public</span>
</>
)}
</div>
</div>
))}
</div>
)}
</div>
{/* Comments Section */}
<div id="comments" className="bg-white rounded-xl shadow-sm border border-gray-200 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-indigo-100 rounded-lg flex items-center justify-center">
<MessageSquare className="h-5 w-5 text-indigo-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900">Comments & Discussion</h2>
</div>
<EnhancedComments
caseId={caseData.id}
mode={mode}
allowAttachments={true}
allowReactions={true}
allowReplies={true}
apiEndpoint={`/api/live-cases/${caseData.id}/comments
/>
</div>
</div>
{/* Enhanced Sidebar */}
<div className="space-y-6">
{/* Quick Stats */}
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center">
<TrendingUp className="h-4 w-4 text-blue-600" />
</div>
<h3 className="text-lg font-bold text-gray-900">Quick Stats</h3>
</div>
<div className="space-y-4">
<div className="flex items-center justify-between p-3 bg-blue-50 rounded-lg">
<div className="flex items-center">
<Users className="h-5 w-5 text-blue-600 mr-3" />
<span className="text-sm font-medium text-gray-700">Applications</span>
</div>
<span className="font-bold text-blue-600 text-lg">{caseData._count?.registrations || 0}</span>
</div>
<div className="flex items-center justify-between p-3 bg-red-50 rounded-lg">
<div className="flex items-center">
<Heart className="h-5 w-5 text-red-600 mr-3" />
<span className="text-sm font-medium text-gray-700">Supporters</span>
</div>
<span className="font-bold text-red-600 text-lg">{caseData._count?.supporters || 0}</span>
</div>
<div className="flex items-center justify-between p-3 bg-green-50 rounded-lg">
<div className="flex items-center">
<DollarSign className="h-5 w-5 text-green-600 mr-3" />
<span className="text-sm font-medium text-gray-700">Offers</span>
</div>
<span className="font-bold text-green-600 text-lg">{caseData._count?.offers || 0}</span>
</div>
<div className="flex items-center justify-between p-3 bg-purple-50 rounded-lg">
<div className="flex items-center">
<MessageSquare className="h-5 w-5 text-purple-600 mr-3" />
<span className="text-sm font-medium text-gray-700">Comments</span>
</div>
<span className="font-bold text-purple-600 text-lg">{caseData._count?.comments || 0}</span>
</div>
</div>
</div>
{/* Admin Tools */}
{mode === 'admin' && (
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-yellow-100 rounded-lg flex items-center justify-center">
<Shield className="h-4 w-4 text-yellow-600" />
</div>
<h3 className="text-lg font-bold text-gray-900">Admin Tools</h3>
</div>
<div className="space-y-3">
<button
onClick={onEdit}
className="w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
<Edit className="h-4 w-4 mr-2" />
Edit Case
</button>
<button
onClick={onViewApplications}
className="w-full flex items-center justify-center px-4 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors font-medium"
>
<Users className="h-4 w-4 mr-2" />
View Applications
</button>
<button
onClick={onManageTeam}
className="w-full flex items-center justify-center px-4 py-3 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors font-medium"
>
<Target className="h-4 w-4 mr-2" />
Manage Team
</button>
</div>
</div>
)}
{/* Owner Tools for Public Mode */}
{mode === 'public' && currentUser && caseData.creator?.id === currentUser.id && (
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-orange-100 rounded-lg flex items-center justify-center">
<Trophy className="h-4 w-4 text-orange-600" />
</div>
<h3 className="text-lg font-bold text-gray-900">Your Case Tools</h3>
</div>
<div className="space-y-3">
<button
onClick={onEdit}
className="w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
<Edit className="h-4 w-4 mr-2" />
Edit Case
</button>
<button
onClick={handleDelete}
className="w-full flex items-center justify-center px-4 py-3 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors font-medium"
>
<Trash className="h-4 w-4 mr-2" />
Delete Case
</button>
</div>
</div>
)}
{/* Case Information */}
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-gray-100 rounded-lg flex items-center justify-center">
<Globe className="h-4 w-4 text-gray-600" />
</div>
<h3 className="text-lg font-bold text-gray-900">Case Information</h3>
</div>
<div className="space-y-4 text-sm">
<div className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="font-medium text-gray-700">Created:</span>
<span className="text-gray-600">
{format(new Date(caseData.createdAt), 'MMM d, yyyy')}
</span>
</div>
<div className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="font-medium text-gray-700">Last Updated:</span>
<span className="text-gray-600">
{format(new Date(caseData.updatedAt), 'MMM d, yyyy')}
</span>
</div>
<div className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="font-medium text-gray-700">Created By:</span>
<span className="text-gray-600">{caseData.creator?.name}</span>
</div>
{caseData.firmName && (
<div className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="font-medium text-gray-700">Firm:</span>
<span className="text-gray-600">{caseData.firmName}</span>
</div>
)}
{caseData.expectedDuration && (
<div className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="font-medium text-gray-700">Expected Duration:</span>
<span className="text-gray-600">{caseData.expectedDuration} days</span>
</div>
)}
{caseData.filingDate && (
<div className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="font-medium text-gray-700">Filing Date:</span>
<span className="text-gray-600">
{format(new Date(caseData.filingDate), 'MMM d, yyyy')}
</span>
</div>
)}
</div>
</div>
</div>
</div>
</div>
{/* Live Case Chat - Only show in public mode */}
{mode === 'public' && currentUser && (
<LiveCaseChat
caseId={caseData.id}
caseTitle={caseData.title}
caseOwner={{
id: caseData.creator?.id || '',
name: caseData.creator?.name || 'Unknown',
avatar: caseData.creator?.image,
role: caseData.creator?.role || 'USER'
}}
/>
)}
{/* Logo Upload Modal */}
{showLogoUpload && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-xl p-6 max-w-md w-full mx-4">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900">Change Case Logo</h3>
<button
onClick={() => {
setShowLogoUpload(false);
setLogoFile(null);
setLogoPreview(null);
}}
className="text-gray-400 hover:text-gray-600"
>
<XCircle className="h-5 w-5" />
</button>
</div>
<div className="space-y-4">
{/* Logo Preview */}
<div className="flex justify-center">
{logoPreview ? (
<img
src={logoPreview}
alt="Logo Preview"
className="w-24 h-24 rounded-lg object-cover border-2 border-gray-200"
/>
) : (
<div className="w-24 h-24 rounded-lg bg-gray-100 border-2 border-dashed border-gray-300 flex items-center justify-center">
<FileText className="w-8 h-8 text-gray-400" />
</div>
)}
</div>
{/* File Input */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Select New Logo
</label>
<input
type="file"
accept="image/*"
onChange={handleLogoChange}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<p className="text-xs text-gray-500 mt-1">
Supported formats: JPG, PNG, GIF. Max size: 5MB
</p>
</div>
{/* Action Buttons */}
<div className="flex gap-3 pt-4">
<button
onClick={() => {
setShowLogoUpload(false);
setLogoFile(null);
setLogoPreview(null);
}}
className="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
>
Cancel
</button>
<button
onClick={handleLogoUpload}
disabled={!logoFile || isUploadingLogo}
className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center"
>
{isUploadingLogo ? (
<>
<svg className="animate-spin h-4 w-4 mr-2" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z" />
</svg>
Uploading...
</>
) : (
'Update Logo'
)}
</button>
</div>
</div>
</div>
</div>
)}
{/* Document Upload Modal */}
{showUploadModal && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-40">
<form
className="bg-white rounded-lg shadow-lg p-6 w-full max-w-md flex flex-col gap-4"
onSubmit={handleDocumentUpload}
>
<h3 className="text-lg font-bold mb-2">Upload Document</h3>
<input
type="file"
accept=".pdf,.doc,.docx,.txt,.jpg,.jpeg,.png,.mp3,.mp4,.wav,.avi,.mov,.mkv"
ref={fileInputRef}
onChange={e => setUploadedFile(e.target.files?.[0] || null)}
required
className="border rounded px-3 py-2"
/>
<textarea
placeholder="Description (optional)"
value={uploadDescription}
onChange={e => setUploadDescription(e.target.value)}
className="border rounded px-3 py-2"
/>
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={uploadPublic}
onChange={e => setUploadPublic(e.target.checked)}
/>
<span>Make this document public</span>
</label>
{uploadError && <div className="text-red-600 text-sm">{uploadError}</div>}
<div className="flex gap-2 mt-2">
<button
type="submit"
disabled={uploading}
className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded font-semibold"
>
{uploading ? 'Uploading...' : 'Upload'}
</button>
<button
type="button"
onClick={() => setShowUploadModal(false)}
className="bg-gray-200 hover:bg-gray-300 text-gray-700 px-4 py-2 rounded font-semibold"
>
Cancel
</button>
</div>
</form>
</div>
)}
{/* Public Document List */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold text-gray-800 flex items-center gap-2">
<FileText className="h-6 w-6 text-blue-600" /> Documents
</h2>
{currentUser && (
<button
onClick={() => setShowUploadModal(true)}
className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-semibold shadow"
>
Upload Document
</button>
)}
</div>
{documents.length === 0 ? (
<div className="text-gray-500">No public documents yet.</div>
) : (
<div className="space-y-6">
{/* Group by uploader, creator on top */}
{Object.entries(
documents.reduce((acc, doc) => {
const key = doc.user?.id || 'unknown';
if (!acc[key]) acc[key] = [];
acc[key].push(doc);
return acc;
}, {} as Record<string, Document[]>) as Record<string, Document[]>
).sort(([a], [b]) => (a === caseData.createdBy ? -1 : b === caseData.createdBy ? 1 : 0)).map(([userId, docs]) => (
<div key={userId} className="border rounded-lg p-4 bg-white/80">
<div className="font-semibold text-blue-700 mb-2 flex items-center gap-2">
{(docs as Document[]).length > 0 && (docs as Document[])[0]?.user?.profilePicture && (
<img src={(docs as Document[])[0]?.user?.profilePicture} alt={(docs as Document[])[0]?.user?.name} className="w-7 h-7 rounded-full object-cover" />
)}
{(docs as Document[]).length > 0 ? ((docs as Document[])[0]?.user?.name || 'Unknown User') : 'Unknown User'}
{userId === caseData.createdBy && <span className="ml-2 px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs">Creator</span>}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{(docs as Document[]).map((doc: Document) => (
<div key={doc.id} className="border rounded p-3 bg-white flex flex-col gap-2 shadow-sm">
<div className="flex items-center gap-2">
{/* File type icon */}
{doc.type?.includes('pdf') ? <FileText className="h-5 w-5 text-red-600" /> :
doc.type?.includes('image') ? <img src={doc.url} alt={doc.name} className="h-8 w-8 object-cover rounded" /> :
doc.type?.includes('audio') ? <span className="inline-block bg-blue-100 text-blue-700 rounded px-2 py-1 text-xs">AUDIO</span> :
doc.type?.includes('video') ? <span className="inline-block bg-purple-100 text-purple-700 rounded px-2 py-1 text-xs">VIDEO</span> :
<FileText className="h-5 w-5 text-gray-400" />}
<span className="font-medium text-gray-800 truncate" title={doc.name}>{doc.name}</span>
</div>
{doc.description && <div className="text-xs text-gray-600">{doc.description}</div>}
<div className="flex items-center gap-2 text-xs text-gray-500">
<span>{doc.type}</span>
<span>{(doc.fileSize / 1024).toFixed(1)} KB</span>
<span>{doc.createdAt ? format(new Date(doc.createdAt), 'MMM d, yyyy') : ''}</span>
</div>
<div className="flex items-center gap-2">
<a
href={doc.url}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline text-sm font-semibold"
>
View / Download
</a>
{(currentUser?.id === doc.userId || currentUser?.role === 'ADMIN' || currentUser?.role === 'SUPERADMIN') && (
<button
onClick={() => handleDeleteDocument(doc.id)}
className="text-red-600 hover:text-red-800 text-sm font-semibold"
title="Delete document"
>
Delete
</button>
)}
</div>
</div>
))}
</div>
</div>
))}
</div>
)}
</div>
</div>
);
};
export default CaseDetail;