T.ME/BIBIL_0DAY
CasperSecurity


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.ca/private_html/src/pages/client/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/pages/client/dashboard_backup.tsx
'use client';

import React, { useState, useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import { isSuperAdmin } from '@/lib/auth-utils';
import { 
  FileText, 
  DollarSign, 
  MessageSquare, 
  Calendar, 
  AlertCircle, 
  CheckCircle, 
  Clock, 
  Download,
  Upload,
  Eye,
  Edit,
  Send,
  Bell,
  Settings,
  User,
  Shield,
  TrendingUp,
  Activity,
  Folder,
  Phone,
  Mail,
  Video,
  MapPin,
  Star,
  MoreVertical,
  Plus,
  Trash2
} from 'lucide-react';
import { format } from 'date-fns';
import CaseWidget from '@/components/CaseWidget';
import LayoutWithSidebar from '../../components/LayoutWithSidebar';

// Utility functions
const getStatusColor = (status: string) => {
  switch (status.toLowerCase()) {
    case 'active': return 'text-green-600 bg-green-100';
    case 'pending': return 'text-yellow-600 bg-yellow-100';
    case 'completed': return 'text-blue-600 bg-blue-100';
    case 'cancelled': return 'text-red-600 bg-red-100';
    default: return 'text-gray-600 bg-gray-100';
  }
};

const getPriorityColor = (priority: string) => {
  switch (priority.toLowerCase()) {
    case 'high': return 'text-red-600 bg-red-100';
    case 'medium': return 'text-yellow-600 bg-yellow-100';
    case 'low': return 'text-green-600 bg-green-100';
    default: return 'text-gray-600 bg-gray-100';
  }
};

interface Case {
  id: string;
  caseNumber: string;
  title: string;
  status: string;
  priority: string;
  createdAt: string;
  updatedAt: string;
  description?: string;
  lawyer: {
    id: string;
    name: string;
    email: string;
    profile?: {
      phone?: string;
      avatar?: string;
    };
  };
  documents: Document[];
  payments: Payment[];
  updates: CaseUpdate[];
}

interface Document {
  id: string;
  title: string;
  type: string;
  filePath: string;
  fileSize: number;
  uploadedAt: string;
  uploadedBy: string;
  status: string;
}

interface Payment {
  id: string;
  amount: number;
  status: string;
  dueDate: string;
  paidAt?: string;
  description: string;
  type: string;
}

interface CaseUpdate {
  id: string;
  title: string;
  content: string;
  type: string;
  createdAt: string;
  createdBy: string;
}

interface Message {
  id: string;
  content: string;
  senderId: string;
  senderName: string;
  timestamp: string;
  isRead: boolean;
}

const ClientDashboard: React.FC = () => {
  const { data: session, status } = useSession();
  const router = useRouter();
  const [cases, setCases] = useState<Case[]>([]);
  const [selectedCase, setSelectedCase] = useState<Case | null>(null);
  const [messages, setMessages] = useState<Message[]>([]);
  const [loading, setLoading] = useState(true);
  const [activeTab, setActiveTab] = useState<'overview' | 'cases' | 'documents' | 'payments' | 'messages' | 'applications'>('overview');
  const [showUploadModal, setShowUploadModal] = useState(false);
  const [showMessageModal, setShowMessageModal] = useState(false);

  useEffect(() => {
    if (status === 'loading') return;
    
    if (!session?.user) {
      router.push('/auth/login');
      return;
    }

    // Check if user is a client, user, or super admin
    if (!['CLIENT', 'USER'].includes(session.user.role) && !isSuperAdmin(session)) {
      router.push('/dashboard');
      return;
    }

    fetchClientData();
  }, [session, status]);

  const fetchClientData = async () => {
    try {
      setLoading(true);
      
      // Fetch cases
      const casesResponse = await fetch('/api/client/cases');
      if (casesResponse.ok) {
        const casesData = await casesResponse.json();
        setCases(casesData.cases || []);
        if (casesData.cases?.length > 0) {
          setSelectedCase(casesData.cases[0]);
        }
      }

      // Fetch messages
      const messagesResponse = await fetch('/api/client/messages');
      if (messagesResponse.ok) {
        const messagesData = await messagesResponse.json();
        setMessages(messagesData.messages || []);
      }
    } catch (error) {
      console.error('Error fetching client data:', error);
    } finally {
      setLoading(false);
    }
  };

  const handleDocumentUpload = async (file: File, caseId: string) => {
    try {
      const formData = new FormData();
      formData.append('file', file);
      formData.append('caseId', caseId);
      formData.append('title', file.name);

      const response = await fetch('/api/client/documents/upload', {
        method: 'POST',
        body: formData
      });

      if (response.ok) {
        fetchClientData();
        setShowUploadModal(false);
      }
    } catch (error) {
      console.error('Error uploading document:', error);
    }
  };

  const handleSendMessage = async (content: string, recipientId: string) => {
    try {
      const response = await fetch('/api/client/messages', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          content,
          recipientId,
          caseId: selectedCase?.id
        })
      });

      if (response.ok) {
        fetchClientData();
        setShowMessageModal(false);
      }
    } catch (error) {
      console.error('Error sending message:', error);
    }
  };

  if (loading) {
    return (
      <LayoutWithSidebar>
        <div className="min-h-screen bg-gray-50 flex items-center justify-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
        </div>
      </LayoutWithSidebar>
    );
  }

  return (
    <LayoutWithSidebar>
      <div className="min-h-screen bg-gray-50 p-6">
        <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
          {/* Header */}
          <div className="mb-8">
            <div className="flex items-center justify-between">
              <div>
                <h1 className="text-3xl font-bold text-gray-900">Client Dashboard</h1>
                <p className="text-gray-600 mt-2">Welcome back, {session?.user?.name}</p>
              </div>
              
              <div className="flex items-center gap-4">
                <button className="p-2 text-gray-600 hover:bg-gray-100 rounded-full">
                  <Bell className="w-5 h-5" />
                </button>
                <button className="p-2 text-gray-600 hover:bg-gray-100 rounded-full">
                  <Settings className="w-5 h-5" />
                </button>
              </div>
            </div>
          </div>

          {/* Quick Stats */}
          <div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
              <div className="flex items-center">
                <div className="p-2 bg-blue-100 rounded-lg">
                  <FileText className="w-6 h-6 text-blue-600" />
                </div>
                <div className="ml-4">
                  <p className="text-sm font-medium text-gray-600">Active Cases</p>
                  <p className="text-2xl font-bold text-gray-900">{cases.filter(c => c.status === 'ACTIVE').length}</p>
                </div>
              </div>
            </div>

            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
              <div className="flex items-center">
                <div className="p-2 bg-green-100 rounded-lg">
                  <DollarSign className="w-6 h-6 text-green-600" />
                </div>
                <div className="ml-4">
                  <p className="text-sm font-medium text-gray-600">Total Paid</p>
                  <p className="text-2xl font-bold text-gray-900">
                    ${cases.reduce((total, c) => 
                      total + (c.payments ? c.payments.filter(p => p.status === 'PAID').reduce((sum, p) => sum + p.amount, 0) : 0), 0
                    ).toLocaleString()}
                  </p>
                </div>
              </div>
            </div>

            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
              <div className="flex items-center">
                <div className="p-2 bg-yellow-100 rounded-lg">
                  <Clock className="w-6 h-6 text-yellow-600" />
                </div>
                <div className="ml-4">
                  <p className="text-sm font-medium text-gray-600">Pending Payments</p>
                  <p className="text-2xl font-bold text-gray-900">
                    ${cases.reduce((total, c) => 
                      total + c.payments.filter(p => p.status === 'PENDING').reduce((sum, p) => sum + p.amount, 0), 0
                    ).toLocaleString()}
                  </p>
                </div>
              </div>
            </div>

            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
              <div className="flex items-center">
                <div className="p-2 bg-purple-100 rounded-lg">
                  <MessageSquare className="w-6 h-6 text-purple-600" />
                </div>
                <div className="ml-4">
                  <p className="text-sm font-medium text-gray-600">Unread Messages</p>
                  <p className="text-2xl font-bold text-gray-900">{messages.filter(m => !m.isRead).length}</p>
                </div>
              </div>
            </div>
          </div>

          {/* Quick Actions */}
          <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
            <h2 className="text-xl font-semibold text-gray-900 mb-4">Quick Actions</h2>
            <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
              <button
                onClick={() => router.push('/admin/cases')}
                className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
              >
                <FileText className="h-6 w-6 text-blue-600 mr-3" />
                <div className="text-left">
                  <div className="font-medium text-gray-900">Case Management</div>
                  <div className="text-sm text-gray-500">View all cases</div>
                </div>
              </button>
              <button
                onClick={() => router.push('/hire/new-case')}
                className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
              >
                <Plus className="h-6 w-6 text-green-600 mr-3" />
                <div className="text-left">
                  <div className="font-medium text-gray-900">Create New Case</div>
                  <div className="text-sm text-gray-500">Start legal process</div>
                </div>
              </button>
              <button
                onClick={() => router.push('/messages')}
                className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
              >
                <MessageSquare className="h-6 w-6 text-purple-600 mr-3" />
                <div className="text-left">
                  <div className="font-medium text-gray-900">Messages</div>
                  <div className="text-sm text-gray-500">View communications</div>
                </div>
              </button>
            </div>
          </div>

          {/* Main Content */}
          <div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
            {/* Sidebar */}
            <div className="lg:col-span-1">
              <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
                <h3 className="text-lg font-semibold text-gray-900 mb-4">Navigation</h3>
                
                <nav className="space-y-2">
                  <button
                    onClick={() => setActiveTab('overview')}
                    className={`w-full flex items-center px-3 py-2 rounded-md text-sm font-medium ${
                      activeTab === 'overview'
                        ? 'bg-blue-100 text-blue-700'
                        : 'text-gray-600 hover:bg-gray-50'
                    }`}
                  >
                    <Activity className="w-4 h-4 mr-3" />
                    Overview
                  </button>
                  
                  <button
                    onClick={() => setActiveTab('cases')}
                    className={`w-full flex items-center px-3 py-2 rounded-md text-sm font-medium ${
                      activeTab === 'cases'
                        ? 'bg-blue-100 text-blue-700'
                        : 'text-gray-600 hover:bg-gray-50'
                    }`}
                  >
                    <FileText className="w-4 h-4 mr-3" />
                    My Cases
                  </button>
                  
                  <button
                    onClick={() => setActiveTab('documents')}
                    className={`w-full flex items-center px-3 py-2 rounded-md text-sm font-medium ${
                      activeTab === 'documents'
                        ? 'bg-blue-100 text-blue-700'
                        : 'text-gray-600 hover:bg-gray-50'
                    }`}
                  >
                    <Folder className="w-4 h-4 mr-3" />
                    Documents
                  </button>
                  
                  <button
                    onClick={() => setActiveTab('payments')}
                    className={`w-full flex items-center px-3 py-2 rounded-md text-sm font-medium ${
                      activeTab === 'payments'
                        ? 'bg-blue-100 text-blue-700'
                        : 'text-gray-600 hover:bg-gray-50'
                    }`}
                  >
                    <DollarSign className="w-4 h-4 mr-3" />
                    Payments
                  </button>
                  
                  <button
                    onClick={() => setActiveTab('messages')}
                    className={`w-full flex items-center px-3 py-2 rounded-md text-sm font-medium ${
                      activeTab === 'messages'
                        ? 'bg-blue-100 text-blue-700'
                        : 'text-gray-600 hover:bg-gray-50'
                    }`}
                  >
                    <MessageSquare className="w-4 h-4 mr-3" />
                    Messages
                  </button>
                  
                  <button
                    onClick={() => setActiveTab('applications')}
                    className={`w-full flex items-center px-3 py-2 rounded-md text-sm font-medium ${
                      activeTab === 'applications'
                        ? 'bg-blue-100 text-blue-700'
                        : 'text-gray-600 hover:bg-gray-50'
                    }`}
                  >
                    <FileText className="w-4 h-4 mr-3" />
                    Applications
                  </button>
                </nav>

                {/* Lawyer Contact */}
                {selectedCase && (
                  <div className="mt-8 pt-6 border-t border-gray-200">
                    <h4 className="text-sm font-medium text-gray-900 mb-3">Your Lawyer</h4>
                    <div className="flex items-center space-x-3">
                      <div className="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center">
                        <User className="w-5 h-5 text-blue-600" />
                      </div>
                      <div>
                        <p className="text-sm font-medium text-gray-900">
                          {selectedCase.lawyer.name}
                        </p>
                        <p className="text-xs text-gray-500">{selectedCase.lawyer.email}</p>
                      </div>
                    </div>
                    
                    <div className="mt-3 space-y-2">
                      <button className="w-full flex items-center justify-center px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-md">
                        <Phone className="w-4 h-4 mr-2" />
                        Call
                      </button>
                      <button className="w-full flex items-center justify-center px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-md">
                        <Mail className="w-4 h-4 mr-2" />
                        Email
                      </button>
                      <button className="w-full flex items-center justify-center px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-md">
                        <Video className="w-4 h-4 mr-2" />
                        Video Call
                      </button>
                    </div>
                  </div>
                )}
              </div>
            </div>

            {/* Main Content Area */}
            <div className="lg:col-span-3">
              {activeTab === 'overview' && (
                <OverviewTab cases={cases} selectedCase={selectedCase} />
              )}
              
              {activeTab === 'cases' && (
                <CasesTab 
                  cases={cases} 
                  selectedCase={selectedCase} 
                  onSelectCase={setSelectedCase} 
                />
              )}
              
              {activeTab === 'documents' && (
                <DocumentsTab 
                  cases={cases} 
                  selectedCase={selectedCase}
                  onUpload={() => setShowUploadModal(true)}
                />
              )}
              
              {activeTab === 'payments' && (
                <PaymentsTab cases={cases} selectedCase={selectedCase} />
              )}
              
              {activeTab === 'messages' && (
                <MessagesTab 
                  messages={messages}
                  selectedCase={selectedCase}
                  onSendMessage={() => setShowMessageModal(true)}
                />
              )}
              
              {activeTab === 'applications' && (
                <ApplicationsTab />
              )}
            </div>
          </div>
        </div>

        {/* Upload Modal */}
        {showUploadModal && (
          <UploadModal
            onUpload={handleDocumentUpload}
            onClose={() => setShowUploadModal(false)}
            caseId={selectedCase?.id}
          />
        )}

        {/* Message Modal */}
        {showMessageModal && (
          <MessageModal
            onSend={handleSendMessage}
            onClose={() => setShowMessageModal(false)}
            recipientId={selectedCase?.lawyer.id}
          />
        )}
      </div>
    </LayoutWithSidebar>
  );
};

