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.quebec/private_html/src/components/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.quebec/private_html/src/components/SmartBillingIntegration.tsx
import React, { useState, useEffect } from 'react';
import { DollarSign, Clock, Calendar, FileText, TrendingUp, AlertTriangle, CheckCircle, User, Scale, Brain, Zap, Target, CreditCard, Receipt, PieChart, BarChart3, Download, Mail, Eye } from 'lucide-react';

interface BillingEntry {
  id: string;
  caseId: string;
  caseName: string;
  clientName: string;
  lawyerId: string;
  lawyerName: string;
  date: string;
  time: string;
  duration: number; // in minutes
  activity: string;
  billableRate: number;
  amount: number;
  status: 'pending' | 'approved' | 'invoiced' | 'paid';
  category: 'research' | 'drafting' | 'court_appearance' | 'client_meeting' | 'travel' | 'phone_call' | 'email';
  description: string;
  attachments?: string[];
}

interface Invoice {
  id: string;
  invoiceNumber: string;
  caseId: string;
  caseName: string;
  clientId: string;
  clientName: string;
  clientEmail: string;
  dateIssued: string;
  dateDue: string;
  status: 'draft' | 'sent' | 'paid' | 'overdue' | 'cancelled';
  subtotal: number;
  tax: number;
  total: number;
  paidAmount: number;
  billingEntries: BillingEntry[];
  paymentTerms: string;
  notes?: string;
}

interface BillingMetrics {
  totalRevenue: number;
  pendingBilling: number;
  outstandingInvoices: number;
  collectionRate: number;
  averageBillableRate: number;
  totalBillableHours: number;
  utilizationRate: number;
  revenueGrowth: number;
}

