A screenshot at phone width showed an "INVOICE | LINES | TOTAL | STATUS" header row while the data under LINES was money. The header and its data cell had drifted apart: the earlier pass hid the Lines <td> but not the matching <th>, because the loop that added the hide classes only matched text-left headers and Lines is text-right. So the Total values rendered under a heading that named a column which no longer existed. The same screenshot showed the totals clipped — "41,710.50" reading as "710,50". With only three columns left, the 520px min-width was still forcing a sideways scroll, and the opaque sticky first column then sat on top of the left of the money values. The mobile floor is gone, so the three remaining columns size to their content, and the sticky and status gutters are trimmed at mobile widths to let them fit 375px. Below sm the table is now exactly Invoice, Total, Status — and every header matches a visible cell. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
138 lines
5.6 KiB
TypeScript
138 lines
5.6 KiB
TypeScript
import "./globals.css";
|
|
import type { Metadata } from "next";
|
|
import Link from "next/link";
|
|
import {
|
|
LayoutDashboard,
|
|
Truck,
|
|
TrendingUp,
|
|
Wrench,
|
|
Wallet,
|
|
LineChart as LineChartIcon,
|
|
Receipt,
|
|
Boxes,
|
|
} from "lucide-react";
|
|
import { Sidebar, type NavItem } from "@/components/Sidebar";
|
|
import { ThemeProvider } from "@/components/ThemeProvider";
|
|
import { ThemeToggle } from "@/components/ThemeToggle";
|
|
import { GlobalSearch } from "@/components/GlobalSearch";
|
|
import { getAssets } from "@/lib/data";
|
|
|
|
// The layout itself reads PocketBase (GlobalSearch needs the asset list), so it
|
|
// must be dynamic too — otherwise Next prerenders the built-in /_not-found page,
|
|
// which inherits this layout, and the build fails without a reachable database.
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Mega Plant Dashboard",
|
|
description: "Mega Plant cost & P&L dashboard",
|
|
manifest: "/manifest.json",
|
|
themeColor: "#30638E",
|
|
appleWebApp: {
|
|
title: "Mega Plant",
|
|
capable: true,
|
|
statusBarStyle: "default",
|
|
},
|
|
icons: {
|
|
icon: [
|
|
{ url: "/icons/favicon-32.png", sizes: "32x32" },
|
|
{ url: "/icons/icon-192.png", sizes: "192x192" },
|
|
{ url: "/icons/icon-512.png", sizes: "512x512" },
|
|
],
|
|
apple: [
|
|
{ url: "/icons/icon-192.png", sizes: "192x192" },
|
|
{ url: "/icons/icon-512.png", sizes: "512x512" },
|
|
],
|
|
},
|
|
};
|
|
|
|
const navItems: NavItem[] = [
|
|
{ kind: "link", href: "/", label: "Dashboard", icon: <LayoutDashboard className="w-4 h-4" /> },
|
|
{ kind: "link", href: "/plant", label: "Plant Register", icon: <Boxes className="w-4 h-4" /> },
|
|
{
|
|
kind: "group",
|
|
label: "Income",
|
|
icon: <TrendingUp className="w-4 h-4" />,
|
|
children: [
|
|
{ href: "/income", label: "Overview" },
|
|
{ href: "/income/invoices", label: "Invoices" },
|
|
],
|
|
},
|
|
{ kind: "link", href: "/running", label: "Running Costs", icon: <Wrench className="w-4 h-4" /> },
|
|
{
|
|
kind: "group",
|
|
label: "Expenses",
|
|
icon: <Wallet className="w-4 h-4" />,
|
|
children: [
|
|
{ href: "/expenses", label: "Overview" },
|
|
{ href: "/expenses/vehicles", label: "Vehicle Costs" },
|
|
{ href: "/expenses/finance", label: "Finance (Bastion)" },
|
|
{ href: "/expenses/personnel", label: "Personnel" },
|
|
{ href: "/expenses/subscriptions", label: "Subscriptions" },
|
|
{ href: "/expenses/rent", label: "Rent & Utilities" },
|
|
{ href: "/expenses/petty-cash", label: "Cash Floats" },
|
|
],
|
|
},
|
|
{ kind: "link", href: "/overheads", label: "Overheads Roll-up", icon: <Receipt className="w-4 h-4" /> },
|
|
{ kind: "link", href: "/charts", label: "Machine Charts", icon: <LineChartIcon className="w-4 h-4" /> },
|
|
];
|
|
|
|
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
const assets = await getAssets();
|
|
return (
|
|
<html lang="en" suppressHydrationWarning>
|
|
<head>
|
|
{/* Part 4: Next 16 emits apple-mobile-web-app-status-bar-style but NOT apple-mobile-web-app-capable.
|
|
Without this tag, iOS Add-to-Home-Screen opens in Safari instead of standalone. */}
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-title" content="Mega Plant" />
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png" />
|
|
<link rel="icon" type="image/png" sizes="64x64" href="/icons/favicon.png" />
|
|
<link rel="apple-touch-icon" href="/icons/icon-192.png" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
|
|
{/* Umami analytics — website id 86d0bd41-e705-4677-af2d-a4228e7c4b95 */}
|
|
<script
|
|
defer
|
|
src="https://umami-vmyngbmelll45wokwr270wbx.169.239.180.130.sslip.io/script.js"
|
|
data-website-id="86d0bd41-e705-4677-af2d-a4228e7c4b95"
|
|
/>
|
|
</head>
|
|
<body className="min-h-screen">
|
|
<ThemeProvider>
|
|
<header className="sticky top-0 z-30 h-16 bg-white/80 dark:bg-bg/80 backdrop-blur border-b border-gray-200 dark:border-border">
|
|
<div className="flex items-center gap-3 sm:gap-6 px-4 sm:px-6 h-full">
|
|
<Link href="/" className="flex items-center gap-2 shrink-0">
|
|
<img
|
|
src="/brand/logo.png"
|
|
alt="Mega Plant"
|
|
className="w-9 h-9 rounded-xl object-contain bg-white dark:bg-bg shadow-sm"
|
|
/>
|
|
<div className="leading-tight hidden sm:block">
|
|
<div className="text-sm font-semibold text-[#003D5B] dark:text-white">Mega Plant</div>
|
|
<div className="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Overheads 2026</div>
|
|
</div>
|
|
</Link>
|
|
|
|
<GlobalSearch assets={assets.map((a) => ({
|
|
id: a.id, code: a.code, name: a.name, category: a.category, supplier: a.supplier,
|
|
}))} />
|
|
|
|
<div className="flex items-center gap-3 shrink-0">
|
|
<div className="hidden md:flex items-center gap-2 px-3 py-1.5 rounded-xl bg-gradient-to-br from-[#30638E] to-[#003D5B] text-white shadow-lg shadow-blue-900/20">
|
|
<span className="text-xs uppercase tracking-wider text-white/70">FY</span>
|
|
<span className="text-sm font-semibold">2026</span>
|
|
</div>
|
|
<ThemeToggle />
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div className="flex">
|
|
<Sidebar items={navItems} />
|
|
<main className="flex-1 min-w-0">{children}</main>
|
|
</div>
|
|
</ThemeProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|