From 2e7bf23752bb2f22eaa55dc62fa7d90b9aa0405d Mon Sep 17 00:00:00 2001 From: sazzadulalambd Date: Sun, 10 May 2026 02:47:04 +0600 Subject: [PATCH] feat: replace hardcoded rental conditions with dynamic plan configurations and update rental creation flow --- src/app/admin/rentals/page.tsx | 121 +++++++++++++++++++------------- src/app/admin/settings/page.tsx | 24 +++---- 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/src/app/admin/rentals/page.tsx b/src/app/admin/rentals/page.tsx index e3fcf58..9700537 100644 --- a/src/app/admin/rentals/page.tsx +++ b/src/app/admin/rentals/page.tsx @@ -272,12 +272,33 @@ export default function RentalsPage() { const [editPermission, setEditPermission] = useState(false); const [lockPermission, setLockPermission] = useState(false); const [unlockPermission, setUnlockPermission] = useState(false); + const [planConditions, setPlanConditions] = useState<{ + single: { name: string; deposit: number; dailyRate: number; weeklyRate: number; monthlyRate: number; contractMonths: number[] }[]; + shared: { name: string; deposit: number; dailyRate: number; weeklyRate: number; monthlyRate: number; contractMonths: number[] }[]; + 'rent-to-own': { name: string; deposit: number; dailyRate: number; weeklyRate: number; monthlyRate: number; contractMonths: number[] }[]; + }>({ + single: [ + { name: 'Single Rent - Premium', deposit: 25000, dailyRate: 400, weeklyRate: 2800, monthlyRate: 12000, contractMonths: [1, 3, 6, 12] }, + { name: 'Single Rent - Standard', deposit: 20000, dailyRate: 300, weeklyRate: 2100, monthlyRate: 9000, contractMonths: [1, 3, 6, 12] }, + { name: 'Single Rent - Economy', deposit: 15000, dailyRate: 250, weeklyRate: 1750, monthlyRate: 7500, contractMonths: [1, 3, 6, 12] }, + ], + shared: [ + { name: 'Share an EV - Premium', deposit: 20000, dailyRate: 300, weeklyRate: 2100, monthlyRate: 8400, contractMonths: [1, 3, 6, 12] }, + { name: 'Share an EV - Standard', deposit: 15000, dailyRate: 200, weeklyRate: 1400, monthlyRate: 5600, contractMonths: [1, 3, 6, 12] }, + { name: 'Share an EV - Economy', deposit: 12000, dailyRate: 150, weeklyRate: 1050, monthlyRate: 4200, contractMonths: [1, 3, 6, 12] }, + ], + 'rent-to-own': [ + { name: 'Rent to Own - Premium', deposit: 25000, dailyRate: 350, weeklyRate: 2450, monthlyRate: 10500, contractMonths: [12, 18, 24, 36] }, + { name: 'Rent to Own - Standard', deposit: 18000, dailyRate: 250, weeklyRate: 1750, monthlyRate: 7000, contractMonths: [12, 18, 24, 36] }, + { name: 'Rent to Own - Economy', deposit: 15000, dailyRate: 200, weeklyRate: 1400, monthlyRate: 6000, contractMonths: [12, 18, 24, 36] }, + ], + }); const [createStep, setCreateStep] = useState(1); const [newRental, setNewRental] = useState<{ userId: string; type: RentalType; - condition: 'Premium' | 'Standard' | 'Economy'; + planConditionName: string; subscriptionType: 'daily' | 'weekly' | 'monthly'; contractMonths: number; bikeId: string; @@ -287,7 +308,7 @@ export default function RentalsPage() { }>({ userId: '', type: 'single', - condition: 'Standard', + planConditionName: '', subscriptionType: 'daily', contractMonths: 0, bikeId: '', @@ -393,7 +414,7 @@ export default function RentalsPage() { const eligibleUsers = mockUsers.filter(u => u.kycStatus === 'approved' && !u.hasActiveRental); const availableBikes = mockBikes.filter(b => b.status === 'available'); - const selectedSettings = rentalSettings[newRental.type]?.[newRental.condition] || rentalSettings.single.Standard; + const selectedPlan = planConditions[newRental.type]?.find(p => p.name === newRental.planConditionName) || planConditions[newRental.type]?.[0]; const stats = { active: rentals.filter(r => r.status === 'active').length, @@ -411,7 +432,7 @@ export default function RentalsPage() { const bike = mockBikes.find(b => b.id === newRental.bikeId); const user = mockUsers.find(u => u.id === newRental.userId); const hub = mockHubs.find(h => h.id === newRental.hubId); - const settings = rentalSettings[newRental.type]?.[newRental.condition]; + const settings = planConditions[newRental.type]?.find(p => p.name === newRental.planConditionName) || planConditions[newRental.type]?.[0]; const rental: Rental = { id: `RNT-${String(rentals.length + 1).padStart(3, '0')}`, @@ -454,7 +475,7 @@ export default function RentalsPage() { setNewRental({ userId: '', type: 'single', - condition: 'Standard', +planConditionName: planConditions.single[1]?.name || '', subscriptionType: 'daily', contractMonths: 0, bikeId: '', @@ -681,19 +702,33 @@ export default function RentalsPage() {
{createStep === 1 && ( -
-

Step 1: Select User

-

Only KYC-approved users without active rentals are shown.

- +
+

Step 1: Start Date & Hub

+
+
+ + setNewRental({ ...newRental, startDate: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" /> +
+
+ + +
+
+
+ +

Only KYC-approved users without active rentals are shown.

+ +
)} @@ -703,7 +738,7 @@ export default function RentalsPage() {
- -
- {(['Premium', 'Standard', 'Economy'] as const).map(cond => ( - + +
@@ -740,7 +767,7 @@ export default function RentalsPage() { className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" > - {selectedSettings.contractMonths.map(m => ( + {selectedPlan?.contractMonths.map(m => ( ))} @@ -770,11 +797,11 @@ export default function RentalsPage() {
- {newRental.condition} - {newRental.type === 'single' ? 'Single Rent' : newRental.type === 'shared' ? 'Share EV' : 'Rent to Own'} + {newRental.planConditionName}
-

Deposit: ৳{selectedSettings.deposit.toLocaleString()}

+

Deposit: ৳{selectedPlan?.deposit.toLocaleString()}

- Rate: ৳{newRental.subscriptionType === 'daily' ? selectedSettings.dailyRate : newRental.subscriptionType === 'weekly' ? selectedSettings.weeklyRate : selectedSettings.monthlyRate} + Rate: ৳{newRental.subscriptionType === 'daily' ? selectedPlan?.dailyRate : newRental.subscriptionType === 'weekly' ? selectedPlan?.weeklyRate : selectedPlan?.monthlyRate} /{newRental.subscriptionType === 'daily' ? 'day' : newRental.subscriptionType === 'weekly' ? 'week' : 'month'}

@@ -837,12 +864,12 @@ export default function RentalsPage() {

Step 5: Deposit Payment

-

Deposit Amount: ৳{selectedSettings.deposit.toLocaleString()}

+

Deposit Amount: ৳{selectedPlan?.deposit.toLocaleString()}

User: {selectedUser?.name}

Bike: {selectedBike?.model} ({selectedBike?.plate})

Hub: {mockHubs.find(h => h.id === newRental.hubId)?.name}

- {selectedSettings.deposit > 0 && ( + {selectedPlan.deposit > 0 && (
@@ -865,7 +892,7 @@ export default function RentalsPage() {
)} - {selectedSettings.deposit > 0 && ( + {selectedPlan.deposit > 0 && (

Journal Preview

@@ -883,13 +910,13 @@ export default function RentalsPage() { {newRental.depositPaymentMethod === 'bank' && '1100 - Bank'} {newRental.depositPaymentMethod === 'wallet' && '1200 - Biker Wallet'} - + - +
৳{selectedSettings.deposit}৳{selectedPlan.deposit} -
2100 - Deposit Received -৳{selectedSettings.deposit}৳{selectedPlan.deposit}
@@ -925,7 +952,7 @@ export default function RentalsPage() { ) : ( <> - {selectedSettings.deposit > 0 && ( + {selectedPlan.deposit > 0 && ( diff --git a/src/app/admin/settings/page.tsx b/src/app/admin/settings/page.tsx index 0adf4d2..4870650 100644 --- a/src/app/admin/settings/page.tsx +++ b/src/app/admin/settings/page.tsx @@ -2461,8 +2461,8 @@ export default function CompanySettingsPage() {
- - { const updated = [...settings.plans.singleRent]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, singleRent: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Plan Name" /> + + { const updated = [...settings.plans.singleRent]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, singleRent: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Plan Condition" />
@@ -2600,8 +2600,8 @@ export default function CompanySettingsPage() {
- - { const updated = [...settings.plans.rentToOwn]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, rentToOwn: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Plan Name" /> + + { const updated = [...settings.plans.rentToOwn]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, rentToOwn: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Plan Condition" />
@@ -2739,8 +2739,8 @@ export default function CompanySettingsPage() {
- - { const updated = [...settings.plans.shareEv]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, shareEv: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Plan Name" /> + + { const updated = [...settings.plans.shareEv]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, shareEv: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Plan Condition" />
@@ -2891,7 +2891,7 @@ export default function CompanySettingsPage() {
- + setNewInvestName(e.target.value)} placeholder="e.g., 1 Bike Plan" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
@@ -2986,7 +2986,7 @@ export default function CompanySettingsPage() {
- + { const updated = [...settings.plans.investment]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
@@ -3101,7 +3101,7 @@ export default function CompanySettingsPage() {
- + setNewSwapName(e.target.value)} placeholder="e.g., Standard Station" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
@@ -3168,7 +3168,7 @@ export default function CompanySettingsPage() {
- + { const updated = [...settings.plans.swapStation]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, swapStation: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
@@ -3255,7 +3255,7 @@ export default function CompanySettingsPage() {
- + setNewRiderName(e.target.value)} placeholder="e.g., Premium Rider Plan" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
@@ -3334,7 +3334,7 @@ export default function CompanySettingsPage() {
- + { const updated = [...settings.plans.riderRequest]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, riderRequest: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />