From 3e2e9cad3a8bf2cf2aee96447cff62cf8bda86f4 Mon Sep 17 00:00:00 2001 From: dharaneesh-r Date: Sat, 19 Sep 2026 13:00:27 +0530 Subject: [PATCH] updates on the setting page --- src/App.jsx | 2 + src/layouts/AdminLayout.jsx | 68 +++------- src/lib/doormileHooks.js | 2 + src/pages/doormile/customers/Customers.jsx | 18 +-- src/pages/doormile/reports/Profitability.jsx | 30 +++-- src/pages/doormile/settings/Settings.jsx | 129 +++++++++++++++++++ 6 files changed, 179 insertions(+), 70 deletions(-) create mode 100644 src/pages/doormile/settings/Settings.jsx diff --git a/src/App.jsx b/src/App.jsx index 3f80f5f..1b451d8 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -51,6 +51,7 @@ const RidersSummary = lazy(() => import('@/pages/doormile/reports/RidersSummary' const Profitability = lazy(() => import('@/pages/doormile/reports/Profitability')); const ViewProfile = lazy(() => import('@/pages/doormile/ViewProfile')); +const Settings = lazy(() => import('@/pages/doormile/settings/Settings')); const PageFallback = () => (
@@ -148,6 +149,7 @@ const AuthenticatedApp = () => { } /> } /> + } /> diff --git a/src/layouts/AdminLayout.jsx b/src/layouts/AdminLayout.jsx index 1600d95..e589c8f 100644 --- a/src/layouts/AdminLayout.jsx +++ b/src/layouts/AdminLayout.jsx @@ -3,7 +3,7 @@ import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { Activity, Bell, Bike, Car, ChevronDown, Coins, FileSpreadsheet, - FileText, IndianRupee, ListTodo, LogOut, Menu, Search, Settings, Shield, + FileText, ListTodo, LogOut, Menu, Search, Settings, Shield, ShieldAlert, User, UserCheck, Users, Warehouse, } from 'lucide-react'; import { cn } from '@/lib/utils'; @@ -79,27 +79,6 @@ const NAV_GROUPS = [ }, ]; -/* Configuration destinations, kept off the operations bar. - * - * Declared here rather than written inline in the account dropdown because - * two surfaces need them: that dropdown on desktop, and the mobile sheet. - * When they lived only in the dropdown's JSX, moving them off the bar quietly - * removed them from the phone entirely — the sheet builds its list from NAV - * plus NAV_GROUPS, and these were in neither. Both pages stayed routed and - * reachable by typed URL, which is the kind of gap nobody reports and nobody - * finds. - * - * (This replaces an ALL_DESTINATIONS constant that flattened NAV and - * NAV_GROUPS. Its comment claimed it was "what the mobile sheet renders"; the - * sheet had moved to a role-filtered local of the same name in lower case, so - * the constant had no readers at all and would have reintroduced the same - * omission if anyone had trusted it.) - */ -const SETTINGS_NAV = [ - { label: 'Pricing Matrix', path: '/doormile/pricing', icon: IndianRupee }, - { label: 'Customers Directory', path: '/doormile/customers', icon: Users }, -]; - function GlobalSearch() { const navigate = useNavigate(); const [query, setQuery] = useState(''); @@ -492,18 +471,15 @@ export default function AdminLayout() { Change password -
- Settings -
- {SETTINGS_NAV.map((item) => ( - navigate(item.path)} - className="cursor-pointer rounded-xl px-2.5 py-2 font-medium" - > - {item.label} - - ))} + navigate('/doormile/settings')} + className={cn( + 'cursor-pointer rounded-xl px-2.5 py-2 font-medium', + location.pathname.startsWith('/doormile/settings') && 'bg-brand-tint text-brand font-semibold' + )} + > + Settings + logout()} @@ -552,22 +528,16 @@ export default function AdminLayout() { Without this block they existed on the bar's dropdown only, so a phone could not reach Pricing or Customers at all. */}
-
+ setMenuOpen(false)} + className={cn( + 'rounded-lg px-3 py-2.5 text-body-sm font-medium transition-colors', + isActive('/doormile/settings') ? 'bg-brand-tint text-brand font-semibold' : 'text-ink-2 hover:bg-surface-sunken' + )} + > Settings -
- {SETTINGS_NAV.map((item) => ( - setMenuOpen(false)} - className={cn( - 'rounded-lg px-3 py-2.5 text-body-sm font-medium transition-colors', - isActive(item.path) ? 'bg-brand-tint text-brand' : 'text-ink-2 hover:bg-surface-sunken' - )} - > - {item.label} - - ))} +
export const useMilers = (options) => useQuery({ queryKey: KEYS.milers, queryFn: api.getallriders, staleTime: 30_000, ...options }); +export const useRiders = useMilers; + export const useMiler = (id, options) => useQuery({ queryKey: KEYS.miler(id), queryFn: () => api.getMiler(id), enabled: !!id, ...options }); diff --git a/src/pages/doormile/customers/Customers.jsx b/src/pages/doormile/customers/Customers.jsx index afb4a50..23dc123 100644 --- a/src/pages/doormile/customers/Customers.jsx +++ b/src/pages/doormile/customers/Customers.jsx @@ -25,7 +25,7 @@ const custEmail = (row) => row.email || ''; /** Tenant customers carry no booking count; 0 is honest rather than blank. */ const custBookings = (row) => row.totalbookings ?? 0; -export default function Customers() { +export default function Customers({ embedded = false }) { const navigate = useNavigate(); const { data: customers = [], isLoading, isFetching } = useTenantCustomers(); const updateCustomer = useUpdateTenantCustomer(); @@ -141,13 +141,15 @@ export default function Customers() { return ( - navigate('/doormile/customer/create')}> - New customer - - } - /> + {!embedded && ( + navigate('/doormile/customer/create')}> + New customer + + } + /> + )} - e.target.value && setDate(e.target.value)} - aria-label="Report date" - className="w-44" - /> - } - /> + {!embedded && ( + e.target.value && setDate(e.target.value)} + aria-label="Report date" + className="w-44" + /> + } + /> + )} diff --git a/src/pages/doormile/settings/Settings.jsx b/src/pages/doormile/settings/Settings.jsx new file mode 100644 index 0000000..6861b99 --- /dev/null +++ b/src/pages/doormile/settings/Settings.jsx @@ -0,0 +1,129 @@ +import React, { useState, useEffect } from 'react'; +import { useSearchParams, useNavigate } from 'react-router-dom'; +import { motion, AnimatePresence } from 'framer-motion'; +import dayjs from 'dayjs'; +import { TrendingUp, Users, Plus } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { Button, Input } from '@/components/ds'; +import Customers from '@/pages/doormile/customers/Customers'; +import Profitability from '@/pages/doormile/reports/Profitability'; + +const TABS = [ + { id: 'profitability', label: 'Profitability', icon: TrendingUp }, + { id: 'customers', label: 'Customers', icon: Users }, +]; + +export default function Settings() { + const [searchParams, setSearchParams] = useSearchParams(); + const navigate = useNavigate(); + const tabParam = searchParams.get('tab'); + + // Default to 'profitability' or respect ?tab= + const [activeTab, setActiveTab] = useState( + tabParam && TABS.some((t) => t.id === tabParam) ? tabParam : 'profitability' + ); + + // Maintain shared date for Profitability + const [reportDate, setReportDate] = useState(dayjs().format('YYYY-MM-DD')); + + // Sync state if URL query param changes + useEffect(() => { + if (tabParam && TABS.some((t) => t.id === tabParam)) { + setActiveTab(tabParam); + } + }, [tabParam]); + + const handleTabChange = (id) => { + setActiveTab(id); + setSearchParams({ tab: id }); + }; + + return ( +
+ {/* Header — Title and Subtitle */} +
+

+ Settings +

+

+ Workspace configuration and management for Doormile Express. +

+
+ + {/* Unified Toolbar: Segmented Tabs on Left, Tab-Specific Action on Right */} +
+ {/* Pill Segmented Tabs */} +
+ {TABS.map((tab) => { + const Icon = tab.icon; + const isActive = activeTab === tab.id; + return ( + + ); + })} +
+ + {/* Tab Context Action aligned directly on the right */} +
+ {activeTab === 'profitability' && ( + e.target.value && setReportDate(e.target.value)} + aria-label="Report date" + className="w-44 bg-white shadow-xs" + /> + )} + {activeTab === 'customers' && ( + + )} +
+
+ + {/* Tab Panels with seamless integration */} +
+ + + {activeTab === 'profitability' && ( + + )} + {activeTab === 'customers' && } + + +
+
+ ); +}