feat: replace native alerts with react-hot-toast notifications and update rider plan constants
This commit is contained in:
@@ -9,10 +9,11 @@ import {
|
|||||||
CheckCircle, XCircle, ArrowLeft, Save, Printer, Send,
|
CheckCircle, XCircle, ArrowLeft, Save, Printer, Send,
|
||||||
MessageSquare, Edit, UserCheck, Wallet, Store, Globe, Calendar, Briefcase, Plus, Upload
|
MessageSquare, Edit, UserCheck, Wallet, Store, Globe, Calendar, Briefcase, Plus, Upload
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
type ApplicationSource = 'app' | 'web' | 'walkin' | 'referral';
|
type ApplicationSource = 'app' | 'web' | 'walkin' | 'referral';
|
||||||
type KYCType = 'biker' | 'investor' | 'swapstation' | 'merchant' | 'general';
|
type KYCType = 'biker' | 'investor' | 'swapstation' | 'merchant' | 'general';
|
||||||
type RiderPlan = 'daily_rent' | 'weekly_rent' | 'monthly_rent' | 'rent_to_own' | 'share_ev';
|
type RiderPlan = 'single_rent' | 'rent_to_own' | 'share_ev';
|
||||||
type VerificationStage = 'application' | 'document_collection' | 'risk_check' | 'plan_selection' | 'payment' | 'agreement' | 'allocated' | 'active';
|
type VerificationStage = 'application' | 'document_collection' | 'risk_check' | 'plan_selection' | 'payment' | 'agreement' | 'allocated' | 'active';
|
||||||
|
|
||||||
interface Document {
|
interface Document {
|
||||||
@@ -310,7 +311,7 @@ export default function KYCDetailPage() {
|
|||||||
} : null);
|
} : null);
|
||||||
setNewMessageText('');
|
setNewMessageText('');
|
||||||
setShowMessageModal(false);
|
setShowMessageModal(false);
|
||||||
alert(`Message sent to ${request.phone}`);
|
toast.success(`SMS sent to ${request.phone}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddDocument = () => {
|
const handleAddDocument = () => {
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ import {
|
|||||||
Upload, CheckCircle, XCircle, Camera, AlertTriangle, Edit, Globe, Wallet, Calendar,
|
Upload, CheckCircle, XCircle, Camera, AlertTriangle, Edit, Globe, Wallet, Calendar,
|
||||||
CreditCard, FileSignature, MapPinned, Key, BatteryCharging, Briefcase, Plus
|
CreditCard, FileSignature, MapPinned, Key, BatteryCharging, Briefcase, Plus
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
export type ApplicationSource = 'app' | 'web' | 'walkin' | 'referral';
|
export type ApplicationSource = 'app' | 'web' | 'walkin' | 'referral';
|
||||||
export type KYCType = 'biker' | 'investor' | 'swapstation' | 'merchant' | 'general';
|
export type KYCType = 'biker' | 'investor' | 'swapstation' | 'merchant' | 'general';
|
||||||
export type RiderPlan = 'daily_rent' | 'weekly_rent' | 'monthly_rent' | 'rent_to_own' | 'share_ev';
|
export type RiderPlan = 'single_rent' | 'rent_to_own' | 'share_ev';
|
||||||
export type VerificationStage = 'application' | 'document_collection' | 'risk_check' | 'plan_selection' | 'payment' | 'agreement' | 'allocated' | 'active';
|
export type VerificationStage = 'application' | 'document_collection' | 'risk_check' | 'plan_selection' | 'payment' | 'agreement' | 'allocated' | 'active';
|
||||||
|
|
||||||
interface NomineeDetails {
|
interface NomineeDetails {
|
||||||
@@ -352,12 +353,12 @@ export default function RequestsPage() {
|
|||||||
return req;
|
return req;
|
||||||
});
|
});
|
||||||
setRequests(updatedRequests);
|
setRequests(updatedRequests);
|
||||||
alert('Document approved!');
|
toast.success('Document approved!');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRejectDocument = (docId: string, reason: string) => {
|
const handleRejectDocument = (docId: string, reason: string) => {
|
||||||
if (!selectedRequest || !reason.trim()) {
|
if (!selectedRequest || !reason.trim()) {
|
||||||
alert('Please enter a reason for rejection');
|
toast.error('Please enter a reason for rejection');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const updatedRequests = requests.map(req => {
|
const updatedRequests = requests.map(req => {
|
||||||
@@ -373,7 +374,7 @@ export default function RequestsPage() {
|
|||||||
});
|
});
|
||||||
setRequests(updatedRequests);
|
setRequests(updatedRequests);
|
||||||
setRejectReason('');
|
setRejectReason('');
|
||||||
alert('Document rejected!');
|
toast.error('Document rejected!');
|
||||||
};
|
};
|
||||||
|
|
||||||
const filteredRequests = requests.filter(req => {
|
const filteredRequests = requests.filter(req => {
|
||||||
@@ -410,7 +411,7 @@ export default function RequestsPage() {
|
|||||||
setRequests(updatedRequests);
|
setRequests(updatedRequests);
|
||||||
setShowMessageModal(false);
|
setShowMessageModal(false);
|
||||||
setMessageText('');
|
setMessageText('');
|
||||||
alert(`Message sent to ${selectedRequest.phone}: "${messageText}"`);
|
toast.success(`SMS sent to ${selectedRequest.phone}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -444,7 +445,7 @@ export default function RequestsPage() {
|
|||||||
);
|
);
|
||||||
setRequests(updatedRequests);
|
setRequests(updatedRequests);
|
||||||
setShowActionModal(false);
|
setShowActionModal(false);
|
||||||
alert(successMessage);
|
toast.success(successMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -1099,7 +1100,7 @@ export default function RequestsPage() {
|
|||||||
};
|
};
|
||||||
setRequests([newRequest, ...requests]);
|
setRequests([newRequest, ...requests]);
|
||||||
setShowNewApplicationModal(false);
|
setShowNewApplicationModal(false);
|
||||||
alert('Application created successfully!');
|
toast.success('Application created successfully!');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -1674,68 +1675,68 @@ function NewApplicationModal({ isOpen, onClose, onSave }: { isOpen: boolean; onC
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formData.type === 'biker' && (
|
{formData.type === 'biker' && (
|
||||||
<div className="bg-amber-50/80 p-4 rounded-xl border border-amber-100">
|
<div className="bg-amber-50/80 p-4 rounded-xl border border-amber-100">
|
||||||
<h4 className="font-semibold text-amber-900 mb-3 flex items-center gap-2 text-sm">
|
<h4 className="font-semibold text-amber-900 mb-3 flex items-center gap-2 text-sm">
|
||||||
<Key className="w-4 h-4" /> Driving License
|
<Key className="w-4 h-4" /> Driving License
|
||||||
</h4>
|
</h4>
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs font-medium text-slate-600 mb-1 block">License Number *</label>
|
<label className="text-xs font-medium text-slate-600 mb-1 block">License Number *</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.drivingLicense.number}
|
value={formData.drivingLicense.number}
|
||||||
onChange={(e) => updateField('drivingLicense.number', e.target.value)}
|
onChange={(e) => updateField('drivingLicense.number', e.target.value)}
|
||||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
placeholder="License number"
|
placeholder="License number"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs font-medium text-slate-600 mb-1 block">Class *</label>
|
<label className="text-xs font-medium text-slate-600 mb-1 block">Class *</label>
|
||||||
<select
|
<select
|
||||||
value={formData.drivingLicense.class}
|
value={formData.drivingLicense.class}
|
||||||
onChange={(e) => updateField('drivingLicense.class', e.target.value)}
|
onChange={(e) => updateField('drivingLicense.class', e.target.value)}
|
||||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white"
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white"
|
||||||
>
|
>
|
||||||
<option value="">Select Class</option>
|
<option value="">Select Class</option>
|
||||||
<option value="C">Class C</option>
|
<option value="C">Class C</option>
|
||||||
<option value="D">Class D</option>
|
<option value="D">Class D</option>
|
||||||
<option value="E">Class E</option>
|
<option value="E">Class E</option>
|
||||||
<option value="F">Class F</option>
|
<option value="F">Class F</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs font-medium text-slate-600 mb-1 block">Status *</label>
|
<label className="text-xs font-medium text-slate-600 mb-1 block">Status *</label>
|
||||||
<select
|
<select
|
||||||
value={formData.drivingLicense.status}
|
value={formData.drivingLicense.status}
|
||||||
onChange={(e) => updateField('drivingLicense.status', e.target.value)}
|
onChange={(e) => updateField('drivingLicense.status', e.target.value)}
|
||||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white"
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white"
|
||||||
>
|
>
|
||||||
<option value="not_applied">Not Applied</option>
|
<option value="not_applied">Not Applied</option>
|
||||||
<option value="applied">Applied</option>
|
<option value="applied">Applied</option>
|
||||||
<option value="issued">Issued</option>
|
<option value="issued">Issued</option>
|
||||||
<option value="expired">Expired</option>
|
<option value="expired">Expired</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs font-medium text-slate-600 mb-1 block">Issue Date *</label>
|
<label className="text-xs font-medium text-slate-600 mb-1 block">Issue Date *</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.drivingLicense.issueDate}
|
value={formData.drivingLicense.issueDate}
|
||||||
onChange={(e) => updateField('drivingLicense.issueDate', e.target.value)}
|
onChange={(e) => updateField('drivingLicense.issueDate', e.target.value)}
|
||||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs font-medium text-slate-600 mb-1 block">Expiry Date *</label>
|
<label className="text-xs font-medium text-slate-600 mb-1 block">Expiry Date *</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.drivingLicense.expiryDate}
|
value={formData.drivingLicense.expiryDate}
|
||||||
onChange={(e) => updateField('drivingLicense.expiryDate', e.target.value)}
|
onChange={(e) => updateField('drivingLicense.expiryDate', e.target.value)}
|
||||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -2217,7 +2218,7 @@ function NewApplicationModal({ isOpen, onClose, onSave }: { isOpen: boolean; onC
|
|||||||
</h4>
|
</h4>
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4">
|
||||||
{[
|
{[
|
||||||
{ v: 'daily_rent', l: 'Single Rent', d: 'Single person rental plan', icon: Bike },
|
{ v: 'single_rent', l: 'Single Rent', d: 'Single person rental plan', icon: Bike },
|
||||||
{ v: 'rent_to_own', l: 'Rent to Own', d: 'Own after X months', icon: Key },
|
{ v: 'rent_to_own', l: 'Rent to Own', d: 'Own after X months', icon: Key },
|
||||||
{ v: 'share_ev', l: 'Share EV', d: 'Shared bike', icon: Users },
|
{ v: 'share_ev', l: 'Share EV', d: 'Shared bike', icon: Users },
|
||||||
].map(plan => (
|
].map(plan => (
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
|
|||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import Sidebar from "@/components/Sidebar";
|
import Sidebar from "@/components/Sidebar";
|
||||||
|
import { Toaster } from "react-hot-toast";
|
||||||
|
|
||||||
const inter = Inter({
|
const inter = Inter({
|
||||||
variable: "--font-inter",
|
variable: "--font-inter",
|
||||||
@@ -25,6 +26,7 @@ export default function RootLayout({
|
|||||||
<main className="lg:ml-64 min-h-screen">
|
<main className="lg:ml-64 min-h-screen">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
<Toaster position="top-right" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user