Re_Figma_Code/src/dealer-claim/components/request-detail/modals/EditClaimAmountModal.tsx

195 lines
6.1 KiB
TypeScript

/**
* EditClaimAmountModal Component
* Modal for editing claim amount (restricted by role)
*/
import { useState } from 'react';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { DollarSign, AlertCircle } from 'lucide-react';
import { toast } from 'sonner';
interface EditClaimAmountModalProps {
isOpen: boolean;
onClose: () => void;
currentAmount: number;
onSubmit: (newAmount: number) => Promise<void>;
currency?: string;
}
export function EditClaimAmountModal({
isOpen,
onClose,
currentAmount,
onSubmit,
currency = '₹',
}: EditClaimAmountModalProps) {
const [amount, setAmount] = useState<string>(currentAmount.toString());
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState<string>('');
const formatCurrency = (value: number) => {
return `${currency}${value.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
};
const handleAmountChange = (value: string) => {
// Remove non-numeric characters except decimal point
const cleaned = value.replace(/[^\d.]/g, '');
// Ensure only one decimal point
const parts = cleaned.split('.');
if (parts.length > 2) {
return;
}
setAmount(cleaned);
setError('');
};
const handleSubmit = async () => {
// Validate amount
const numAmount = parseFloat(amount);
if (isNaN(numAmount) || numAmount <= 0) {
setError('Please enter a valid amount greater than 0');
return;
}
if (numAmount === currentAmount) {
toast.info('Amount is unchanged');
onClose();
return;
}
try {
setSubmitting(true);
await onSubmit(numAmount);
onClose();
} catch (error) {
console.error('Failed to update claim amount:', error);
setError('Failed to update claim amount. Please try again.');
} finally {
setSubmitting(false);
}
};
const handleClose = () => {
if (!submitting) {
setAmount(currentAmount.toString());
setError('');
onClose();
}
};
return (
<Dialog open={isOpen} onOpenChange={handleClose}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<DollarSign className="w-5 h-5 text-green-600" />
Edit Claim Amount
</DialogTitle>
<DialogDescription>
Update the claim amount. This will be recorded in the activity log.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
{/* Current Amount Display */}
<div className="bg-gray-50 rounded-lg p-4 border border-gray-200">
<Label className="text-xs font-medium text-gray-500 uppercase tracking-wide mb-1 block">
Current Claim Amount
</Label>
<p className="text-2xl font-bold text-gray-900">
{formatCurrency(currentAmount)}
</p>
</div>
{/* New Amount Input */}
<div className="space-y-2">
<Label htmlFor="new-amount" className="text-sm font-medium">
New Claim Amount <span className="text-red-500">*</span>
</Label>
<div className="relative">
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500 font-semibold">
{currency}
</span>
<Input
id="new-amount"
type="text"
value={amount}
onChange={(e) => handleAmountChange(e.target.value)}
placeholder="Enter amount"
className="pl-8 text-lg font-semibold"
disabled={submitting}
/>
</div>
{error && (
<div className="flex items-center gap-2 text-sm text-red-600">
<AlertCircle className="w-4 h-4" />
<span>{error}</span>
</div>
)}
</div>
{/* Amount Difference */}
{amount && !isNaN(parseFloat(amount)) && parseFloat(amount) !== currentAmount && (
<div className="bg-blue-50 rounded-lg p-3 border border-blue-200">
<div className="flex items-center justify-between text-sm">
<span className="text-gray-700">Difference:</span>
<span className={`font-semibold ${
parseFloat(amount) > currentAmount ? 'text-green-700' : 'text-red-700'
}`}>
{parseFloat(amount) > currentAmount ? '+' : ''}
{formatCurrency(parseFloat(amount) - currentAmount)}
</span>
</div>
</div>
)}
{/* Warning Message */}
<div className="bg-amber-50 border border-amber-200 rounded-lg p-3">
<div className="flex gap-2">
<AlertCircle className="w-4 h-4 text-amber-600 mt-0.5 flex-shrink-0" />
<div className="text-xs text-amber-800">
<p className="font-semibold mb-1">Important:</p>
<ul className="space-y-1 list-disc list-inside">
<li>Ensure the new amount is verified and approved</li>
<li>This change will be logged in the activity trail</li>
<li>Budget blocking (IO) may need to be adjusted</li>
</ul>
</div>
</div>
</div>
</div>
<DialogFooter>
<Button
variant="outline"
onClick={handleClose}
disabled={submitting}
>
Cancel
</Button>
<Button
onClick={handleSubmit}
disabled={submitting || !amount || parseFloat(amount) <= 0}
className="bg-green-600 hover:bg-green-700"
>
{submitting ? 'Updating...' : 'Update Amount'}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}