feat(shift): two-pane shift history — list + per-shift activity log, timeframe presets
Rework the shift screen into a master/detail view on /shift: the shift CONTROL (open/close, drawer vouchers, X-report) on top, then a two-pane history below — shift list on the LEFT, the selected shift's signed activity log on the RIGHT. - Timeframe presets replace the bare from/to inputs: Yesterday / Last week / Last month / All / Custom (custom reveals the date pickers). Filters the shift list by start time. - Activity log = every ledger event in the selected shift's [start, end] window (entries, exits, payments, vouchers, anomalies, the Z-report), rendered like the booth live feed (same EVENT_STYLE), with the shift's drawer reconciliation in the pane header. - Scope unchanged + enforced SERVER-SIDE: an operator sees only their own shifts (no operator filter); an admin (shift:cash) sees all + the operator filter. The list auto-selects the newest shift. API: /api/events gains an optional `until` (ISO) upper bound so a shift's window can be fetched ([start,end]); fetchEvents passes it. Verified on live data: a closed shift window returns just its 20 events out of 260. Build+lint 12/12 (i18n parity). The same component also backs /setup/shifts. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
+13
-3
@@ -344,9 +344,19 @@ const shiftRoute = createRoute({
|
||||
path: "/shift",
|
||||
component: function ShiftRoute() {
|
||||
const { user } = rootRoute.useRouteContext();
|
||||
// The drawer-voucher form is operator-RAISED (shift:create); an admin still has
|
||||
// to authorize each voucher with their password server-side.
|
||||
return <ShiftControl canVoucher={can(user, "shift:create")} />;
|
||||
// Top: the shift CONTROL (open/close, drawer vouchers, X-report). The drawer-voucher
|
||||
// form is operator-RAISED (shift:create); an admin authorizes with their password.
|
||||
// Below: the shift LIST + per-shift activity log (scoped server-side by permission).
|
||||
return (
|
||||
<div className="mx-auto max-w-6xl px-4 py-4">
|
||||
<ShiftControl canVoucher={can(user, "shift:create")} />
|
||||
{can(user, "shift:read") && (
|
||||
<div className="mt-6">
|
||||
<ShiftsHistory user={user} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user