import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card'; import { Badge } from '../ui/badge'; import { Button } from '../ui/button'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import { Textarea } from '../ui/textarea'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table'; import { Progress } from '../ui/progress'; import { ArrowLeft, DollarSign, CheckCircle, XCircle, Upload, FileText, Calendar, User, MapPin, AlertCircle, Wallet, Receipt, TrendingUp, TrendingDown, Building, CreditCard, Hash, Send, Users, Plus, Edit2, Trash2, Save, Calculator } from 'lucide-react'; import { toast } from 'sonner'; import { departments } from '../../lib/mock-data'; interface FinanceFnFDetailsPageProps { fnfId: string; onBack: () => void; } // Mock data - in real app this would come from API const getFnFData = (id: string) => { return { id: id, caseNumber: 'FNF-2024-001', dealerName: 'Rajesh Kumar', dealerCode: 'DLR-001', location: 'Mumbai, Maharashtra', terminationType: 'Resignation', submittedDate: '2025-09-15', dueDate: '2025-10-20', status: 'Pending Finance Review', financialData: { // Payables (Company owes dealer) securityDeposit: 500000, inventoryValue: 1200000, equipmentValue: 300000, // Receivables (Dealer owes company) outstandingInvoices: 450000, serviceDues: 75000, partsDues: 125000, advancesGiven: 200000, penalties: 50000, otherCharges: 25000, // Deductions warrantyPending: 100000, }, bankDetails: { accountName: 'Rajesh Kumar', accountNumber: '1234567890', ifscCode: 'HDFC0001234', bankName: 'HDFC Bank', branch: 'Mumbai Central' }, documents: [ { name: 'Resignation Letter.pdf', size: '245 KB', uploadedOn: '2025-09-15', type: 'Resignation' }, { name: 'Asset Handover Receipt.pdf', size: '312 KB', uploadedOn: '2025-09-16', type: 'Asset' }, { name: 'Inventory Report.xlsx', size: '856 KB', uploadedOn: '2025-09-17', type: 'Inventory' }, { name: 'Bank Statement.pdf', size: '1.2 MB', uploadedOn: '2025-09-15', type: 'Financial' } ], departmentResponses: departments.map((dept, index) => ({ id: `dept-${index + 1}`, departmentName: dept, status: index < 8 ? 'NOC Submitted' : index < 12 ? 'Dues Pending' : 'Pending', remarks: index < 8 ? 'No outstanding dues, clearance provided' : index < 12 ? 'Outstanding amount to be recovered' : 'Awaiting department response', amountType: index === 8 ? 'Recovery Amount' : index === 9 ? 'Payable Amount' : index === 10 ? 'Recovery Amount' : undefined, amount: index === 8 ? 75000 : index === 9 ? 12000 : index === 10 ? 125000 : undefined, submittedDate: index < 12 ? '2025-10-05' : undefined, submittedBy: index < 12 ? `${dept} Head` : undefined })) }; }; const calculateSettlement = (financialData: any) => { const payables = financialData.securityDeposit + financialData.inventoryValue + financialData.equipmentValue; const receivables = financialData.outstandingInvoices + financialData.serviceDues + financialData.partsDues + financialData.advancesGiven + financialData.penalties + financialData.otherCharges; const deductions = financialData.warrantyPending; const netSettlement = payables - receivables - deductions; return { payables, receivables, deductions, netSettlement, settlementAmount: Math.abs(netSettlement), settlementType: netSettlement > 0 ? 'Payable to Dealer' : 'Recovery from Dealer' }; }; const getDepartmentStatusColor = (status: string) => { switch (status) { case 'NOC Submitted': return 'bg-green-100 text-green-700 border-green-300'; case 'Dues Pending': return 'bg-red-100 text-red-700 border-red-300'; case 'Completed': return 'bg-green-100 text-green-700 border-green-300'; case 'Pending': return 'bg-slate-100 text-slate-700 border-slate-300'; default: return 'bg-slate-100 text-slate-700 border-slate-300'; } }; interface FinancialLineItem { id: string; department: string; description: string; amount: number; } export function FinanceFnFDetailsPage({ fnfId, onBack }: FinanceFnFDetailsPageProps) { const fnfCase = getFnFData(fnfId); // Initialize editable line items from mock data const [payableItems, setPayableItems] = useState([ { id: '1', department: 'Security Deposit', description: 'Refundable security deposit', amount: fnfCase.financialData.securityDeposit }, { id: '2', department: 'Inventory', description: 'Vehicle inventory value', amount: fnfCase.financialData.inventoryValue }, { id: '3', department: 'Equipment', description: 'Equipment and fixtures value', amount: fnfCase.financialData.equipmentValue } ]); const [receivableItems, setReceivableItems] = useState([ { id: '1', department: 'Sales', description: 'Outstanding invoices', amount: fnfCase.financialData.outstandingInvoices }, { id: '2', department: 'Service', description: 'Service dues', amount: fnfCase.financialData.serviceDues }, { id: '3', department: 'Parts', description: 'Parts dues', amount: fnfCase.financialData.partsDues }, { id: '4', department: 'Finance', description: 'Advances given to dealer', amount: fnfCase.financialData.advancesGiven }, { id: '5', department: 'Compliance', description: 'Penalties and fines', amount: fnfCase.financialData.penalties }, { id: '6', department: 'Other', description: 'Miscellaneous charges', amount: fnfCase.financialData.otherCharges } ]); const [deductionItems, setDeductionItems] = useState([ { id: '1', department: 'Warranty', description: 'Pending warranty claims', amount: fnfCase.financialData.warrantyPending } ]); // Form states for adding new items const [newPayable, setNewPayable] = useState({ department: '', description: '', amount: '' }); const [newReceivable, setNewReceivable] = useState({ department: '', description: '', amount: '' }); const [newDeduction, setNewDeduction] = useState({ department: '', description: '', amount: '' }); // Edit mode states const [editingPayableId, setEditingPayableId] = useState(null); const [editingReceivableId, setEditingReceivableId] = useState(null); const [editingDeductionId, setEditingDeductionId] = useState(null); // Calculate dynamic settlement const calculateDynamicSettlement = () => { const payables = payableItems.reduce((sum, item) => sum + item.amount, 0); const receivables = receivableItems.reduce((sum, item) => sum + item.amount, 0); const deductions = deductionItems.reduce((sum, item) => sum + item.amount, 0); const netSettlement = payables - receivables - deductions; return { payables, receivables, deductions, netSettlement, settlementAmount: Math.abs(netSettlement), settlementType: netSettlement > 0 ? 'Payable to Dealer' : netSettlement < 0 ? 'Recovery from Dealer' : 'No Settlement Required' }; }; const settlement = calculateDynamicSettlement(); const [settlementDetails, setSettlementDetails] = useState({ verificationTransactionId: '', settlementAmount: settlement.settlementAmount.toString(), settlementDate: new Date().toISOString().split('T')[0], paymentMode: '', bankReference: '', verificationRemarks: '', adjustments: '0' }); const [uploadedDocuments, setUploadedDocuments] = useState([]); // Handlers for Payables const handleAddPayable = () => { if (!newPayable.department || !newPayable.description || !newPayable.amount) { toast.error('Please fill in all fields'); return; } const item: FinancialLineItem = { id: Date.now().toString(), department: newPayable.department, description: newPayable.description, amount: parseFloat(newPayable.amount) }; setPayableItems([...payableItems, item]); setNewPayable({ department: '', description: '', amount: '' }); toast.success('Payable item added'); }; const handleUpdatePayable = (id: string, field: keyof FinancialLineItem, value: string | number) => { setPayableItems(payableItems.map(item => item.id === id ? { ...item, [field]: field === 'amount' ? parseFloat(value.toString()) : value } : item )); }; const handleDeletePayable = (id: string) => { setPayableItems(payableItems.filter(item => item.id !== id)); toast.info('Payable item removed'); }; // Handlers for Receivables const handleAddReceivable = () => { if (!newReceivable.department || !newReceivable.description || !newReceivable.amount) { toast.error('Please fill in all fields'); return; } const item: FinancialLineItem = { id: Date.now().toString(), department: newReceivable.department, description: newReceivable.description, amount: parseFloat(newReceivable.amount) }; setReceivableItems([...receivableItems, item]); setNewReceivable({ department: '', description: '', amount: '' }); toast.success('Receivable item added'); }; const handleUpdateReceivable = (id: string, field: keyof FinancialLineItem, value: string | number) => { setReceivableItems(receivableItems.map(item => item.id === id ? { ...item, [field]: field === 'amount' ? parseFloat(value.toString()) : value } : item )); }; const handleDeleteReceivable = (id: string) => { setReceivableItems(receivableItems.filter(item => item.id !== id)); toast.info('Receivable item removed'); }; // Handlers for Deductions const handleAddDeduction = () => { if (!newDeduction.department || !newDeduction.description || !newDeduction.amount) { toast.error('Please fill in all fields'); return; } const item: FinancialLineItem = { id: Date.now().toString(), department: newDeduction.department, description: newDeduction.description, amount: parseFloat(newDeduction.amount) }; setDeductionItems([...deductionItems, item]); setNewDeduction({ department: '', description: '', amount: '' }); toast.success('Deduction item added'); }; const handleUpdateDeduction = (id: string, field: keyof FinancialLineItem, value: string | number) => { setDeductionItems(deductionItems.map(item => item.id === id ? { ...item, [field]: field === 'amount' ? parseFloat(value.toString()) : value } : item )); }; const handleDeleteDeduction = (id: string) => { setDeductionItems(deductionItems.filter(item => item.id !== id)); toast.info('Deduction item removed'); }; const handleFileUpload = (event: React.ChangeEvent) => { const files = event.target.files; if (files && files.length > 0) { const newDocs = Array.from(files).map(file => ({ name: file.name, size: `${(file.size / 1024).toFixed(0)} KB`, uploadedOn: new Date().toISOString().split('T')[0], type: 'Settlement Verification' })); setUploadedDocuments([...uploadedDocuments, ...newDocs]); toast.success(`${files.length} document(s) uploaded successfully`); } }; const handleApproveSettlement = () => { if (!settlementDetails.verificationTransactionId || !settlementDetails.settlementDate || !settlementDetails.paymentMode) { toast.error('Please fill in all required settlement details'); return; } const adjustedAmount = settlement.settlementAmount + parseFloat(settlementDetails.adjustments || '0'); if (adjustedAmount.toString() !== settlementDetails.settlementAmount) { toast.warning('Settlement amount has been adjusted'); } toast.success(`F&F Settlement approved for ${fnfCase.dealerName}`); setTimeout(() => onBack(), 1500); }; const handleRejectSettlement = () => { if (!settlementDetails.verificationRemarks) { toast.error('Please provide remarks for rejection'); return; } toast.error(`F&F Settlement rejected for ${fnfCase.dealerName}`); setTimeout(() => onBack(), 1500); }; const handleRequestClarification = () => { if (!settlementDetails.verificationRemarks) { toast.error('Please provide details for clarification request'); return; } toast.info(`Clarification request sent for ${fnfCase.dealerName}`); setTimeout(() => onBack(), 1500); }; return (
{/* Header */}

