23cb057f0b
Wave 1: 07-01-PLAN.md — Unified services table (audit trail, backfill, validation) Wave 2: 07-02-PLAN.md — Admin catalog CRUD rewire (preserve historical references) Ready for execution: /gsd-execute-phase 7 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
237 lines
7.9 KiB
Markdown
237 lines
7.9 KiB
Markdown
---
|
|
plan_id: 06-01
|
|
phase: 6
|
|
wave: 1
|
|
title: "Sidebar layout — AdminSidebar + AppShell + move client list to /admin/clients"
|
|
type: execute
|
|
depends_on: []
|
|
files_modified:
|
|
- src/app/admin/layout.tsx
|
|
- src/components/admin/NavBar.tsx
|
|
- src/app/admin/page.tsx
|
|
- src/app/admin/clients/page.tsx
|
|
- src/components/admin/AdminSidebar.tsx
|
|
requirements_addressed: [UX-01, UX-03]
|
|
autonomous: true
|
|
must_haves:
|
|
truths:
|
|
- "AdminLayout uses a flex-row shell: sidebar left (fixed width) + main content right"
|
|
- "NavBar.tsx is replaced by AdminSidebar.tsx — header nav no longer exists"
|
|
- "AdminSidebar has links: Dashboard, Clienti, Progetti, Offerte, Forecast, Catalogo, Impostazioni + Logout at bottom"
|
|
- "Active route is highlighted in the sidebar (usePathname)"
|
|
- "Client list (previously at /admin) is now at /admin/clients with identical functionality"
|
|
- "/admin page exists but shows a placeholder or redirects — replaced in 06-02 with real dashboard"
|
|
artifacts:
|
|
- path: "src/components/admin/AdminSidebar.tsx"
|
|
provides: "Sidebar client component with navigation links and logout"
|
|
contains: "usePathname, signOut, all nav links"
|
|
- path: "src/app/admin/layout.tsx"
|
|
provides: "AppShell layout: flex row, sidebar + main"
|
|
contains: "AdminSidebar, flex, min-h-screen"
|
|
- path: "src/app/admin/clients/page.tsx"
|
|
provides: "Client list page moved from /admin"
|
|
contains: "getAllClientsWithPayments"
|
|
key_links:
|
|
- from: "src/components/admin/AdminSidebar.tsx"
|
|
to: "src/app/admin/layout.tsx"
|
|
via: "import"
|
|
pattern: "AdminSidebar"
|
|
---
|
|
|
|
<objective>
|
|
Replace the top header NavBar with a persistent left sidebar. Move the client list from /admin to /admin/clients. The /admin route will be a blank placeholder for now — the real dashboard comes in 06-02.
|
|
|
|
This is a pure layout + routing refactor. No data model changes. No new queries.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/Users/simonecavalli/IAMCAVALLI/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/Users/simonecavalli/IAMCAVALLI/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@/Users/simonecavalli/IAMCAVALLI/.planning/ROADMAP.md
|
|
@/Users/simonecavalli/IAMCAVALLI/.planning/STATE.md
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Create AdminSidebar component</name>
|
|
<files>src/components/admin/AdminSidebar.tsx</files>
|
|
|
|
<read_first>
|
|
- src/components/admin/NavBar.tsx — copy links and logout logic
|
|
- src/app/admin/layout.tsx — understand current layout
|
|
</read_first>
|
|
|
|
<action>
|
|
Create `src/components/admin/AdminSidebar.tsx` as a client component:
|
|
|
|
```tsx
|
|
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { usePathname } from "next/navigation";
|
|
import { signOut } from "next-auth/react";
|
|
import {
|
|
LayoutDashboard,
|
|
Users,
|
|
FolderOpen,
|
|
Tag,
|
|
TrendingUp,
|
|
BookOpen,
|
|
Settings,
|
|
LogOut,
|
|
} from "lucide-react";
|
|
|
|
const NAV_ITEMS = [
|
|
{ href: "/admin", label: "Dashboard", icon: LayoutDashboard, exact: true },
|
|
{ href: "/admin/clients", label: "Clienti", icon: Users },
|
|
{ href: "/admin/projects", label: "Progetti", icon: FolderOpen },
|
|
{ href: "/admin/offers", label: "Offerte", icon: Tag },
|
|
{ href: "/admin/forecast", label: "Forecast", icon: TrendingUp },
|
|
{ href: "/admin/catalog", label: "Catalogo", icon: BookOpen },
|
|
{ href: "/admin/impostazioni", label: "Impostazioni", icon: Settings },
|
|
];
|
|
|
|
export function AdminSidebar() {
|
|
const pathname = usePathname();
|
|
|
|
const isActive = (href: string, exact?: boolean) =>
|
|
exact ? pathname === href : pathname === href || pathname.startsWith(href + "/");
|
|
|
|
return (
|
|
<aside className="w-56 shrink-0 min-h-screen bg-[#1A463C] flex flex-col">
|
|
{/* Logo */}
|
|
<div className="px-5 py-5 border-b border-white/10">
|
|
<span className="font-bold text-white tracking-tight text-sm">iamcavalli</span>
|
|
</div>
|
|
|
|
{/* Nav links */}
|
|
<nav className="flex-1 px-3 py-4 flex flex-col gap-0.5">
|
|
{NAV_ITEMS.map(({ href, label, icon: Icon, exact }) => {
|
|
const active = isActive(href, exact);
|
|
return (
|
|
<Link
|
|
key={href}
|
|
href={href}
|
|
className={`flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors ${
|
|
active
|
|
? "bg-white/15 text-white font-medium"
|
|
: "text-white/65 hover:text-white hover:bg-white/10"
|
|
}`}
|
|
>
|
|
<Icon size={16} strokeWidth={1.8} />
|
|
{label}
|
|
</Link>
|
|
);
|
|
})}
|
|
</nav>
|
|
|
|
{/* Logout */}
|
|
<div className="px-3 py-4 border-t border-white/10">
|
|
<button
|
|
onClick={() => signOut({ callbackUrl: "/admin/login" })}
|
|
className="flex items-center gap-3 px-3 py-2 w-full rounded-md text-sm text-white/65 hover:text-white hover:bg-white/10 transition-colors"
|
|
>
|
|
<LogOut size={16} strokeWidth={1.8} />
|
|
Esci
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
);
|
|
}
|
|
```
|
|
|
|
Check that `lucide-react` is already a dependency (`package.json`). If not, note it as a deviation but do NOT install it — shadcn/ui already bundles it transitively in this project.
|
|
</action>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Update AdminLayout to AppShell (sidebar + main)</name>
|
|
<files>src/app/admin/layout.tsx</files>
|
|
|
|
<action>
|
|
Replace the current vertical layout (nav on top, max-w-5xl centered main) with a horizontal AppShell:
|
|
|
|
```tsx
|
|
import { AdminSidebar } from "@/components/admin/AdminSidebar";
|
|
import { getServerSession } from "next-auth";
|
|
import { authOptions } from "@/lib/auth";
|
|
|
|
export default async function AdminLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
const session = await getServerSession(authOptions);
|
|
return (
|
|
<div className="flex min-h-screen bg-gray-50">
|
|
{session && <AdminSidebar />}
|
|
<main className="flex-1 px-8 py-8 overflow-y-auto">
|
|
{children}
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
Remove the import of NavBar. The sidebar handles all navigation.
|
|
</action>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Move client list to /admin/clients/page.tsx</name>
|
|
<files>src/app/admin/clients/page.tsx, src/app/admin/page.tsx</files>
|
|
|
|
<read_first>
|
|
- src/app/admin/page.tsx — full content to copy
|
|
- src/app/admin/clients/ — check if page.tsx already exists
|
|
</read_first>
|
|
|
|
<action>
|
|
1. Copy the full content of `src/app/admin/page.tsx` to `src/app/admin/clients/page.tsx`.
|
|
Update the "Nuovo cliente" link href if it points to `/admin/clients/new` — it should already be correct.
|
|
Update the "Mostra archiviati" toggle link from `?archived=1` on `/admin` to `/admin/clients?archived=1`.
|
|
|
|
2. Replace `src/app/admin/page.tsx` with a minimal redirect placeholder for now (dashboard content comes in 06-02):
|
|
|
|
```tsx
|
|
import { redirect } from "next/navigation";
|
|
|
|
// Dashboard page — content added in Phase 6 Plan 02
|
|
export default function AdminRoot() {
|
|
redirect("/admin/clients");
|
|
}
|
|
```
|
|
|
|
This keeps the app functional during the transition: clicking Dashboard in the sidebar goes to /admin which redirects to /admin/clients until the real dashboard exists.
|
|
</action>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 4: Delete NavBar.tsx and verify TypeScript builds</name>
|
|
<files>src/components/admin/NavBar.tsx</files>
|
|
|
|
<action>
|
|
Delete `src/components/admin/NavBar.tsx` since it is fully replaced by AdminSidebar.
|
|
|
|
Run `npx tsc --noEmit` to verify no TypeScript errors. If NavBar is imported anywhere else, remove those imports.
|
|
|
|
Run `npm run build` to confirm the Next.js build passes.
|
|
</action>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
- [ ] `npx tsc --noEmit` passes with no errors
|
|
- [ ] `npm run build` completes successfully
|
|
- [ ] Sidebar renders with all 7 nav links + logout button
|
|
- [ ] Active link is visually highlighted
|
|
- [ ] `/admin/clients` loads the client list correctly
|
|
- [ ] `/admin` redirects to `/admin/clients`
|
|
- [ ] No references to NavBar remain in the codebase
|
|
</verification>
|