From 049f5fb841c585c587f423648d157b54a7790204 Mon Sep 17 00:00:00 2001 From: makearmy Date: Sat, 27 Sep 2025 15:28:02 -0400 Subject: [PATCH] added sub-tabs for 'additions' --- app/portal/projects/page.tsx | 7 +-- app/portal/rigs/page.tsx | 6 +-- components/portal/ProjectsSwitcher.tsx | 74 ++++++++++++++++++++++++++ components/portal/RigsSwitcher.tsx | 71 ++++++++++++++++++++++++ components/portal/SettingsSwitcher.tsx | 50 +++++++++-------- 5 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 components/portal/ProjectsSwitcher.tsx create mode 100644 components/portal/RigsSwitcher.tsx diff --git a/app/portal/projects/page.tsx b/app/portal/projects/page.tsx index b1589194..1794b2d1 100644 --- a/app/portal/projects/page.tsx +++ b/app/portal/projects/page.tsx @@ -1,5 +1,5 @@ // app/portal/projects/page.tsx -import ProjectsPage from "@/app/projects/page"; +import ProjectsSwitcher from "@/components/portal/ProjectsSwitcher"; export const metadata = { title: "MakerDash • Projects" }; @@ -7,10 +7,7 @@ export default function ProjectsPortalPage() { return (

Projects

-
- {/* Render canonical projects page directly (Server Component OK) */} - -
+
); } diff --git a/app/portal/rigs/page.tsx b/app/portal/rigs/page.tsx index 390faf0c..129a6bc9 100644 --- a/app/portal/rigs/page.tsx +++ b/app/portal/rigs/page.tsx @@ -1,5 +1,5 @@ // app/portal/rigs/page.tsx -import RigsListClient from "@/app/rigs/RigsListClient"; +import RigsSwitcher from "@/components/portal/RigsSwitcher"; export const metadata = { title: "MakerDash • Rigs" }; @@ -7,9 +7,7 @@ export default function RigsPortalPage() { return (

Rigs

