feat: optimize KYC action buttons for mobile layout and add approval modal support
This commit is contained in:
@@ -3,10 +3,9 @@ import withPWAInit from "@ducanh2912/next-pwa";
|
||||
|
||||
const withPWA = withPWAInit({
|
||||
dest: "public",
|
||||
disable: false, // Explicitly enabling PWA even in development mode per user request
|
||||
disable: false,
|
||||
register: true,
|
||||
skipWaiting: true,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
images: {
|
||||
@@ -18,6 +17,7 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
turbopack: {},
|
||||
};
|
||||
|
||||
export default withPWA(nextConfig);
|
||||
@@ -254,6 +254,7 @@ export default function KYCDetailPage() {
|
||||
const [editForm, setEditForm] = useState<Partial<Request>>({});
|
||||
const [showMessageModal, setShowMessageModal] = useState(false);
|
||||
const [showAddNoteModal, setShowAddNoteModal] = useState(false);
|
||||
const [showApproveModal, setShowApproveModal] = useState(false);
|
||||
const [newNoteText, setNewNoteText] = useState('');
|
||||
const [newMessageText, setNewMessageText] = useState('');
|
||||
const [showAddDocModal, setShowAddDocModal] = useState(false);
|
||||
@@ -409,82 +410,86 @@ export default function KYCDetailPage() {
|
||||
</div>
|
||||
<p className="text-slate-500 mt-1">{request.name} • {request.submittedAt}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
|
||||
<div className="flex flex-col sm:flex-row sm:flex-wrap gap-2">
|
||||
{editMode ? (
|
||||
<>
|
||||
<button onClick={handleSaveEdit} className="px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center gap-2">
|
||||
<Save className="w-4 h-4" /> Save
|
||||
<button onClick={handleSaveEdit} className="flex-1 sm:flex-none px-3 sm:px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center justify-center gap-2">
|
||||
<Save className="w-4 h-4" /> <span>Save</span>
|
||||
</button>
|
||||
<button onClick={() => { setEditForm(request); setEditMode(false); }} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
|
||||
<button onClick={() => { setEditForm(request); setEditMode(false); }} className="flex-1 sm:flex-none px-3 sm:px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{request.type === 'biker' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create biker profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved', verificationStage: 'active' } : null);
|
||||
alert('Biker created successfully!');
|
||||
}
|
||||
}}
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm hover:bg-blue-700 flex items-center gap-2"
|
||||
>
|
||||
<Bike className="w-4 h-4" /> Make Biker
|
||||
{/* Top Row on Mobile: Make [Type] Button */}
|
||||
<div className="flex gap-2 w-full sm:w-auto">
|
||||
{request.type === 'biker' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => setShowApproveModal(true)}
|
||||
className="flex-1 sm:flex-none px-3 sm:px-4 py-2 bg-blue-600 text-white rounded-lg text-sm hover:bg-blue-700 flex items-center justify-center gap-2"
|
||||
>
|
||||
<Bike className="w-4 h-4" /> <span>Make Biker</span>
|
||||
</button>
|
||||
)}
|
||||
{request.type === 'investor' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create investor profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved' } : null);
|
||||
alert('Investor created successfully!');
|
||||
}
|
||||
}}
|
||||
className="flex-1 sm:flex-none px-3 sm:px-4 py-2 bg-purple-600 text-white rounded-lg text-sm hover:bg-purple-700 flex items-center justify-center gap-2"
|
||||
>
|
||||
<DollarSign className="w-4 h-4" /> <span>Make Investor</span>
|
||||
</button>
|
||||
)}
|
||||
{request.type === 'swapstation' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create shop profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved' } : null);
|
||||
alert('Shop created successfully!');
|
||||
}
|
||||
}}
|
||||
className="flex-1 sm:flex-none px-3 sm:px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center justify-center gap-2"
|
||||
>
|
||||
<Store className="w-4 h-4" /> <span>Make Shop</span>
|
||||
</button>
|
||||
)}
|
||||
{request.type === 'merchant' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create merchant profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved' } : null);
|
||||
alert('Merchant created successfully!');
|
||||
}
|
||||
}}
|
||||
className="flex-1 sm:flex-none px-3 sm:px-4 py-2 bg-orange-600 text-white rounded-lg text-sm hover:bg-orange-700 flex items-center justify-center gap-2"
|
||||
>
|
||||
<User className="w-4 h-4" /> <span>Make Merchant</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Bottom Row on Mobile: Edit, Note, SMS */}
|
||||
<div className="flex gap-2 w-full sm:w-auto">
|
||||
<button onClick={() => setEditMode(true)} className="flex-1 sm:flex-none px-3 sm:px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50 flex items-center justify-center gap-2">
|
||||
<Edit className="w-4 h-4" /> <span>Edit</span>
|
||||
</button>
|
||||
)}
|
||||
{request.type === 'investor' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create investor profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved' } : null);
|
||||
alert('Investor created successfully!');
|
||||
}
|
||||
}}
|
||||
className="px-4 py-2 bg-purple-600 text-white rounded-lg text-sm hover:bg-purple-700 flex items-center gap-2"
|
||||
>
|
||||
<DollarSign className="w-4 h-4" /> Make Investor
|
||||
<button onClick={() => setShowAddNoteModal(true)} className="flex-1 sm:flex-none px-3 sm:px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50 flex items-center justify-center gap-2">
|
||||
<MessageSquare className="w-4 h-4" /> <span>Note</span>
|
||||
</button>
|
||||
)}
|
||||
{request.type === 'swapstation' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create shop profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved' } : null);
|
||||
alert('Shop created successfully!');
|
||||
}
|
||||
}}
|
||||
className="px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center gap-2"
|
||||
>
|
||||
<Store className="w-4 h-4" /> Make Shop
|
||||
<button onClick={() => setShowMessageModal(true)} className="flex-1 sm:flex-none px-3 sm:px-4 py-2 bg-accent text-white rounded-lg text-sm hover:bg-accent/90 flex items-center justify-center gap-2">
|
||||
<Send className="w-4 h-4" /> <span>SMS</span>
|
||||
</button>
|
||||
)}
|
||||
{request.type === 'merchant' && request.status !== 'approved' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Approve this request and create merchant profile?')) {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved' } : null);
|
||||
alert('Merchant created successfully!');
|
||||
}
|
||||
}}
|
||||
className="px-4 py-2 bg-orange-600 text-white rounded-lg text-sm hover:bg-orange-700 flex items-center gap-2"
|
||||
>
|
||||
<User className="w-4 h-4" /> Make Merchant
|
||||
</button>
|
||||
)}
|
||||
<button onClick={() => setEditMode(true)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50 flex items-center gap-2">
|
||||
<Edit className="w-4 h-4" /> Edit
|
||||
</button>
|
||||
<button onClick={() => setShowAddNoteModal(true)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50 flex items-center gap-2">
|
||||
<MessageSquare className="w-4 h-4" /> Note
|
||||
</button>
|
||||
<button onClick={() => setShowMessageModal(true)} className="px-4 py-2 bg-accent text-white rounded-lg text-sm hover:bg-accent/90 flex items-center gap-2">
|
||||
<Send className="w-4 h-4" /> SMS
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -771,6 +776,27 @@ export default function KYCDetailPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showApproveModal && (
|
||||
<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-slate-800">Approve Request</h3>
|
||||
<button onClick={() => setShowApproveModal(false)} className="text-slate-400 hover:text-slate-600">×</button>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<p className="text-sm text-slate-700 mb-4">Approve this request and create biker profile?</p>
|
||||
<div className="flex justify-end gap-2">
|
||||
<button onClick={() => setShowApproveModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
|
||||
<button onClick={() => {
|
||||
setRequest(prev => prev ? { ...prev, status: 'approved', verificationStage: 'active' } : null);
|
||||
setShowApproveModal(false);
|
||||
toast.success('Biker created successfully!');
|
||||
}} className="px-4 py-2 bg-blue-600 text-white rounded-lg">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showAddNoteModal && (
|
||||
<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">
|
||||
|
||||
Reference in New Issue
Block a user