feat: replace prompt-based document rejection with a dedicated modal interface
This commit is contained in:
@@ -259,6 +259,10 @@ export default function KYCDetailPage() {
|
|||||||
const [showAddDocModal, setShowAddDocModal] = useState(false);
|
const [showAddDocModal, setShowAddDocModal] = useState(false);
|
||||||
const [newDocName, setNewDocName] = useState('');
|
const [newDocName, setNewDocName] = useState('');
|
||||||
const [showUploadDocModal, setShowUploadDocModal] = useState(false);
|
const [showUploadDocModal, setShowUploadDocModal] = useState(false);
|
||||||
|
|
||||||
|
const [showRejectDocModal, setShowRejectDocModal] = useState(false);
|
||||||
|
const [rejectDocId, setRejectDocId] = useState<string | null>(null);
|
||||||
|
const [rejectReason, setRejectReason] = useState('');
|
||||||
const [uploadDocId, setUploadDocId] = useState<string | null>(null);
|
const [uploadDocId, setUploadDocId] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -333,16 +337,24 @@ export default function KYCDetailPage() {
|
|||||||
} : null);
|
} : null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRejectDocument = (docId: string) => {
|
const openRejectDocModal = (docId: string) => {
|
||||||
const reason = prompt('Enter rejection reason:');
|
setRejectDocId(docId);
|
||||||
if (reason) {
|
setRejectReason('');
|
||||||
|
setShowRejectDocModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRejectDocument = () => {
|
||||||
|
if (!request || !rejectDocId || !rejectReason.trim()) return;
|
||||||
setRequest(prev => prev ? {
|
setRequest(prev => prev ? {
|
||||||
...prev,
|
...prev,
|
||||||
requiredDocuments: prev.requiredDocuments.map(doc =>
|
requiredDocuments: prev.requiredDocuments.map(doc =>
|
||||||
doc.id === docId ? { ...doc, status: 'rejected' as const, rejectedReason: reason } : doc
|
doc.id === rejectDocId ? { ...doc, status: 'rejected' as const, rejectedReason: rejectReason } : doc
|
||||||
)
|
)
|
||||||
} : null);
|
} : null);
|
||||||
}
|
setShowRejectDocModal(false);
|
||||||
|
setRejectDocId(null);
|
||||||
|
setRejectReason('');
|
||||||
|
toast.success('Document rejected');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadDocument = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleUploadDocument = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@@ -654,11 +666,14 @@ export default function KYCDetailPage() {
|
|||||||
{doc.status === 'uploaded' && (
|
{doc.status === 'uploaded' && (
|
||||||
<>
|
<>
|
||||||
<button onClick={() => handleApproveDocument(doc.id)} className="p-1 bg-green-100 text-green-600 rounded hover:bg-green-200" title="Approve"><CheckCircle className="w-4 h-4" /></button>
|
<button onClick={() => handleApproveDocument(doc.id)} className="p-1 bg-green-100 text-green-600 rounded hover:bg-green-200" title="Approve"><CheckCircle className="w-4 h-4" /></button>
|
||||||
<button onClick={() => handleRejectDocument(doc.id)} className="p-1 bg-red-100 text-red-600 rounded hover:bg-red-200" title="Reject"><XCircle className="w-4 h-4" /></button>
|
<button onClick={() => openRejectDocModal(doc.id)} className="p-1 bg-red-100 text-red-600 rounded hover:bg-red-200" title="Reject"><XCircle className="w-4 h-4" /></button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{doc.status === 'approved' && <span className="text-xs px-2 py-1 bg-green-100 text-green-700 rounded-full">Approved</span>}
|
{doc.status === 'approved' && <span className="text-xs px-2 py-1 bg-green-100 text-green-700 rounded-full">Approved</span>}
|
||||||
{doc.status === 'rejected' && <span className="text-xs px-2 py-1 bg-red-100 text-red-700 rounded-full">Rejected</span>}
|
{doc.status === 'rejected' && <span className="text-xs px-2 py-1 bg-red-100 text-red-700 rounded-full">Rejected</span>}
|
||||||
|
{doc.status === 'rejected' && doc.rejectedReason && (
|
||||||
|
<div className="text-xs text-red-600 mt-1 italic">Reason: {doc.rejectedReason}</div>
|
||||||
|
)}
|
||||||
{doc.status === 'pending' && <span className="text-xs px-2 py-1 bg-amber-100 text-amber-700 rounded-full">Pending</span>}
|
{doc.status === 'pending' && <span className="text-xs px-2 py-1 bg-amber-100 text-amber-700 rounded-full">Pending</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -826,6 +841,31 @@ export default function KYCDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showRejectDocModal && (
|
||||||
|
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
||||||
|
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
|
||||||
|
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
|
||||||
|
<h3 className="font-semibold text-red-600">Reject Document</h3>
|
||||||
|
<button onClick={() => setShowRejectDocModal(false)} className="text-slate-400 hover:text-slate-600">×</button>
|
||||||
|
</div>
|
||||||
|
<div className="p-4">
|
||||||
|
<label className="text-sm font-medium text-slate-600 mb-2 block">Rejection Reason</label>
|
||||||
|
<textarea
|
||||||
|
value={rejectReason}
|
||||||
|
onChange={(e) => setRejectReason(e.target.value)}
|
||||||
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
|
rows={4}
|
||||||
|
placeholder="Enter reason for rejection..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
|
||||||
|
<button onClick={() => setShowRejectDocModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
|
||||||
|
<button onClick={handleRejectDocument} disabled={!rejectReason.trim()} className="px-4 py-2 bg-red-600 text-white rounded-lg disabled:opacity-50">Reject</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user