yslootahrobotics/.github/prompts/plan-adminDashboardAuthCrudEnhancements.prompt.md
Najjar\NajjarV02 05b540997e 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

117 lines
6.0 KiB
Markdown

# 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)
6. **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
7. **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)
8. **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
9. **Analytics overview cards** at top of admin page
- Total revenue (from Stripe)
- Number of orders
- Most popular persona
- Most popular color
10. **Configurator settings** section
- Edit default color (`#96a2b6`)
- Toggle available color options
- Set min/max price boundaries
11. **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**