#!/usr/bin/env bash echo "🚀 Generating Admin UI (Next.js App Router, JS, Tailwind)..." ### Root paths APP_DIR="src/app/admin" COMP_DIR="src/components/admin" LIB_DIR="lib" # Create directories mkdir -p "$APP_DIR" mkdir -p "$APP_DIR/models/new" mkdir -p "$APP_DIR/models/[id]" mkdir -p "$APP_DIR/parts/new" mkdir -p "$APP_DIR/parts/[id]" mkdir -p "$COMP_DIR" mkdir -p "$LIB_DIR" ############################################ # 1. ADMIN LAYOUT ############################################ cat <<'EOF' > "$APP_DIR/layout.js" import React from "react"; import Link from "next/link"; import "../globals.css"; export default function AdminLayout({ children }) { return (
{children}
); } EOF ############################################ # 2. ADMIN HOME PAGE ############################################ cat <<'EOF' > "$APP_DIR/page.js" import { supabaseServer } from "@/lib/supabaseServer"; export default async function AdminHome() { const { data: models } = await supabaseServer.from("models").select("*"); const { data: parts } = await supabaseServer.from("parts").select("*"); const { data: compat } = await supabaseServer.from("parts_compatible_models").select("*"); return (

Admin Dashboard

Models

{models?.length ?? 0}

Parts

{parts?.length ?? 0}

Compatibility

{compat?.length ?? 0}

); } EOF ############################################ # 3. MODELS LIST PAGE ############################################ cat <<'EOF' > "$APP_DIR/models/page.js" import Link from "next/link"; import { supabaseServer } from "@/lib/supabaseServer"; export default async function ModelsPage() { const { data: models } = await supabaseServer .from("models") .select("*") .order("name"); return (

Models

+ Add Model
{models?.map((m) => (
{m.name}
{m.brand}
))}
); } EOF ############################################ # 4. NEW MODEL PAGE ############################################ cat <<'EOF' > "$APP_DIR/models/new/page.js" "use client"; import { useState } from "react"; import { supabaseBrowser } from "@/lib/supabaseClient"; import { useRouter } from "next/navigation"; export default function NewModelPage() { const [form, setForm] = useState({ name: "", brand: "", scale: "", chassis_type: "", notes: "", }); const router = useRouter(); async function save() { const { error } = await supabaseBrowser.from("models").insert(form); if (!error) router.push("/admin/models"); } return (

Add New Model

{Object.entries(form).map(([key, value]) => (
setForm({ ...form, [key]: e.target.value })} />
))}
); } EOF ############################################ # 5. MODEL DETAIL PAGE ############################################ cat <<'EOF' > "$APP_DIR/models/[id]/page.js" import Link from "next/link"; import { supabaseServer } from "@/lib/supabaseServer"; export default async function ModelDetail({ params }) { const { id } = params; const { data: model } = await supabaseServer .from("models") .select("*") .eq("id", id) .single(); const { data: compat } = await supabaseServer .from("parts_compatible_models") .select("*, parts(*)") .eq("model_id", id); return (

{model?.name}

Brand: {model?.brand}
Scale: {model?.scale}
Chassis: {model?.chassis_type}

Compatible Parts

+ Add Compatible Part
{compat?.map((c) => (
{c.parts.name}
{c.fit_type}
View Part
))}
); } EOF ############################################ # PARTS PAGES (STUBS) ############################################ cat <<'EOF' > "$APP_DIR/parts/page.js" export default function PartsPage() { return (

Parts (UI Coming Next)

List, edit, and link parts here.

); } EOF cat <<'EOF' > "$APP_DIR/parts/new/page.js" export default function NewPartPage() { return (

Add Part (UI Coming Next)

); } EOF ############################################ # SUPABASE CLIENTS ############################################ cat <<'EOF' > "$LIB_DIR/supabaseClient.js" import { createClient } from "@supabase/supabase-js"; export const supabaseBrowser = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ); EOF cat <<'EOF' > "$LIB_DIR/supabaseServer.js" import { createClient } from "@supabase/supabase-js"; export const supabaseServer = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY ); EOF echo "🎉 Admin UI scaffolding complete!"