yslootahrobotics/.github/prompts/plan-adminDashboardAuthCrudEnhancements.prompt.md
Najjar\NajjarV02 05b540997e
Some checks are pending
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions
feat: add admin authentication and management features
- Implemented Prisma schema with models for AdminUser, AppSettings, and Snapshot.
- Created seed script to initialize the database with an admin user and JWT secret.
- Developed admin login page with form handling and error management.
- Added API routes for admin login, logout, change password, and JWT verification.
- Integrated Stripe for payment intent management in admin orders.
- Established middleware for protecting admin routes with JWT authentication.
- Created Zustand stores for managing persona and snapshot states.
2026-04-13 17:57:59 +04:00

6.0 KiB

Plan: Admin Dashboard Auth + CRUD + Enhancements

TL;DR

Add password authentication to the admin dashboard, enable full CRUD for personas/pricing, and add useful admin features like order analytics and configurator settings management.

Phase 1: Admin Authentication (Database-backed with Prisma + SQLite)

Steps

  1. Setup Prisma + SQLite

    • Install prisma and @prisma/client
    • Create prisma/schema.prisma with SQLite provider
    • Models: AdminUser (id, username, passwordHash, createdAt), AppSettings (key, value)
    • Run npx prisma db push to create the database
    • Create src/lib/prisma.ts — singleton Prisma client
  2. Create seed script prisma/seed.ts

    • Creates default admin user with bcrypt-hashed password
    • Generates and stores JWT secret in AppSettings table
    • Run with npx prisma db seed
  3. Create admin auth API routes

    • src/app/api/admin/login/route.ts — POST, accepts { username, password }, verifies bcrypt hash from DB, returns JWT in httpOnly cookie (JWT secret from DB)
    • src/app/api/admin/verify/route.ts — GET, checks JWT cookie validity
    • src/app/api/admin/logout/route.ts — POST, clears auth cookie
    • src/app/api/admin/change-password/route.ts — POST, accepts { currentPassword, newPassword }, updates hash in DB
  4. Create admin middleware src/middleware.ts

    • Protects all /admin/* routes (except /admin/login/)
    • Checks for valid JWT cookie, redirects to /admin/login/ if missing/invalid
    • Note: middleware can't use Prisma directly (edge runtime), so JWT secret needs to be in env OR verify via API call
  5. Create admin login page src/app/admin/login/page.tsx

    • Username + password form (styled to match existing admin design)
    • Calls login API, redirects to /admin/ on success
    • Shows error on wrong credentials
  6. Add JWT_SECRET to .env.local (only this one — password is in DB)

    • Alternative: store JWT secret in DB and load at startup into a module-level cache

Dependencies to install

  • prisma (dev), @prisma/client, bcryptjs, @types/bcryptjs (dev), jose

Phase 2: Full CRUD for Pricing Items + Personas

Steps (depends on Phase 1)

  1. Add/Remove pricing items in admin — Update src/app/admin/page.tsx

    • "Add Item" button with fields: id (auto-slug from label), label, price
    • Delete button per row (with confirmation)
    • Update usePricingStore to support addItem() and removeItem() actions
  2. Persona management section — New section in admin page

    • List current personas with edit capability (label, description, colors)
    • Add new persona form
    • Delete persona button
    • Create usePersonaStore or extend usePricingStore to manage persona definitions
    • Sync persona list with ConfigPanel's PERSONA_OPTIONS (currently hardcoded)

Phase 3: Additional Admin Features

Steps (parallel with Phase 2)

  1. Orders dashboard section — New section in admin page

    • Show orders from Stripe API (list recent payments)
    • Display: order ID, customer email, amount, status, date
    • New API route src/app/api/admin/orders/route.ts to fetch from Stripe
  2. Analytics overview cards at top of admin page

    • Total revenue (from Stripe)
    • Number of orders
    • Most popular persona
    • Most popular color
  3. Configurator settings section

    • Edit default color (#96a2b6)
    • Toggle available color options
    • Set min/max price boundaries
  4. Logout button in admin header

Relevant Files

  • src/app/admin/page.tsx — Main admin dashboard (add CRUD UI, analytics)
  • src/app/admin/login/page.tsx — New login page
  • src/app/api/admin/login/route.ts — New auth API
  • src/app/api/admin/verify/route.ts — New verify API
  • src/app/api/admin/orders/route.ts — New orders API
  • src/middleware.ts — New, protects admin routes
  • src/lib/prisma.ts — New, Prisma client singleton
  • prisma/schema.prisma — New, database schema (AdminUser, AppSettings)
  • prisma/seed.ts — New, seeds default admin user
  • src/store/usePricingStore.ts — Add addItem(), removeItem() actions
  • src/components/ConfigPanel.tsx — Persona options currently hardcoded (PERSONA_OPTIONS const)
  • .env.local — Add ADMIN_PASSWORD, ADMIN_JWT_SECRET

Verification

  1. Visit /admin/ without login → redirected to /admin/login/
  2. Enter wrong password → error message shown
  3. Enter correct password → redirected to /admin/
  4. Add a pricing item → appears in configurator pricing breakdown
  5. Remove a pricing item → disappears from pricing
  6. Edit persona → reflected in ConfigPanel
  7. Orders section shows real Stripe payment data
  8. Refresh admin page → still logged in (cookie persists)
  9. Run npx vitest run → all existing tests pass

Decisions

  • Database: Prisma + SQLite — file-based, no external server needed, real ORM
  • Admin password stored as bcrypt hash in DB (not in env vars)
  • JWT secret stored in AppSettings table in DB
  • JWT in httpOnly cookie — secure, no localStorage tokens
  • jose library for JWT — lightweight, edge-compatible (works in Next.js middleware)
  • Personas need to move from hardcoded array to store-driven — breaking change in ConfigPanel
  • Stripe orders fetched via Stripe API directly — no local DB needed for orders

Further Considerations

  1. Persona storage: Currently hardcoded in ConfigPanel. Moving to a store means ConfigPanel reads from store dynamically. This is required for admin CRUD to work. Recommended: create persona store with localStorage persistence (same pattern as pricing store)
  2. Stripe orders vs local orders: Currently orders only exist client-side. To show in admin, we fetch from Stripe's payment intents list. Recommended: use Stripe API directly, no local DB needed
  3. Multi-admin support: Currently single password. If needed later, can upgrade to NextAuth with credentials provider. Recommended: start simple, upgrade if needed