// Tab Components
const OverviewTab: React.FC<{ cases: Case[], selectedCase: Case | null }> = ({ cases, selectedCase }) => (
  <div className="space-y-6">
    {/* Welcome Section */}
    <div className="bg-gradient-to-r from-blue-600 to-blue-700 rounded-lg shadow-sm p-6 text-white">
      <h2 className="text-2xl font-bold mb-2">Welcome to Your Legal Dashboard</h2>
      <p className="text-blue-100">
        Manage your cases, track progress, and stay connected with your legal team.
      </p>
    </div>

    {/* Unified Case Management Widget */}
    <CaseWidget
      title="My Cases"
      showMyCases={true}
      showAssignedCases={false}
      showPublicCases={false}
      maxCases={5}
      showCreateButton={true}
      showFilters={true}
      className="mb-6"
    />

    {/* Recent Activity */}
    <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
      <h2 className="text-xl font-semibold text-gray-900 mb-4">Recent Activity</h2>
      
      {selectedCase?.updates.slice(0, 5).map((update) => (
        <div key={update.id} className="flex items-start space-x-3 py-3 border-b border-gray-100 last:border-b-0">
          <div className="w-2 h-2 bg-blue-500 rounded-full mt-2"></div>
          <div className="flex-1">
            <p className="text-sm font-medium text-gray-900">{update.title}</p>
            <p className="text-sm text-gray-600">{update.content}</p>
            <p className="text-xs text-gray-500 mt-1">
              {format(new Date(update.createdAt), 'MMM dd, yyyy')}
            </p>
          </div>
        </div>
      ))}
    </div>

    <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <h3 className="text-lg font-semibold text-gray-900 mb-4">Upcoming Deadlines</h3>
        <div className="space-y-3">
          {cases.flatMap(c => c.documents)
            .filter(d => d.status === 'PENDING')
            .slice(0, 3)
            .map((doc) => (
              <div key={doc.id} className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-gray-900">{doc.title}</p>
                  <p className="text-xs text-gray-500">{doc.type}</p>
                </div>
                <span className="text-xs text-red-600 bg-red-100 px-2 py-1 rounded-full">
                  Due Soon
                </span>
              </div>
            ))}
        </div>
      </div>

      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <h3 className="text-lg font-semibold text-gray-900 mb-4">Recent Documents</h3>
        <div className="space-y-3">
          {cases.flatMap(c => c.documents)
            .sort((a, b) => new Date(b.uploadedAt).getTime() - new Date(a.uploadedAt).getTime())
            .slice(0, 3)
            .map((doc) => (
              <div key={doc.id} className="flex items-center justify-between">
                <div className="flex items-center space-x-3">
                  <FileText className="w-4 h-4 text-gray-400" />
                  <div>
                    <p className="text-sm font-medium text-gray-900">{doc.title}</p>
                    <p className="text-xs text-gray-500">
                      {format(new Date(doc.uploadedAt), 'MMM dd, yyyy')}
                    </p>
                  </div>
                </div>
                <button className="text-blue-600 hover:text-blue-700">
                  <Download className="w-4 h-4" />
                </button>
              </div>
            ))}
        </div>
      </div>
    </div>
  </div>
);

