ui/ux on catalogue

This commit is contained in:
2026-09-18 19:19:34 +05:30
parent 041dc37861
commit 93735e232a
7 changed files with 259 additions and 94 deletions

View File

@@ -22,6 +22,7 @@ import {
import type { DeliveryRow, OrderRow, TenantLocation } from '@/api/types';
import { KpiCard } from '@/components/KpiCard';
import { Tab, TabBar } from '@/components/TabBar';
import { StickyRow } from '@/components/StickyRow';
import { useSelection, type Selection } from '@/components/useSelection';
import { Panel } from '@/components/Panel';
import { TablePager } from '@/components/TablePager';
@@ -244,57 +245,62 @@ export function DispatchBoard({ scope }: { scope: DispatchScope }) {
operations cluster beside it was removed earlier — and a card holding
nothing but a tab track is a box drawn round a box. Every other page
stands its switcher directly on the page. */}
<TabBar aria-label="Dispatch views">
<Tab
label="By rider"
icon={<Bike size={14} />}
count={totals.riders || undefined}
isActive={mode === 'riders'}
onClick={() => changeMode('riders')}
/>
<Tab
label="By store"
icon={<Store size={14} />}
count={branches.length || undefined}
isActive={mode === 'stores'}
onClick={() => changeMode('stores')}
/>
{/* A shop's customer book is its own. Grouping a partner's rounds by
customer would mean reading every merchant's book to put a name to
a phone number, so the tab is not offered on a partner board. */}
{scope.kind === 'tenant' ? (
{/* Held under the nav bar while the board scrolls. Dispatch builds its
own switcher instead of going through `PageHeader`, so it asks for
the behaviour directly — same component, same row, same canvas. */}
<StickyRow>
<TabBar aria-label="Dispatch views">
<Tab
label="By customer"
icon={<Users size={14} />}
isActive={mode === 'customers'}
onClick={() => changeMode('customers')}
label="By rider"
icon={<Bike size={14} />}
count={totals.riders || undefined}
isActive={mode === 'riders'}
onClick={() => changeMode('riders')}
/>
) : null}
<Tab
label="By store"
icon={<Store size={14} />}
count={branches.length || undefined}
isActive={mode === 'stores'}
onClick={() => changeMode('stores')}
/>
{/* A shop's customer book is its own. Grouping a partner's rounds by
customer would mean reading every merchant's book to put a name to
a phone number, so the tab is not offered on a partner board. */}
{scope.kind === 'tenant' ? (
<Tab
label="By customer"
icon={<Users size={14} />}
isActive={mode === 'customers'}
onClick={() => changeMode('customers')}
/>
) : null}
{/* The three below group the day differently from the three above:
those slice the same stops by whose they are, these report on how
the day went. The rule in the track says so. */}
<Tab
label="Active fleet"
icon={<Radio size={14} />}
isActive={mode === 'active'}
onClick={() => changeMode('active')}
isGroupStart
isLive
/>
<Tab
label="Plan vs actual"
icon={<Timer size={14} />}
isActive={mode === 'timing'}
onClick={() => changeMode('timing')}
/>
<Tab
label="Unit economics"
icon={<IndianRupee size={14} />}
isActive={mode === 'profit'}
onClick={() => changeMode('profit')}
/>
</TabBar>
{/* The three below group the day differently from the three above:
those slice the same stops by whose they are, these report on how
the day went. The rule in the track says so. */}
<Tab
label="Active fleet"
icon={<Radio size={14} />}
isActive={mode === 'active'}
onClick={() => changeMode('active')}
isGroupStart
isLive
/>
<Tab
label="Plan vs actual"
icon={<Timer size={14} />}
isActive={mode === 'timing'}
onClick={() => changeMode('timing')}
/>
<Tab
label="Unit economics"
icon={<IndianRupee size={14} />}
isActive={mode === 'profit'}
onClick={() => changeMode('profit')}
/>
</TabBar>
</StickyRow>
{/* The same four-card row every other page uses — same `kpi-grid`, same