ui/ux improvement
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
import type { DeliveryRow, OrderRow, TenantLocation } from '@/api/types';
|
||||
import { KpiCard } from '@/components/KpiCard';
|
||||
import { Tab, TabBar } from '@/components/TabBar';
|
||||
import { useSelection, type Selection } from '@/components/useSelection';
|
||||
import { Panel } from '@/components/Panel';
|
||||
import { TablePager } from '@/components/TablePager';
|
||||
@@ -231,80 +232,69 @@ export function DispatchBoard({ scope }: { scope: DispatchScope }) {
|
||||
|
||||
return (
|
||||
<div className="dispatch-container">
|
||||
{/* ── Unified Strategy & Operations Toolbar (xpressconsole #strat-row style) ── */}
|
||||
<div id="strat-row" className="strat-row">
|
||||
<div className="strat-tabs">
|
||||
<button
|
||||
type="button"
|
||||
className={`sbt ${mode === 'riders' ? 'active' : ''}`}
|
||||
onClick={() => changeMode('riders')}
|
||||
>
|
||||
<span className="sbt-icon"><Bike size={15} /></span>
|
||||
<span>By Rider</span>
|
||||
<span className="sbt-badge">{totals.riders}</span>
|
||||
</button>
|
||||
{/* The view switcher, on the console's own segmented control.
|
||||
|
||||
These six were `.sbt` — a seventh treatment of "tab" in this app:
|
||||
bordered when idle, a solid brand fill with a purple glow when
|
||||
selected. They now read exactly like the view tabs on Sales, Users,
|
||||
Inventory and the rest.
|
||||
|
||||
The `.strat-row` card around them is gone too. It was a bordered,
|
||||
shadowed toolbar whose only remaining child was this strip — the
|
||||
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' ? (
|
||||
<Tab
|
||||
label="By customer"
|
||||
icon={<Users size={14} />}
|
||||
isActive={mode === 'customers'}
|
||||
onClick={() => changeMode('customers')}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className={`sbt ${mode === 'stores' ? 'active' : ''}`}
|
||||
onClick={() => changeMode('stores')}
|
||||
>
|
||||
<span className="sbt-icon"><Store size={15} /></span>
|
||||
<span>By Store</span>
|
||||
<span className="sbt-badge">{branches.length}</span>
|
||||
</button>
|
||||
|
||||
{/* 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' ? (
|
||||
<button
|
||||
type="button"
|
||||
className={`sbt ${mode === 'customers' ? 'active' : ''}`}
|
||||
onClick={() => changeMode('customers')}
|
||||
>
|
||||
<span className="sbt-icon"><Users size={15} /></span>
|
||||
<span>By Customer</span>
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className={`sbt ${mode === 'active' ? 'active' : ''}`}
|
||||
onClick={() => changeMode('active')}
|
||||
>
|
||||
<span className="sbt-icon"><Radio size={15} /></span>
|
||||
<span>Active Fleet</span>
|
||||
<span className="sbt-dot-live" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className={`sbt ${mode === 'timing' ? 'active' : ''}`}
|
||||
onClick={() => changeMode('timing')}
|
||||
>
|
||||
<span className="sbt-icon"><Timer size={15} /></span>
|
||||
<span>Plan vs Actual</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className={`sbt ${mode === 'profit' ? 'active' : ''}`}
|
||||
onClick={() => changeMode('profit')}
|
||||
>
|
||||
<span className="sbt-icon"><IndianRupee size={15} /></span>
|
||||
<span>Unit Economics</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* No operations cluster.
|
||||
What stood here was a hub picker with one hard-coded hub, a demo /
|
||||
live toggle, a rider count read off the mock fleet, and a profit
|
||||
chip computed as `value * 0.28` labelled "(84%)" — a number with no
|
||||
source. All four described the page rather than the day's work, and
|
||||
three of them were not true. The KPI row below carries the figures
|
||||
that come from the data. */}
|
||||
</div>
|
||||
{/* 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 same four-card row every other page uses — same `kpi-grid`, same
|
||||
|
||||
Reference in New Issue
Block a user