Re_Figma_Code/components/modals/InitiatorVerificationModal.tsx
2025-10-22 10:27:06 +05:30

233 lines
9.3 KiB
TypeScript

import React, { useState } from 'react';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../ui/dialog';
import { Button } from '../ui/button';
import { Label } from '../ui/label';
import { Input } from '../ui/input';
import { Textarea } from '../ui/textarea';
import { Badge } from '../ui/badge';
import { CheckCircle, AlertCircle, DollarSign, FileText } from 'lucide-react';
import { toast } from 'sonner@2.0.3';
interface InitiatorVerificationModalProps {
isOpen: boolean;
onClose: () => void;
onSubmit: (data: {
approvedAmount: string;
verificationComments: string;
}) => Promise<void>;
activityName: string;
requestedAmount?: string;
documents?: any[];
}
export function InitiatorVerificationModal({
isOpen,
onClose,
onSubmit,
activityName,
requestedAmount = 'TBD',
documents = []
}: InitiatorVerificationModalProps) {
const [approvedAmount, setApprovedAmount] = useState(requestedAmount === 'TBD' ? '' : requestedAmount.replace(/[₹,]/g, ''));
const [verificationComments, setVerificationComments] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const formatCurrency = (value: string) => {
// Remove non-numeric characters
const numericValue = value.replace(/[^0-9]/g, '');
if (!numericValue) return '';
// Format with commas
const number = parseInt(numericValue);
return `${number.toLocaleString('en-IN')}`;
};
const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value.replace(/[^0-9]/g, '');
setApprovedAmount(value);
};
const handleSubmit = async () => {
// Validation
if (!approvedAmount || approvedAmount === '0') {
toast.error('Please enter a valid approved amount');
return;
}
if (!verificationComments.trim()) {
toast.error('Please add verification comments');
return;
}
setIsSubmitting(true);
try {
await onSubmit({
approvedAmount: formatCurrency(approvedAmount),
verificationComments
});
onClose();
} catch (error) {
console.error('Error submitting verification:', error);
} finally {
setIsSubmitting(false);
}
};
const isAmountModified = requestedAmount !== 'TBD' &&
formatCurrency(approvedAmount) !== requestedAmount;
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="flex items-center gap-2 text-2xl">
<CheckCircle className="w-6 h-6 text-[--re-green]" />
Initiator Verification & Approval
</DialogTitle>
<DialogDescription className="text-base">
<div className="space-y-1 mt-2">
<p><strong>Activity:</strong> {activityName}</p>
<p className="text-sm text-gray-600 mt-2">
Review the dealer's completion documents and approve the final amount for E-invoice generation.
</p>
</div>
</DialogDescription>
</DialogHeader>
<div className="space-y-6 py-4">
{/* Completion Documents Review */}
<div className="space-y-3">
<Label className="text-base font-semibold">Dealer Completion Documents</Label>
{documents.length > 0 ? (
<div className="border rounded-lg divide-y">
{documents.slice(0, 5).map((doc, index) => (
<div key={index} className="p-3 flex items-center gap-3 hover:bg-gray-50">
<FileText className="w-5 h-5 text-gray-600" />
<div className="flex-1">
<p className="text-sm font-medium">{doc.name}</p>
<p className="text-xs text-gray-500">{doc.size} • Uploaded by {doc.uploadedBy}</p>
</div>
<Button variant="outline" size="sm">View</Button>
</div>
))}
</div>
) : (
<div className="border border-dashed rounded-lg p-4 text-center text-gray-500 text-sm">
No completion documents uploaded yet
</div>
)}
</div>
{/* Amount Approval Section */}
<div className="space-y-4 bg-blue-50 border-2 border-blue-200 rounded-lg p-4">
<div className="flex items-center justify-between">
<Label className="text-base font-semibold">Amount Approval</Label>
{isAmountModified && (
<Badge variant="destructive" className="text-xs">Amount Modified</Badge>
)}
</div>
{requestedAmount !== 'TBD' && (
<div className="bg-white rounded-lg p-3 border">
<Label className="text-xs text-gray-600 uppercase tracking-wider">Original Requested Amount</Label>
<p className="text-lg font-semibold text-gray-900 mt-1">{requestedAmount}</p>
</div>
)}
<div>
<Label htmlFor="approvedAmount" className="text-base font-semibold flex items-center gap-2">
Final Approved Amount *
{approvedAmount && <CheckCircle className="w-4 h-4 text-green-600" />}
</Label>
<p className="text-sm text-gray-600 mb-2">
Enter the final amount to be approved for E-invoice generation
</p>
<div className="relative">
<DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-gray-500" />
<Input
id="approvedAmount"
type="text"
placeholder="Enter amount (e.g., 245000)"
value={approvedAmount}
onChange={handleAmountChange}
className="pl-10 h-12 text-lg"
/>
</div>
{approvedAmount && (
<p className="text-sm text-gray-600 mt-2">
Formatted: <span className="font-semibold">{formatCurrency(approvedAmount)}</span>
</p>
)}
</div>
{isAmountModified && (
<div className="bg-amber-50 border border-amber-200 rounded-lg p-3 flex items-start gap-2">
<AlertCircle className="w-5 h-5 text-amber-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-amber-800">
<p className="font-semibold">Amount has been modified</p>
<p className="text-xs">Please provide justification in the verification comments below.</p>
</div>
</div>
)}
</div>
{/* Verification Comments */}
<div className="space-y-2">
<Label htmlFor="verificationComments" className="text-base font-semibold flex items-center gap-2">
Verification Comments *
{verificationComments.trim() && <CheckCircle className="w-4 h-4 text-green-600" />}
</Label>
<Textarea
id="verificationComments"
placeholder="Provide your verification comments, document review notes, and justification for any amount modifications..."
value={verificationComments}
onChange={(e) => setVerificationComments(e.target.value)}
className="min-h-[120px]"
/>
<p className="text-xs text-gray-500">
{verificationComments.length} characters
</p>
</div>
{/* Info Box */}
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 flex items-start gap-3">
<CheckCircle className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-blue-800">
<p className="font-semibold mb-1">Next Steps After Approval</p>
<ul className="list-disc list-inside space-y-1 text-xs">
<li>E-Invoice will be automatically generated based on the approved amount</li>
<li>Request will be forwarded to Finance for credit note issuance</li>
<li>Dealer will be notified of the approval</li>
</ul>
</div>
</div>
{/* Validation Alert */}
{(!approvedAmount || !verificationComments.trim()) && (
<div className="bg-amber-50 border border-amber-200 rounded-lg p-4 flex items-start gap-3">
<AlertCircle className="w-5 h-5 text-amber-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-amber-800">
<p className="font-semibold mb-1">Missing Required Information</p>
<p>Please enter the approved amount and provide verification comments before submitting.</p>
</div>
</div>
)}
</div>
<DialogFooter>
<Button variant="outline" onClick={onClose} disabled={isSubmitting}>
Cancel
</Button>
<Button
onClick={handleSubmit}
disabled={isSubmitting || !approvedAmount || !verificationComments.trim()}
className="bg-[--re-green] hover:bg-[--re-green-dark]"
>
{isSubmitting ? 'Approving...' : 'Approve & Continue'}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}