233 lines
9.3 KiB
TypeScript
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>
|
|
);
|
|
}
|