472573a1a8
Terminal (PRD 5.3/5.5): - Opens with no network: a service worker caches the app shell and build assets, and the last confirmed session and product list are kept on the phone. Only a definitive 401/403 sends the cashier to the login page. - The offline queue is keyed by cashier and branch, sends only the signed-in cashier's sales, chunks to the server's batch limit, and acts on the per-sale result: synced, or rejected with the reason shown and never retried. Rows from the old queue are adopted on first sync. - Several products per sale (tap to add), optional customer details, and a printable receipt. The banner shows sales waiting to sync and any that need attention; sign-out warns about unsynced sales. - M-Pesa only appears when FEATURE_MPESA is on. A timed-out prompt now tells the cashier not to take cash until the payment is checked, instead of reporting it as failed. Admin: - New Stock page: stock per branch with low/out flags, physical counts and adjustments, inter-branch transfers, morning dispatch and evening count entry, and recent movements. - Dashboard shows stock on hand per branch and links to Stock. - Staff page can deactivate and reactivate accounts. - Products page is read-only for branch managers and edits the low-stock alert level. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
44 lines
1.6 KiB
TypeScript
44 lines
1.6 KiB
TypeScript
import type { Metadata, Viewport } from "next";
|
|
import "./globals.css";
|
|
import { ToastProvider } from "@/components/ui/Toast";
|
|
import ServiceWorkerRegister from "@/components/ServiceWorkerRegister";
|
|
|
|
// NOTE: We deliberately do NOT use `next/font/google` here. That loader
|
|
// downloads the font files from Google at *build time*, which fails in
|
|
// restricted CI/build environments (e.g. Render) with
|
|
// "TypeError: Cannot read properties of null (reading '1')". Instead we
|
|
// load the same fonts via a standard <link> at runtime. The matching CSS
|
|
// variables (--font-display / --font-body / --font-mono) are declared in
|
|
// globals.css, so the typography is unchanged.
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Vessel \u2014 Branch Delivery Console",
|
|
description: "Multi-branch 20L jerrycan delivery & payment operations",
|
|
};
|
|
|
|
export const viewport: Viewport = {
|
|
width: "device-width",
|
|
initialScale: 1,
|
|
maximumScale: 1,
|
|
themeColor: "#0C0C0C",
|
|
};
|
|
|
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<html lang="en">
|
|
<head>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;700&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
</head>
|
|
<body>
|
|
<ServiceWorkerRegister />
|
|
<ToastProvider>{children}</ToastProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|