/** * 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 { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Loader2, Receipt, X, RotateCcw } from 'lucide-react'; import { getCreditNoteByRequestId, cancelForm16Submission, setForm16ResubmissionNeeded, generateForm16CreditNoteManually, } 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' | 'credit' | null>(null); const [generateCnOpen, setGenerateCnOpen] = useState(false); const [generateCnAmount, setGenerateCnAmount] = useState(''); const form16 = request?.form16Submission; const hasSubmission = !!form16; const hasCreditNote = !!creditNote && creditNote.status !== 'withdrawn'; const suggestedAmount = form16?.tdsAmount != null ? Number(form16.tdsAmount) : undefined; 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); } }; const handleGenerateCreditNote = async () => { const amount = parseFloat(generateCnAmount); if (!requestId || Number.isNaN(amount) || amount <= 0) { toast.error('Enter a valid amount to generate credit note'); return; } setActionLoading('credit'); try { await generateForm16CreditNoteManually(requestId, amount); setGenerateCnOpen(false); setGenerateCnAmount(''); toast.success('Credit note generated (manually approved)'); const note = await getCreditNoteByRequestId(requestId); setCreditNote(note ? { id: typeof note.id === 'number' ? note.id : Number(note.id), status: note.status || '' } : null); onRefresh?.(); } catch (e) { toast.error(e instanceof Error ? e.message : 'Failed to generate credit note'); } finally { setActionLoading(null); } }; if (loading || !hasSubmission || hasCreditNote) return null; return ( <> Form 16 actions View the document in the Documents tab. Cancel submission, mark resubmission needed, or generate credit note (e.g. when OCR was partial). Generate credit note (manual) Enter the amount for the credit note. This will mark the Form 16 as manually approved.
setGenerateCnAmount(e.target.value)} /> {suggestedAmount != null && (

Suggested from submission TDS amount: ₹{suggestedAmount.toLocaleString('en-IN')}

)}
); }