-
- -
+
); } diff --git a/components/portal/ProjectsSwitcher.tsx b/components/portal/ProjectsSwitcher.tsx new file mode 100644 index 00000000..c4ba4fa2 --- /dev/null +++ b/components/portal/ProjectsSwitcher.tsx @@ -0,0 +1,74 @@ +// components/portal/ProjectsSwitcher.tsx +"use client"; + +import { useRouter, useSearchParams } from "next/navigation"; +import dynamic from "next/dynamic"; +import { cn } from "@/lib/utils"; + +// Canonical viewer page; use dynamic in a client component +const ProjectsView = dynamic(() => import("@/app/projects/page"), { ssr: false }); + +const TABS = [ + { key: "list", label: "Projects" }, +{ key: "add", label: "Add Project" }, +]; + +function Panel({ tab }: { tab: string }) { + switch (tab) { + case "list": + return ( +
+ +
+ ); + case "add": + return ( +
+

Add Project

+
+ Project submission form will be embedded here. We’ll wire to an authenticated endpoint (e.g. POST /api/my/projects) and auto-assign owner. +
+ +
+ ); + default: + return null; + } +} + +export default function ProjectsSwitcher() { + const router = useRouter(); + const sp = useSearchParams(); + const active = sp.get("t") || "list"; + + function setTab(nextKey: string) { + const q = new URLSearchParams(sp.toString()); + q.set("t", nextKey); + router.replace(`/portal/projects?${q.toString()}`, { scroll: false }); + } + + return ( +
+
+ {TABS.map(({ key, label }) => ( + + ))} +
+ + +
+ ); +} diff --git a/components/portal/RigsSwitcher.tsx b/components/portal/RigsSwitcher.tsx new file mode 100644 index 00000000..a75b02f0 --- /dev/null +++ b/components/portal/RigsSwitcher.tsx @@ -0,0 +1,71 @@ +// components/portal/RigsSwitcher.tsx +"use client"; + +import { useRouter, useSearchParams } from "next/navigation"; +import { cn } from "@/lib/utils"; +import RigsListClient from "@/app/rigs/RigsListClient"; + +const TABS = [ + { key: "my", label: "My Rigs" }, +{ key: "add", label: "Add Rig" }, +]; + +function Panel({ tab }: { tab: string }) { + switch (tab) { + case "my": + return ( +
+ +
+ ); + case "add": + // Placeholder: we’ll retrofit the builder (or a minimal create form) next sprint + return ( +
+
+ Add Rig form will go here. We’ll wire to POST /api/my/rigs with user auth. +
+ +
+ ); + default: + return null; + } +} + +export default function RigsSwitcher() { + const router = useRouter(); + const sp = useSearchParams(); + const active = sp.get("t") || "my"; + + function setTab(nextKey: string) { + const q = new URLSearchParams(sp.toString()); + q.set("t", nextKey); + router.replace(`/portal/rigs?${q.toString()}`, { scroll: false }); + } + + return ( +
+
+ {TABS.map(({ key, label }) => ( + + ))} +
+ + +
+ ); +} diff --git a/components/portal/SettingsSwitcher.tsx b/components/portal/SettingsSwitcher.tsx index cf1b2f02..01060648 100644 --- a/components/portal/SettingsSwitcher.tsx +++ b/components/portal/SettingsSwitcher.tsx @@ -5,36 +5,42 @@ import { useRouter, useSearchParams } from "next/navigation"; import dynamic from "next/dynamic"; import { cn } from "@/lib/utils"; -/** - * IMPORTANT: - * We dynamically import the existing settings pages so you do NOT have to move their contents. - * These imports point directly at your canonical routes: - * /app/settings/fiber/page.tsx - * /app/settings/uv/page.tsx - * /app/settings/co2-galvo/page.tsx - * /app/settings/co2-gantry/page.tsx - * - * If any of those filenames differ, update the paths below accordingly. - */ -const FiberPanel = dynamic(() => import("@/app/settings/fiber/page"), { ssr: false }); -const UVPanel = dynamic(() => import("@/app/settings/uv/page"), { ssr: false }); -const CO2GalvoPanel = dynamic(() => import("@/app/settings/co2-galvo/page"), { ssr: false }); +// Use existing canonical pages; dynamic imports in a client component are OK +const FiberPanel = dynamic(() => import("@/app/settings/fiber/page"), { ssr: false }); +const UVPanel = dynamic(() => import("@/app/settings/uv/page"), { ssr: false }); +const CO2GalvoPanel = dynamic(() => import("@/app/settings/co2-galvo/page"), { ssr: false }); const CO2GantryPanel = dynamic(() => import("@/app/settings/co2-gantry/page"), { ssr: false }); const TABS = [ - { key: "fiber", label: "Fiber" }, -{ key: "uv", label: "UV" }, -{ key: "co2-galvo", label: "CO₂ Galvo" }, + { key: "fiber", label: "Fiber" }, +{ key: "uv", label: "UV" }, { key: "co2-gantry", label: "CO₂ Gantry" }, +{ key: "co2-galvo", label: "CO₂ Galvo" }, +{ key: "add", label: "Add Setting" }, // new ]; function Panel({ tab }: { tab: string }) { switch (tab) { - case "fiber": return ; - case "uv": return ; - case "co2-galvo": return ; + case "fiber": return ; + case "uv": return ; + case "co2-galvo": return ; case "co2-gantry": return ; - default: return ; + case "add": + return ( +
+

Add Setting

+
+ Submission form will be embedded here. We’ll retrofit your existing public submission to require auth and record owner. +
+
    +
  • Route: POST /api/my/settings/:type (fiber|uv|co2-gantry|co2-galvo)
  • +
  • Server adds owner using /users/me via bearer
  • +
  • On success: toast + refresh current view tab
  • +
+
+ ); + default: + return ; } } @@ -51,7 +57,6 @@ export default function SettingsSwitcher() { return (
- {/* sub-tabs */}
{TABS.map(({ key, label }) => (