const CasesTab: React.FC<{ 
  cases: Case[], 
  selectedCase: Case | null, 
  onSelectCase: (case_: Case) => void 
}> = ({ cases, selectedCase, onSelectCase }) => (
  <div className="space-y-6">
    {/* Case Management Header */}
    <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-2xl font-bold text-gray-900">Case Management</h2>
          <p className="text-gray-600 mt-1">Manage all your legal cases in one place</p>
        </div>
        <div className="flex items-center gap-3">
          <span className="bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1 rounded-full">
            {cases.length} Total Cases
          </span>
        </div>
      </div>
    </div>

    {/* Unified Case Management Widget */}
    <CaseWidget
      title="All My Cases"
      showMyCases={true}
      showAssignedCases={false}
      showPublicCases={false}
      maxCases={10}
      showCreateButton={true}
      showFilters={true}
      className="mb-6"
    />

    {/* Case Statistics */}
    <div className="grid grid-cols-1 md:grid-cols-4 gap-6">
      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <div className="flex items-center">
          <div className="p-2 bg-green-100 rounded-lg">
            <CheckCircle className="h-6 w-6 text-green-600" />
          </div>
          <div className="ml-4">
            <p className="text-sm font-medium text-gray-600">Active Cases</p>
            <p className="text-2xl font-bold text-gray-900">
              {cases.filter(c => c.status === 'active').length}
            </p>
          </div>
        </div>
      </div>

      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <div className="flex items-center">
          <div className="p-2 bg-yellow-100 rounded-lg">
            <Clock className="h-6 w-6 text-yellow-600" />
          </div>
          <div className="ml-4">
            <p className="text-sm font-medium text-gray-600">Pending Cases</p>
            <p className="text-2xl font-bold text-gray-900">
              {cases.filter(c => c.status === 'pending').length}
            </p>
          </div>
        </div>
      </div>

      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <div className="flex items-center">
          <div className="p-2 bg-blue-100 rounded-lg">
            <FileText className="h-6 w-6 text-blue-600" />
          </div>
          <div className="ml-4">
            <p className="text-sm font-medium text-gray-600">Total Documents</p>
            <p className="text-2xl font-bold text-gray-900">
              {cases.reduce((total, c) => total + c.documents.length, 0)}
            </p>
          </div>
        </div>
      </div>

      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <div className="flex items-center">
          <div className="p-2 bg-purple-100 rounded-lg">
            <MessageSquare className="h-6 w-6 text-purple-600" />
          </div>
          <div className="ml-4">
            <p className="text-sm font-medium text-gray-600">Recent Updates</p>
            <p className="text-2xl font-bold text-gray-900">
              {cases.reduce((total, c) => total + c.updates.length, 0)}
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
);

