Re_Figma_Code/src/custom/components/request-detail/Form16QuickActions.tsx
2026-03-12 15:34:19 +05:30

118 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Form 16 Quick Actions RE actions for the Quick Actions sidebar.
* Shown only for Form 16 requests when RE user and no credit note yet.
* Location: custom (Form 16 only); does not modify shared workflow components.
*/
import { useState, useEffect } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Loader2, Receipt, X, RotateCcw } from 'lucide-react';
import {
getCreditNoteByRequestId,
cancelForm16Submission,
setForm16ResubmissionNeeded,
} from '@/services/form16Api';
import { toast } from 'sonner';
interface Form16QuickActionsProps {
requestId: string;
request: any;
onRefresh?: () => void;
}
export function Form16QuickActions({ requestId, request, onRefresh }: Form16QuickActionsProps) {
const [creditNote, setCreditNote] = useState<{ id: number; status: string } | null>(null);
const [loading, setLoading] = useState(true);
const [actionLoading, setActionLoading] = useState<'cancel' | 'resubmit' | null>(null);
const form16 = request?.form16Submission;
const hasSubmission = !!form16;
const hasCreditNote = !!creditNote && creditNote.status !== 'withdrawn';
useEffect(() => {
if (!requestId) {
setLoading(false);
return;
}
let cancelled = false;
(async () => {
try {
const note = await getCreditNoteByRequestId(requestId);
if (!cancelled) setCreditNote(note ? { id: typeof note.id === 'number' ? note.id : Number(note.id), status: note.status || '' } : null);
} catch {
if (!cancelled) setCreditNote(null);
} finally {
if (!cancelled) setLoading(false);
}
})();
return () => { cancelled = true; };
}, [requestId]);
const handleCancelSubmission = async () => {
if (!requestId || !window.confirm('Cancel this Form 16 submission? The request will be marked as rejected.')) return;
setActionLoading('cancel');
try {
await cancelForm16Submission(requestId);
toast.success('Submission cancelled');
onRefresh?.();
} catch (e) {
toast.error(e instanceof Error ? e.message : 'Failed to cancel submission');
} finally {
setActionLoading(null);
}
};
const handleResubmissionNeeded = async () => {
if (!requestId || !window.confirm('Mark this submission as resubmission needed? The dealer will need to resubmit Form 16.')) return;
setActionLoading('resubmit');
try {
await setForm16ResubmissionNeeded(requestId);
toast.success('Marked as resubmission needed');
onRefresh?.();
} catch (e) {
toast.error(e instanceof Error ? e.message : 'Failed to update');
} finally {
setActionLoading(null);
}
};
if (loading || !hasSubmission || hasCreditNote) return null;
return (
<Card className="border-blue-200 bg-blue-50/30" data-testid="form16-quick-actions-card">
<CardHeader className="pb-2">
<CardTitle className="text-sm flex items-center gap-2 text-blue-800">
<Receipt className="w-4 h-4" />
Form 16 actions
</CardTitle>
<CardDescription className="text-xs text-gray-600">
View the document in the Documents tab. Cancel submission or mark resubmission needed.
</CardDescription>
</CardHeader>
<CardContent className="space-y-2">
<Button
variant="outline"
size="sm"
className="w-full justify-start border-red-300 text-red-700 hover:bg-red-50"
onClick={handleCancelSubmission}
disabled={!!actionLoading}
>
{actionLoading === 'cancel' ? <Loader2 className="w-3 h-3 animate-spin mr-1" /> : <X className="w-3 h-3 mr-1" />}
Cancel submission
</Button>
<Button
variant="outline"
size="sm"
className="w-full justify-start border-amber-300 text-amber-700 hover:bg-amber-50"
onClick={handleResubmissionNeeded}
disabled={!!actionLoading}
>
{actionLoading === 'resubmit' ? <Loader2 className="w-3 h-3 animate-spin mr-1" /> : <RotateCcw className="w-3 h-3 mr-1" />}
Resubmission needed
</Button>
</CardContent>
</Card>
);
}