From 7f5c7f3f656c2cd887b006d9ea3ef5cf9e208fdb Mon Sep 17 00:00:00 2001 From: sazzadulalambd Date: Sun, 10 May 2026 17:52:21 +0600 Subject: [PATCH] feat: add inline editing and EV model selection to plan management components --- .../settings/components/PlanSelection.tsx | 785 ++++++++---------- src/app/admin/settings/page.tsx | 92 +- 2 files changed, 403 insertions(+), 474 deletions(-) diff --git a/src/app/admin/settings/components/PlanSelection.tsx b/src/app/admin/settings/components/PlanSelection.tsx index e4ffc7f..8e7273b 100644 --- a/src/app/admin/settings/components/PlanSelection.tsx +++ b/src/app/admin/settings/components/PlanSelection.tsx @@ -1,9 +1,11 @@ 'use client'; import { useState } from 'react'; -import { Plus, Save, Trash2, X } from 'lucide-react'; +import { Plus, Save, Trash2, X, Pencil, Check } from 'lucide-react'; import { CompanySettings } from '../page'; +const EV_MODELS = ['Etron ET50', 'Yadea DT3', 'AIMA Lightning', 'AIMA EM5', 'Yadea G5', 'TVS iQube', 'Bajaj Chetak', 'Hero Photon', 'Okinawa Praise', 'Ampere Magnus', 'Benling Aura', 'Lectrix LXS', 'Revolt RV400']; + interface PlanSelectionProps { settings: CompanySettings; setSettings: React.Dispatch>; @@ -11,6 +13,7 @@ interface PlanSelectionProps { setActivePlanTab: (tab: 'singleRent' | 'rentToOwn' | 'shareEv') => void; handleSave: () => void; addNewPlan: (type: 'singleRent' | 'rentToOwn' | 'shareEv') => void; + isDirty: boolean; } export default function PlanSelection({ @@ -20,8 +23,19 @@ export default function PlanSelection({ setActivePlanTab, handleSave, addNewPlan, + isDirty, }: PlanSelectionProps) { const [deleteModal, setDeleteModal] = useState<{ type: 'singleRent' | 'rentToOwn' | 'shareEv' | null; idx: number | null }>({ type: null, idx: null }); + const [editingPlanId, setEditingPlanId] = useState(null); + const [openDropdown, setOpenDropdown] = useState(null); + + const isAnyEditing = editingPlanId !== null; + const colorMap: Record = { + singleRent: 'blue', + rentToOwn: 'purple', + shareEv: 'green', + }; + const color = colorMap[activePlanTab] || 'blue'; const handleDeletePlan = () => { if (deleteModal.type !== null && deleteModal.idx !== null) { @@ -31,463 +45,338 @@ export default function PlanSelection({ } }; + const renderPlanCard = (plan: CompanySettings['plans']['singleRent'][number] | CompanySettings['plans']['rentToOwn'][number] | CompanySettings['plans']['shareEv'][number], idx: number, type: 'singleRent' | 'rentToOwn' | 'shareEv') => { + const isEditing = editingPlanId === plan.id; + const isColor = color; + const accent = { + blue: { bg: 'bg-blue-600', bgLight: 'bg-blue-50', border: 'border-blue-100', text: 'text-blue-600', textDark: 'text-blue-800', textLight: 'text-blue-100', placeholder: 'placeholder-blue-400' }, + purple: { bg: 'bg-purple-600', bgLight: 'bg-purple-50', border: 'border-purple-100', text: 'text-purple-600', textDark: 'text-purple-800', textLight: 'text-purple-100', placeholder: 'placeholder-purple-400' }, + green: { bg: 'bg-green-600', bgLight: 'bg-green-50', border: 'border-green-100', text: 'text-green-600', textDark: 'text-green-800', textLight: 'text-green-100', placeholder: 'placeholder-green-400' }, + }[isColor]!; + + const inputClass = `w-full px-3 py-2 border border-slate-200 rounded-lg text-sm transition-all ${isEditing ? 'bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 outline-none' : 'bg-slate-50 text-slate-500 cursor-not-allowed'}`; + + const updatePlan = (field: string, value: unknown) => { + const arr = [...(settings.plans[type] as unknown as Record[])]; + arr[idx] = { ...arr[idx], [field]: value }; + setSettings({ ...settings, plans: { ...settings.plans, [type]: arr } }); + }; + + const toggleEvModel = (model: string) => { + const current = plan.evModels as string[]; + const updated = current.includes(model) ? current.filter(m => m !== model) : [...current, model]; + updatePlan('evModels', updated); + }; + + const isShareEv = type === 'shareEv'; + const isRentToOwn = type === 'rentToOwn'; + const depositLabel = isShareEv ? 'Deposit Each (৳)' : 'Deposit (৳)'; + const planAny = plan as Record; + const depositValue = isShareEv ? (planAny.depositEach as number) : (planAny.deposit as number); + const dailyRentLabel = isShareEv ? 'Daily Rent Each (৳)' : 'Daily Rent (৳)'; + const dailyRentField = isShareEv ? (planAny.dailyRentEach as number) : (planAny.dailyRent as number); + + const closeAllDropdowns = () => setOpenDropdown(null); + + return ( +
+
+
+

{plan.name || 'Untitled Plan'} — ৳{dailyRentField}/day

+