F&F Settlement Review

Full & Final Settlement for {fnfCase.dealerName}

{/* Status Banner */}

Settlement Pending Finance Approval

Case: {fnfCase.caseNumber} • Due: {fnfCase.dueDate}

{fnfCase.status} {fnfCase.terminationType}
{/* Settlement Summary Card */}
{settlement.settlementType === 'Payable to Dealer' ? ( ) : settlement.settlementType === 'Recovery from Dealer' ? ( ) : ( )}

{settlement.settlementType}

{settlement.settlementType === 'No Settlement Required' ? '₹0' : `₹${settlement.settlementAmount.toLocaleString('en-IN')}`}

Net Settlement Amount

{settlement.settlementType === 'Payable to Dealer' ? 'Company will pay to dealer' : settlement.settlementType === 'Recovery from Dealer' ? 'Dealer must pay to company' : 'No payment required'}

{/* Left Column - Case Details & Financial Info */}
Overview Financial Departments Documents Bank Details {/* Case Information */} Case Information

{fnfCase.caseNumber}

{fnfCase.dealerCode}

{fnfCase.dealerName}

{fnfCase.location}

{fnfCase.terminationType}
{fnfCase.status}

{fnfCase.submittedDate}

{fnfCase.dueDate}

{(() => { const submitted = new Date(fnfCase.submittedDate); const today = new Date(); const diffTime = Math.abs(today.getTime() - submitted.getTime()); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); return `${diffDays} day${diffDays !== 1 ? 's' : ''}`; })()}

SAL-{fnfCase.dealerCode}

SRV-{fnfCase.dealerCode}

GER-{fnfCase.dealerCode}

GMA-{fnfCase.dealerCode}

{/* Settlement Calculation Overview */} Settlement Calculation Summary
Total Payables (to Dealer) + ₹{settlement.payables.toLocaleString('en-IN')}
Total Receivables (from Dealer) - ₹{settlement.receivables.toLocaleString('en-IN')}
Total Deductions - ₹{settlement.deductions.toLocaleString('en-IN')}
Net Settlement

{settlement.settlementType}

{settlement.settlementType === 'No Settlement Required' ? '₹0' : `₹${settlement.settlementAmount.toLocaleString('en-IN')}`}

Calculation Formula

Net Settlement = Payables - Receivables - Deductions
All amounts are editable in the Financial tab

{/* Payables - Editable */}
Payables to Dealer (Editable) Add or modify amounts company owes to dealer
{/* Existing Payables */} Department Description Amount (₹) Actions {payableItems.map((item) => ( {editingPayableId === item.id ? ( handleUpdatePayable(item.id, 'department', e.target.value)} className="h-8" /> ) : ( {item.department} )} {editingPayableId === item.id ? ( handleUpdatePayable(item.id, 'description', e.target.value)} className="h-8" /> ) : ( {item.description} )} {editingPayableId === item.id ? ( handleUpdatePayable(item.id, 'amount', e.target.value)} className="h-8 text-right" /> ) : ( ₹{item.amount.toLocaleString('en-IN')} )}
{editingPayableId === item.id ? ( ) : ( )}
))}
{/* Add New Payable */}