const DocumentsTab: React.FC<{ 
  cases: Case[], 
  selectedCase: Case | null,
  onUpload: () => void
}> = ({ cases, selectedCase, onUpload }) => (
  <div className="bg-white rounded-lg shadow-sm border border-gray-200">
    <div className="p-6 border-b border-gray-200">
      <div className="flex items-center justify-between">
        <h2 className="text-xl font-semibold text-gray-900">Documents</h2>
        <button
          onClick={onUpload}
          className="flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
        >
          <Upload className="w-4 h-4 mr-2" />
          Upload Document
        </button>
      </div>
    </div>
    
    <div className="p-6">
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        {cases.flatMap(c => c.documents).map((doc) => (
          <div key={doc.id} className="border border-gray-200 rounded-lg p-4">
            <div className="flex items-start justify-between">
              <div className="flex-1">
                <h3 className="text-sm font-medium text-gray-900">{doc.title}</h3>
                <p className="text-xs text-gray-500 mt-1">{doc.type}</p>
                <p className="text-xs text-gray-500">
                  {format(new Date(doc.uploadedAt), 'MMM dd, yyyy')}
                </p>
              </div>
              <div className="flex items-center space-x-2">
                <button className="text-blue-600 hover:text-blue-700">
                  <Eye className="w-4 h-4" />
                </button>
                <button className="text-blue-600 hover:text-blue-700">
                  <Download className="w-4 h-4" />
                </button>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  </div>
);

const PaymentsTab: React.FC<{ cases: Case[], selectedCase: Case | null }> = ({ cases }) => (
  <div className="bg-white rounded-lg shadow-sm border border-gray-200">
    <div className="p-6 border-b border-gray-200">
      <h2 className="text-xl font-semibold text-gray-900">Payment History</h2>
    </div>
    
    <div className="overflow-x-auto">
      <table className="min-w-full divide-y divide-gray-200">
        <thead className="bg-gray-50">
          <tr>
            <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
              Description
            </th>
            <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
              Amount
            </th>
            <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
              Status
            </th>
            <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
              Due Date
            </th>
            <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
              Actions
            </th>
          </tr>
        </thead>
        <tbody className="bg-white divide-y divide-gray-200">
          {cases.flatMap(c => c.payments).map((payment) => (
            <tr key={payment.id}>
              <td className="px-6 py-4 whitespace-nowrap">
                <div>
                  <div className="text-sm font-medium text-gray-900">{payment.description}</div>
                  <div className="text-sm text-gray-500">{payment.type}</div>
                </div>
              </td>
              <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
                ${payment.amount.toLocaleString()}
              </td>
              <td className="px-6 py-4 whitespace-nowrap">
                <span className={`px-2 py-1 text-xs font-medium rounded-full ${
                  payment.status === 'PAID' ? 'text-green-600 bg-green-100' :
                  payment.status === 'PENDING' ? 'text-yellow-600 bg-yellow-100' :
                  'text-red-600 bg-red-100'
                }`}>
                  {payment.status}
                </span>
              </td>
              <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                {format(new Date(payment.dueDate), 'MMM dd, yyyy')}
              </td>
              <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
                {payment.status === 'PENDING' && (
                  <button className="text-blue-600 hover:text-blue-900">
                    Pay Now
                  </button>
                )}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  </div>
);

const MessagesTab: React.FC<{ 
  messages: Message[], 
  selectedCase: Case | null,
  onSendMessage: () => void
}> = ({ messages, onSendMessage }) => (
  <div className="bg-white rounded-lg shadow-sm border border-gray-200">
    <div className="p-6 border-b border-gray-200">
      <div className="flex items-center justify-between">
        <h2 className="text-xl font-semibold text-gray-900">Messages</h2>
        <button
          onClick={onSendMessage}
          className="flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
        >
          <Send className="w-4 h-4 mr-2" />
          New Message
        </button>
      </div>
    </div>
    
    <div className="p-6">
      <div className="space-y-4">
        {messages.map((message) => (
          <div key={message.id} className={`flex ${message.senderId === 'client' ? 'justify-end' : 'justify-start'}`}>
            <div className={`max-w-xs lg:max-w-md px-4 py-2 rounded-lg ${
              message.senderId === 'client' 
                ? 'bg-blue-600 text-white' 
                : 'bg-gray-100 text-gray-900'
            }`}>
              <p className="text-sm">{message.content}</p>
              <p className={`text-xs mt-1 ${
                message.senderId === 'client' ? 'text-blue-100' : 'text-gray-500'
              }`}>
                {format(new Date(message.timestamp), 'MMM dd, HH:mm')}
              </p>
            </div>
          </div>
        ))}
      </div>
    </div>
  </div>
);

// Modal Components
const UploadModal: React.FC<{
  onUpload: (file: File, caseId: string) => void;
  onClose: () => void;
  caseId?: string;
}> = ({ onUpload, onClose, caseId }) => {
  const [file, setFile] = useState<File | null>(null);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (file && caseId) {
      onUpload(file, caseId);
    }
  };

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4">
        <div className="p-6">
          <h3 className="text-lg font-semibold text-gray-900 mb-4">Upload Document</h3>
          
          <form onSubmit={handleSubmit} className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Select File
              </label>
              <input
                type="file"
                onChange={(e) => setFile(e.target.files?.[0] || null)}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                required
              />
            </div>
            
            <div className="flex items-center justify-end gap-4 pt-4">
              <button
                type="button"
                onClick={onClose}
                className="px-4 py-2 text-gray-600 hover:text-gray-800"
              >
                Cancel
              </button>
              <button
                type="submit"
                disabled={!file}
                className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
              >
                Upload
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

const MessageModal: React.FC<{
  onSend: (content: string, recipientId: string) => void;
  onClose: () => void;
  recipientId?: string;
}> = ({ onSend, onClose, recipientId }) => {
  const [content, setContent] = useState('');

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (content && recipientId) {
      onSend(content, recipientId);
    }
  };

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4">
        <div className="p-6">
          <h3 className="text-lg font-semibold text-gray-900 mb-4">Send Message</h3>
          
          <form onSubmit={handleSubmit} className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Message
              </label>
              <textarea
                value={content}
                onChange={(e) => setContent(e.target.value)}
                rows={4}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                placeholder="Type your message..."
                required
              />
            </div>
            
            <div className="flex items-center justify-end gap-4 pt-4">
              <button
                type="button"
                onClick={onClose}
                className="px-4 py-2 text-gray-600 hover:text-gray-800"
              >
                Cancel
              </button>
              <button
                type="submit"
                disabled={!content}
                className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
              >
                Send
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

// Applications Tab Component
const ApplicationsTab: React.FC = () => {
  const [registrations, setRegistrations] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchRegistrations();
  }, []);

  const fetchRegistrations = async () => {
    try {
      setLoading(true);
      const response = await fetch('/api/user/registrations');
      if (response.ok) {
        const data = await response.json();
        setRegistrations(data.registrations || []);
      }
    } catch (error) {
      console.error('Error fetching registrations:', error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center p-8">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Applications Header */}
      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <div className="flex items-center justify-between">
          <div>
            <h2 className="text-2xl font-bold text-gray-900">Application Management</h2>
            <p className="text-gray-600 mt-1">Track and manage your legal applications</p>
          </div>
          <div className="flex items-center gap-3">
            <span className="bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1 rounded-full">
              {registrations.length} Total Applications
            </span>
          </div>
        </div>
      </div>

      {/* Applications List */}
      <div className="bg-white rounded-lg shadow-sm border border-gray-200">
        <div className="p-6 border-b border-gray-200">
          <h3 className="text-lg font-semibold text-gray-900">Your Applications</h3>
        </div>
        
        {registrations.length === 0 ? (
          <div className="p-8 text-center">
            <FileText className="w-12 h-12 text-gray-400 mx-auto mb-4" />
            <h3 className="text-lg font-medium text-gray-900 mb-2">No Applications Yet</h3>
            <p className="text-gray-600 mb-4">You haven't submitted any applications yet.</p>
            <button
              onClick={() => window.location.href = '/join'}
              className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
            >
              Submit New Application
            </button>
          </div>
        ) : (
          <div className="divide-y divide-gray-200">
            {registrations.map((registration) => (
              <div key={registration.id} className="p-6 hover:bg-gray-50 transition-colors">
                <div className="flex items-center justify-between">
                  <div className="flex-1">
                    <div className="flex items-center gap-3 mb-2">
                      <h4 className="text-lg font-medium text-gray-900">
                        {registration.firstName} {registration.lastName}
                      </h4>
                      <span className={`px-2 py-1 text-xs font-medium rounded-full ${
                        registration.status === 'APPROVED' ? 'bg-green-100 text-green-800' :
                        registration.status === 'REJECTED' ? 'bg-red-100 text-red-800' :
                        registration.status === 'PENDING' ? 'bg-yellow-100 text-yellow-800' :
                        'bg-gray-100 text-gray-800'
                      }`}>
                        {registration.status}
                      </span>
                    </div>
                    <p className="text-sm text-gray-600 mb-2">{registration.email}</p>
                    {registration.detaineeInfo && (
                      <div className="text-sm text-gray-500">
                        <p>Detainee: {registration.detaineeInfo.name}</p>
                        <p>Facility: {registration.detaineeInfo.facility}</p>
                      </div>
                    )}
                    <p className="text-xs text-gray-400 mt-2">
                      Submitted: {new Date(registration.createdAt).toLocaleDateString()}
                    </p>
                  </div>
                  <div className="flex items-center gap-2">
                    <button
                      onClick={() => window.location.href = `/user/applications/${registration.id}`}
                      className="text-blue-600 hover:text-blue-700 text-sm font-medium"
                    >
                      View Details
                    </button>
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
};

export default ClientDashboard; 

CasperSecurity Mini