const SmartBillingIntegration: React.FC = () => {
  const [activeTab, setActiveTab] = useState<'dashboard' | 'time_entries' | 'invoices' | 'analytics' | 'settings'>('dashboard');
  const [billingEntries, setBillingEntries] = useState<BillingEntry[]>([]);
  const [invoices, setInvoices] = useState<Invoice[]>([]);
  const [metrics, setMetrics] = useState<BillingMetrics | null>(null);
  const [selectedPeriod, setSelectedPeriod] = useState<'week' | 'month' | 'quarter' | 'year'>('month');

  useEffect(() => {
    loadBillingData();
    loadInvoices();
    loadMetrics();
  }, [selectedPeriod]);

  const loadBillingData = () => {
    const entries: BillingEntry[] = [
      {
        id: 'bill_001',
        caseId: 'case_bordeaux_2024',
        caseName: 'Bordeaux Detention Center Class Action',
        clientName: 'Multiple Detainees',
        lawyerId: 'lawyer_justin',
        lawyerName: 'Justin Wee',
        date: '2025-03-08',
        time: '09:00',
        duration: 180, // 3 hours
        activity: 'Class Action Petition Drafting',
        billableRate: 650,
        amount: 1950,
        status: 'approved',
        category: 'drafting',
        description: 'Comprehensive class action petition drafting with AI-assisted legal research and fact compilation',
        attachments: ['petition_draft_v1.pdf', 'research_notes.pdf']
      },
      {
        id: 'bill_002',
        caseId: 'case_bordeaux_2024',
        caseName: 'Bordeaux Detention Center Class Action',
        clientName: 'Multiple Detainees',
        lawyerId: 'lawyer_audrey',
        lawyerName: 'Audrey Labrecque',
        date: '2025-03-08',
        time: '14:00',
        duration: 120, // 2 hours
        activity: 'Emergency Injunction Motion',
        billableRate: 550,
        amount: 1100,
        status: 'approved',
        category: 'drafting',
        description: 'Drafted emergency preliminary injunction motion with supporting affidavits',
        attachments: ['injunction_motion.pdf']
      },
      {
        id: 'bill_003',
        caseId: 'case_imm_001',
        caseName: 'Rodriguez Immigration Case',
        clientName: 'Maria Rodriguez',
        lawyerId: 'lawyer_marie',
        lawyerName: 'Marie-Christine Vachon',
        date: '2025-03-07',
        time: '10:30',
        duration: 90,
        activity: 'Detention Center Client Visit',
        billableRate: 450,
        amount: 675,
        status: 'pending',
        category: 'client_meeting',
        description: 'Initial consultation and case assessment at Laval Immigration Holding Centre'
      },
      {
        id: 'bill_004',
        caseId: 'case_bordeaux_2024',
        caseName: 'Bordeaux Detention Center Class Action',
        clientName: 'Multiple Detainees',
        lawyerId: 'lawyer_david',
        lawyerName: 'David Frappier',
        date: '2025-03-06',
        time: '11:00',
        duration: 240, // 4 hours
        activity: 'Expert Witness Consultation',
        billableRate: 600,
        amount: 2400,
        status: 'invoiced',
        category: 'research',
        description: 'Consultation with detention conditions expert and medical professionals'
      }
    ];
    setBillingEntries(entries);
  };

  const loadInvoices = () => {
    const invoiceData: Invoice[] = [
      {
        id: 'inv_001',
        invoiceNumber: 'INV-2025-001',
        caseId: 'case_bordeaux_2024',
        caseName: 'Bordeaux Detention Center Class Action',
        clientId: 'client_bordeaux',
        clientName: 'Bordeaux Class Action Fund',
        clientEmail: 'finance@bordeauxfund.org',
        dateIssued: '2025-03-01',
        dateDue: '2025-03-31',
        status: 'sent',
        subtotal: 24750.00,
        tax: 3712.50,
        total: 28462.50,
        paidAmount: 0,
        paymentTerms: 'Net 30',
        billingEntries: billingEntries.filter(entry => entry.status === 'invoiced'),
        notes: 'Class action legal services for February 2025'
      },
      {
        id: 'inv_002',
        invoiceNumber: 'INV-2025-002',
        caseId: 'case_imm_001',
        caseName: 'Rodriguez Immigration Case',
        clientId: 'client_rodriguez',
        clientName: 'Maria Rodriguez',
        clientEmail: 'maria.rodriguez@email.com',
        dateIssued: '2025-02-28',
        dateDue: '2025-03-28',
        status: 'paid',
        subtotal: 3500.00,
        tax: 525.00,
        total: 4025.00,
        paidAmount: 4025.00,
        paymentTerms: 'Net 30',
        billingEntries: [],
        notes: 'Immigration detention defense - flat fee arrangement'
      }
    ];
    setInvoices(invoiceData);
  };

  const loadMetrics = () => {
    const metricsData: BillingMetrics = {
      totalRevenue: 847293,
      pendingBilling: 47580,
      outstandingInvoices: 156745,
      collectionRate: 94.7,
      averageBillableRate: 575,
      totalBillableHours: 1472,
      utilizationRate: 87.3,
      revenueGrowth: 23.4
    };
    setMetrics(metricsData);
  };

  const generateInvoice = (entries: BillingEntry[]) => {
    const subtotal = entries.reduce((sum, entry) => sum + entry.amount, 0);
    const tax = subtotal * 0.15; // 15% tax rate
    const total = subtotal + tax;
    
    const newInvoice: Invoice = {
      id: `inv_${Date.now()}
      invoiceNumber: `INV-2025-${String(invoices.length + 1).padStart(3, '0')}
      caseId: entries[0]?.caseId || '',
      caseName: entries[0]?.caseName || '',
      clientId: `client_${entries[0]?.caseId}
      clientName: entries[0]?.clientName || '',
      clientEmail: 'client@email.com',
      dateIssued: new Date().toISOString().split('T')[0],
      dateDue: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
      status: 'draft',
      subtotal,
      tax,
      total,
      paidAmount: 0,
      paymentTerms: 'Net 30',
      billingEntries: entries,
      notes: `Legal services for ${new Date().toLocaleDateString('en-US', { month: 'long', year: 'numeric' })}
    };
    
    setInvoices([newInvoice, ...invoices]);
    
    // Update billing entries status
    setBillingEntries(prev => 
      prev.map(entry => 
        entries.find(e => e.id === entry.id) 
          ? { ...entry, status: 'invoiced' as const }
          : entry
      )
    );
  };

  const categoryColors = {
    research: 'bg-blue-100 text-blue-800',
    drafting: 'bg-purple-100 text-purple-800',
    court_appearance: 'bg-red-100 text-red-800',
    client_meeting: 'bg-green-100 text-green-800',
    travel: 'bg-yellow-100 text-yellow-800',
    phone_call: 'bg-orange-100 text-orange-800',
    email: 'bg-gray-100 text-gray-800'
  };

  const statusColors = {
    pending: 'bg-yellow-100 text-yellow-800',
    approved: 'bg-green-100 text-green-800',
    invoiced: 'bg-blue-100 text-blue-800',
    paid: 'bg-purple-100 text-purple-800',
    draft: 'bg-gray-100 text-gray-800',
    sent: 'bg-blue-100 text-blue-800',
    overdue: 'bg-red-100 text-red-800',
    cancelled: 'bg-gray-100 text-gray-800'
  };

  return (
    <div className="min-h-screen bg-gradient-to-br from-blue-50 via-purple-50 to-indigo-50 p-6">
      {/* Header */}
      <div className="mb-8">
        <div className="flex items-center justify-between">
          <div className="flex items-center space-x-4">
            <div className="p-3 bg-gradient-to-r from-green-600 to-emerald-600 rounded-xl">
              <DollarSign className="h-8 w-8 text-white" />
            </div>
            <div>
              <h1 className="text-3xl font-bold bg-gradient-to-r from-green-600 to-emerald-600 bg-clip-text text-transparent">
                💰 SmartBilling Pro Suite
              </h1>
              <p className="text-gray-600 flex items-center space-x-2">
                <Brain className="h-4 w-4" />
                <span>AI-Powered Billing, Invoicing & Financial Management</span>
              </p>
            </div>
          </div>
          
          <div className="flex items-center space-x-4">
            <select 
              value={selectedPeriod}
              onChange={(e) => setSelectedPeriod(e.target.value as any)}
              className="px-3 py-2 border border-gray-300 rounded-lg text-sm"
            >
              <option value="week">This Week</option>
              <option value="month">This Month</option>
              <option value="quarter">This Quarter</option>
              <option value="year">This Year</option>
            </select>
            <button className="flex items-center space-x-2 px-4 py-2 bg-gradient-to-r from-purple-600 to-blue-600 text-white rounded-lg font-medium hover:shadow-lg transition-all">
              <Zap className="h-4 w-4" />
              <span>Auto-Generate Invoice</span>
            </button>
          </div>
        </div>
      </div>

      {/* Navigation Tabs */}
      <div className="mb-6">
        <div className="flex space-x-1 bg-white rounded-lg p-1 shadow-md">
          {[
            { id: 'dashboard', label: 'Dashboard', icon: Target },
            { id: 'time_entries', label: 'Time Entries', icon: Clock },
            { id: 'invoices', label: 'Invoices', icon: Receipt },
            { id: 'analytics', label: 'Analytics', icon: BarChart3 },
            { id: 'settings', label: 'Settings', icon: Calendar }
          ].map((tab) => {
            const IconComponent = tab.icon;
            return (
              <button
                key={tab.id}
                onClick={() => setActiveTab(tab.id as any)}
                className={
                  activeTab === tab.id
                    ? 'bg-green-600 text-white shadow-md'
                    : 'text-gray-600 hover:text-green-600 hover:bg-gray-50'
                }
              >
                <IconComponent className="h-4 w-4" />
                <span>{tab.label}</span>
              </button>
            );
          })}
        </div>
      </div>

      {/* Dashboard View */}
      {activeTab === 'dashboard' && (
        <div className="space-y-6">
          {/* Key Metrics */}
          <div className="grid grid-cols-4 gap-6">
            <div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-gray-600">Total Revenue</p>
                  <p className="text-3xl font-bold text-green-600">${metrics?.totalRevenue.toLocaleString()}</p>
                </div>
                <div className="p-3 bg-green-100 rounded-lg">
                  <DollarSign className="h-6 w-6 text-green-600" />
                </div>
              </div>
              <div className="mt-4 flex items-center text-sm">
                <TrendingUp className="h-4 w-4 text-green-500 mr-1" />
                <span className="text-green-600">+{metrics?.revenueGrowth}% vs last period</span>
              </div>
            </div>

            <div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-gray-600">Pending Billing</p>
                  <p className="text-3xl font-bold text-yellow-600">${metrics?.pendingBilling.toLocaleString()}</p>
                </div>
                <div className="p-3 bg-yellow-100 rounded-lg">
                  <Clock className="h-6 w-6 text-yellow-600" />
                </div>
              </div>
              <div className="mt-4 flex items-center text-sm">
                <AlertTriangle className="h-4 w-4 text-yellow-500 mr-1" />
                <span className="text-yellow-600">Ready to invoice</span>
              </div>
            </div>

            <div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-gray-600">Outstanding</p>
                  <p className="text-3xl font-bold text-red-600">${metrics?.outstandingInvoices.toLocaleString()}</p>
                </div>
                <div className="p-3 bg-red-100 rounded-lg">
                  <Receipt className="h-6 w-6 text-red-600" />
                </div>
              </div>
              <div className="mt-4 flex items-center text-sm">
                <AlertTriangle className="h-4 w-4 text-red-500 mr-1" />
                <span className="text-red-600">Awaiting payment</span>
              </div>
            </div>

            <div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-gray-600">Collection Rate</p>
                  <p className="text-3xl font-bold text-blue-600">{metrics?.collectionRate}%</p>
                </div>
                <div className="p-3 bg-blue-100 rounded-lg">
                  <TrendingUp className="h-6 w-6 text-blue-600" />
                </div>
              </div>
              <div className="mt-4 flex items-center text-sm">
                <CheckCircle className="h-4 w-4 text-blue-500 mr-1" />
                <span className="text-blue-600">Above industry avg</span>
              </div>
            </div>
          </div>

          {/* Recent Activity */}
          <div className="grid grid-cols-2 gap-6">
            {/* Recent Time Entries */}
            <div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
              <h2 className="text-xl font-bold text-gray-900 mb-6 flex items-center">
                <Clock className="h-5 w-5 mr-2" />
                Recent Time Entries
              </h2>
              
              <div className="space-y-4">
                {billingEntries.slice(0, 5).map((entry) => (
                  <div key={entry.id} className="p-4 bg-gray-50 rounded-lg border border-gray-200">
                    <div className="flex items-center justify-between mb-2">
                      <div>
                        <h3 className="font-semibold text-gray-900">{entry.activity}</h3>
                        <p className="text-sm text-gray-600">{entry.caseName}</p>
                      </div>
                      <div className="text-right">
                        <p className="font-bold text-green-600">${entry.amount}</p>
                        <span className={`px-2 py-1 rounded-full text-xs font-medium ${statusColors[entry.status]}
                          {entry.status.toUpperCase()}
                        </span>
                      </div>
                    </div>
                    
                    <div className="flex items-center justify-between text-sm text-gray-600">
                      <div className="flex items-center space-x-4">
                        <span>{entry.lawyerName}</span>
                        <span>{entry.duration}min</span>
                        <span className={`px-2 py-1 rounded-full text-xs ${categoryColors[entry.category]}
                          {entry.category.replace('_', ' ').toUpperCase()}
                        </span>
                      </div>
                      <span>{entry.date}</span>
                    </div>
                  </div>
                ))}
              </div>
              
              <button className="w-full mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 transition-colors">
                View All Time Entries
              </button>
            </div>

            {/* Recent Invoices */}
            <div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
              <h2 className="text-xl font-bold text-gray-900 mb-6 flex items-center">
                <Receipt className="h-5 w-5 mr-2" />
                Recent Invoices
              </h2>
              
              <div className="space-y-4">
                {invoices.slice(0, 5).map((invoice) => (
                  <div key={invoice.id} className="p-4 bg-gray-50 rounded-lg border border-gray-200">
                    <div className="flex items-center justify-between mb-2">
                      <div>
                        <h3 className="font-semibold text-gray-900">{invoice.invoiceNumber}</h3>
                        <p className="text-sm text-gray-600">{invoice.clientName}</p>
                      </div>
                      <div className="text-right">
                        <p className="font-bold text-green-600">${invoice.total.toLocaleString()}</p>
                        <span className={`px-2 py-1 rounded-full text-xs font-medium ${statusColors[invoice.status]}
                          {invoice.status.toUpperCase()}
                        </span>
                      </div>
                    </div>
                    
                    <div className="flex items-center justify-between text-sm text-gray-600">
                      <div className="flex items-center space-x-4">
                        <span>Due: {invoice.dateDue}</span>
                        {invoice.status === 'paid' && (
                          <span className="text-green-600">✓ Paid</span>
                        )}
                      </div>
                      <div className="flex items-center space-x-2">
                        <button className="p-1 hover:bg-gray-200 rounded">
                          <Eye className="h-4 w-4 text-gray-600" />
                        </button>
                        <button className="p-1 hover:bg-gray-200 rounded">
                          <Download className="h-4 w-4 text-gray-600" />
                        </button>
                        <button className="p-1 hover:bg-gray-200 rounded">
                          <Mail className="h-4 w-4 text-gray-600" />
                        </button>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
              
              <button className="w-full mt-4 px-4 py-2 bg-green-600 text-white rounded-lg font-medium hover:bg-green-700 transition-colors">
                Create New Invoice
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Time Entries View */}
      {activeTab === 'time_entries' && (
        <div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
          <div className="flex items-center justify-between mb-6">
            <h2 className="text-xl font-bold text-gray-900">Time Entries</h2>
            <div className="flex items-center space-x-4">
              <select className="px-3 py-2 border border-gray-300 rounded-lg text-sm">
                <option>All Status</option>
                <option>Pending</option>
                <option>Approved</option>
                <option>Invoiced</option>
              </select>
              <button 
                onClick={() => {
                  const approvedEntries = billingEntries.filter(entry => entry.status === 'approved');
                  if (approvedEntries.length > 0) {
                    generateInvoice(approvedEntries);
                  }
                }}
                className="px-4 py-2 bg-green-600 text-white rounded-lg font-medium hover:bg-green-700 transition-colors"
              >
                Generate Invoice
              </button>
            </div>
          </div>
          
          <div className="overflow-x-auto">
            <table className="w-full">
              <thead>
                <tr className="border-b border-gray-200">
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Date/Time</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Lawyer</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Case</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Activity</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Duration</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Rate</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Amount</th>
                  <th className="text-left py-3 px-4 font-medium text-gray-900">Status</th>
                </tr>
              </thead>
              <tbody>
                {billingEntries.map((entry) => (
                  <tr key={entry.id} className="border-b border-gray-100 hover:bg-gray-50">
                    <td className="py-3 px-4">
                      <div>
                        <p className="font-medium text-gray-900">{entry.date}</p>
                        <p className="text-sm text-gray-600">{entry.time}</p>
                      </div>
                    </td>
                    <td className="py-3 px-4">
                      <p className="text-sm text-gray-900">{entry.lawyerName}</p>
                    </td>
                    <td className="py-3 px-4">
                      <div>
                        <p className="font-medium text-gray-900">{entry.caseName}</p>
                        <p className="text-sm text-gray-600">{entry.clientName}</p>
                      </div>
                    </td>
                    <td className="py-3 px-4">
                      <div>
                        <p className="font-medium text-gray-900">{entry.activity}</p>
                        <span className={`px-2 py-1 rounded-full text-xs font-medium ${categoryColors[entry.category]}
                          {entry.category.replace('_', ' ').toUpperCase()}
                        </span>
                      </div>
                    </td>
                    <td className="py-3 px-4">
                      <p className="text-sm text-gray-900">{Math.floor(entry.duration / 60)}h {entry.duration % 60}m</p>
                    </td>
                    <td className="py-3 px-4">
                      <p className="text-sm text-gray-900">${entry.billableRate}/hr</p>
                    </td>
                    <td className="py-3 px-4">
                      <p className="font-bold text-green-600">${entry.amount}</p>
                    </td>
                    <td className="py-3 px-4">
                      <span className={`px-2 py-1 rounded-full text-xs font-medium ${statusColors[entry.status]}
                        {entry.status.toUpperCase()}
                      </span>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
};

export default SmartBillingIntegration; 

CasperSecurity Mini