Add New Payable Item:

setNewPayable({ ...newPayable, department: e.target.value })} className="col-span-3" /> setNewPayable({ ...newPayable, description: e.target.value })} className="col-span-5" /> setNewPayable({ ...newPayable, amount: e.target.value })} className="col-span-3" />
{/* Total */}
Total Payables ₹{settlement.payables.toLocaleString('en-IN')}
{/* Receivables - Editable */}
Receivables from Dealer (Editable) Add or modify amounts dealer owes to company
{/* Existing Receivables */} Department Description Amount (₹) Actions {receivableItems.map((item) => ( {editingReceivableId === item.id ? ( handleUpdateReceivable(item.id, 'department', e.target.value)} className="h-8" /> ) : ( {item.department} )} {editingReceivableId === item.id ? ( handleUpdateReceivable(item.id, 'description', e.target.value)} className="h-8" /> ) : ( {item.description} )} {editingReceivableId === item.id ? ( handleUpdateReceivable(item.id, 'amount', e.target.value)} className="h-8 text-right" /> ) : ( ₹{item.amount.toLocaleString('en-IN')} )}
{editingReceivableId === item.id ? ( ) : ( )}
))}
{/* Add New Receivable */}

Add New Receivable Item:

setNewReceivable({ ...newReceivable, department: e.target.value })} className="col-span-3" /> setNewReceivable({ ...newReceivable, description: e.target.value })} className="col-span-5" /> setNewReceivable({ ...newReceivable, amount: e.target.value })} className="col-span-3" />
{/* Total */}
Total Receivables ₹{settlement.receivables.toLocaleString('en-IN')}
{/* Deductions - Editable */}
Deductions (Editable) Add or modify pending claims and deductions
{/* Existing Deductions */} Department Description Amount (₹) Actions {deductionItems.map((item) => ( {editingDeductionId === item.id ? ( handleUpdateDeduction(item.id, 'department', e.target.value)} className="h-8" /> ) : ( {item.department} )} {editingDeductionId === item.id ? ( handleUpdateDeduction(item.id, 'description', e.target.value)} className="h-8" /> ) : ( {item.description} )} {editingDeductionId === item.id ? ( handleUpdateDeduction(item.id, 'amount', e.target.value)} className="h-8 text-right" /> ) : ( ₹{item.amount.toLocaleString('en-IN')} )}
{editingDeductionId === item.id ? ( ) : ( )}
))}
{/* Add New Deduction */}

Add New Deduction Item:

setNewDeduction({ ...newDeduction, department: e.target.value })} className="col-span-3" /> setNewDeduction({ ...newDeduction, description: e.target.value })} className="col-span-5" /> setNewDeduction({ ...newDeduction, amount: e.target.value })} className="col-span-3" />
{/* Total */}
Total Deductions ₹{settlement.deductions.toLocaleString('en-IN')}
{/* Final Settlement Summary */} Final Settlement Summary
Total Payables (to Dealer) + ₹{settlement.payables.toLocaleString('en-IN')}
Total Receivables (from Dealer) - ₹{settlement.receivables.toLocaleString('en-IN')}
Total Deductions - ₹{settlement.deductions.toLocaleString('en-IN')}

Net Settlement

{settlement.settlementType}

{settlement.settlementType === 'No Settlement Required' ? '₹0' : `₹${settlement.settlementAmount.toLocaleString('en-IN')}`}

Calculation Formula

Net Settlement = Payables - Receivables - Deductions
{settlement.netSettlement > 0 && 'Positive value means company pays to dealer'} {settlement.netSettlement < 0 && 'Negative value means dealer pays to company'} {settlement.netSettlement === 0 && 'Zero means no payment required from either party'}

{/* Progress Summary */} Department Response Progress {fnfCase.departmentResponses.filter((d: any) => d.status !== 'Pending').length} of {fnfCase.departmentResponses.length} departments have responded d.status !== 'Pending').length / fnfCase.departmentResponses.length) * 100} className="h-3" />

NOC Submitted

{fnfCase.departmentResponses.filter((d: any) => d.status === 'NOC Submitted').length}

Dues Pending

{fnfCase.departmentResponses.filter((d: any) => d.status === 'Dues Pending').length}

Awaiting Response

{fnfCase.departmentResponses.filter((d: any) => d.status === 'Pending').length}

{/* Department Responses Table */} All Department Responses Status of NOC and dues clearance from all 16 departments Department Status Amount Type Amount Submitted Date Remarks {fnfCase.departmentResponses.map((dept: any) => ( {dept.departmentName} {dept.status} {dept.amountType ? ( {dept.amountType} ) : ( '-' )} {dept.amount ? ( ₹{dept.amount.toLocaleString('en-IN')} ) : ( '-' )} {dept.submittedDate || '-'} {dept.remarks || '-'} ))}
{/* Important Notes */}

Department Response Guidelines

  • NOC Submitted: Department has no outstanding dues and provided clearance
  • Dues Pending: Department has identified amounts to be recovered or paid
  • Pending: Department has not yet responded to the F&F request
{/* Submitted Documents */} Submitted Documents
{fnfCase.documents.map((doc, index) => (

{doc.name}

{doc.size} • {doc.type} • Uploaded on {doc.uploadedOn}

))}
{/* Upload Additional Documents */} Upload Settlement Verification Documents Upload bank receipts, settlement proofs, or any additional documents

Click to upload or drag and drop

PDF, DOC, DOCX, PNG, JPG, XLSX (max 10MB)

{uploadedDocuments.length > 0 && (
{uploadedDocuments.map((doc, index) => (

{doc.name}

{doc.size} • {doc.type}

))}
)}
{/* Bank Account Details */} Dealer Bank Account Details Bank account for settlement transfer (if payable to dealer)

{fnfCase.bankDetails.accountName}

{fnfCase.bankDetails.accountNumber}

{fnfCase.bankDetails.ifscCode}

{fnfCase.bankDetails.bankName}

{fnfCase.bankDetails.branch}

Bank Verification Required

Please verify bank account details before processing settlement payment

{/* Right Column - Settlement Verification Form */}
Settlement Verification Enter settlement transaction details
setSettlementDetails({ ...settlementDetails, paymentMode: e.target.value })} />
setSettlementDetails({ ...settlementDetails, verificationTransactionId: e.target.value })} />
setSettlementDetails({ ...settlementDetails, bankReference: e.target.value })} />
setSettlementDetails({ ...settlementDetails, settlementAmount: e.target.value })} />
{ const adjustments = e.target.value; const adjustedAmount = settlement.settlementAmount + parseFloat(adjustments || '0'); setSettlementDetails({ ...settlementDetails, adjustments, settlementAmount: adjustedAmount.toString() }); }} /> {parseFloat(settlementDetails.adjustments) !== 0 && (

Adjusted amount: ₹{settlementDetails.settlementAmount}

)}
setSettlementDetails({ ...settlementDetails, settlementDate: e.target.value })} />