# Admin Panel Frontend Implementation Plan

## Overview

This document outlines the complete frontend implementation plan for the Admin Panel of the Chowman Durga Puja Quiz & Win application. The admin panel provides administrative functionality for managing users, questions, offers, participants, settings, and viewing dashboard analytics.

## Tech Stack

- **Framework**: React 19 with TypeScript
- **Routing**: Inertia.js (React adapter) with Laravel backend
- **Styling**: Tailwind CSS 4.x with custom components
- **UI Components**: Radix UI primitives + custom components (Button, Card, Input, Alert, etc.)
- **State Management**: React hooks + Inertia.js form helpers
- **Notifications**: Sonner (toast notifications)
- **API Client**: Custom `apiClient` wrapper around fetch with automatic JSON handling
- **Build Tool**: Vite (via vite-plus)

## Project Structure

```
resources/js/
├── app.tsx                    # Inertia app entry point
├── lib/
│   ├── apiClient.ts           # API client with error handling
│   ├── ApiError.ts            # Custom error class
│   └── utils.ts               # Utility functions (cn for classnames)
├── components/
│   └── ui/                    # Reusable UI components
│       ├── button.tsx
│       ├── card.tsx
│       ├── input.tsx
│       ├── alert.tsx
│       ├── label.tsx
│       ├── separator.tsx
│       ├── spinner.tsx
│       ├── sonner.tsx
│       └── input-otp.tsx
├── features/
│   └── admin/
│       ├── auth/
│       │   ├── services/api.ts       # Auth API types & functions
│       │   └── components/           # Auth components (to be created)
│       ├── users/
│       │   ├── services/api.ts       # Users API types & functions
│       │   └── components/           # User management components (to be created)
│       ├── participants/
│       │   ├── services/api.ts       # Participants API types & functions
│       │   └── components/           # Participant management components (to be created)
│       ├── questions/
│       │   ├── services/api.ts       # Questions API types & functions
│       │   └── components/           # Question management components (to be created)
│       ├── offers/
│       │   ├── service/api.ts        # Offers API types & functions
│       │   └── components/           # Offer management components (to be created)
│       ├── dashboard/
│       │   ├── services/api.ts       # Dashboard API types & functions
│       │   └── components/           # Dashboard components (to be created)
│       └── settings/
│           ├── services/api.ts       # Settings API types & functions
│           └── components/           # Settings components (to be created)
├── pages/
│   ├── admin/                 # Admin panel pages (to be created)
│   │   ├── login.tsx          # Admin login page
│   │   ├── layout.tsx         # Admin layout with sidebar
│   │   ├── dashboard.tsx      # Dashboard overview
│   │   ├── users/
│   │   │   ├── index.tsx      # User list
│   │   │   ├── create.tsx     # Create user
│   │   │   └── edit.tsx       # Edit user
│   │   ├── participants/
│   │   │   ├── index.tsx      # Participant list with filters
│   │   │   └── [id].tsx       # Participant detail (optional)
│   │   ├── questions/
│   │   │   ├── index.tsx      # Question list
│   │   │   ├── create.tsx     # Create question
│   │   │   ├── edit.tsx       # Edit question
│   │   │   └── import.tsx     # Import questions
│   │   ├── offers/
│   │   │   ├── index.tsx      # Offer list
│   │   │   └── edit.tsx       # Edit offer
│   │   └── settings/
│   │       └── index.tsx      # Settings page
│   ├── welcome.tsx            # Public landing page
│   └── quiz-app.tsx           # Quiz application page
```

## Admin Routes (Laravel web.php)

Add the following routes to `routes/web.php`:

```php
<?php

use Illuminate\Support\Facades\Route;

Route::inertia('/', 'welcome')->name('home');
Route::inertia('/quiz', 'quiz-app')->name('quiz');

// Admin Panel Routes
Route::prefix('admin')->name('admin.')->group(function (): void {
    // Login (no auth required)
    Route::inertia('/login', 'admin/login')->name('login');
    Route::post('/login', [\App\Http\Controllers\Admin\AuthController::class, 'login'])->name('login.post');

    // Authenticated admin routes
    Route::middleware(['auth:sanctum', 'ability:admin,viewer'])->group(function (): void {
        Route::inertia('/dashboard', 'admin/dashboard')->name('dashboard');
        Route::post('/logout', [\App\Http\Controllers\Admin\AuthController::class, 'logout'])->name('logout');

        // Users (admin only)
        Route::middleware(['abilities:admin'])->group(function (): void {
            Route::inertia('/users', 'admin/users/index')->name('users.index');
            Route::inertia('/users/create', 'admin/users/create')->name('users.create');
            Route::inertia('/users/{user}/edit', 'admin/users/edit')->name('users.edit');
        });

        // Participants (admin & viewer)
        Route::inertia('/participants', 'admin/participants/index')->name('participants.index');

        // Questions (admin only)
        Route::middleware(['abilities:admin'])->group(function (): void {
            Route::inertia('/questions', 'admin/questions/index')->name('questions.index');
            Route::inertia('/questions/create', 'admin/questions/create')->name('questions.create');
            Route::inertia('/questions/{question}/edit', 'admin/questions/edit')->name('questions.edit');
            Route::inertia('/questions/import', 'admin/questions/import')->name('questions.import');
        });

        // Offers (admin only)
        Route::middleware(['abilities:admin'])->group(function (): void {
            Route::inertia('/offers', 'admin/offers/index')->name('offers.index');
            Route::inertia('/offers/{offer}/edit', 'admin/offers/edit')->name('offers.edit');
        });

        // Settings (admin only)
        Route::middleware(['abilities:admin'])->group(function (): void {
            Route::inertia('/settings', 'admin/settings/index')->name('settings.index');
        });
    });
});

require __DIR__.'/settings.php';
```

Note: The actual API routes are already defined in `routes/api.php` under `/api/v1/admin/*`. The frontend will call these API endpoints directly.

## API Endpoints Reference

### Authentication (`/api/v1/admin/auth/`)

| Method | Endpoint  | Description       | Auth              |
| ------ | --------- | ----------------- | ----------------- |
| POST   | `/login`  | Admin login       | Public            |
| POST   | `/logout` | Admin logout      | Sanctum + ability |
| POST   | `/me`     | Get current admin | Sanctum + ability |

### Users (`/api/v1/admin/users/`)

| Method | Endpoint    | Description            | Auth  |
| ------ | ----------- | ---------------------- | ----- |
| POST   | `/index`    | List users (paginated) | Admin |
| POST   | `/show`     | Get single user        | Admin |
| POST   | `/store`    | Create user            | Admin |
| POST   | `/update`   | Update user            | Admin |
| POST   | `/password` | Update user password   | Admin |
| POST   | `/delete`   | Delete user            | Admin |

### Participants (`/api/v1/admin/participants/`)

| Method | Endpoint  | Description                             | Auth         |
| ------ | --------- | --------------------------------------- | ------------ |
| POST   | `/index`  | List participants (filtered, paginated) | Admin/Viewer |
| POST   | `/export` | Export participants to Excel            | Admin/Viewer |

### Questions (`/api/v1/admin/questions/`)

| Method | Endpoint         | Description                   | Auth  |
| ------ | ---------------- | ----------------------------- | ----- |
| POST   | `/index`         | List questions (paginated)    | Admin |
| POST   | `/show`          | Get single question           | Admin |
| POST   | `/template`      | Download import template      | Admin |
| POST   | `/store`         | Create question               | Admin |
| POST   | `/update`        | Update question               | Admin |
| POST   | `/toggle-active` | Toggle question active status | Admin |
| POST   | `/delete`        | Delete question               | Admin |
| POST   | `/import`        | Import questions from file    | Admin |

### Offers (`/api/v1/admin/offers/`)

| Method | Endpoint  | Description      | Auth  |
| ------ | --------- | ---------------- | ----- |
| POST   | `/index`  | List all offers  | Admin |
| POST   | `/show`   | Get single offer | Admin |
| POST   | `/update` | Update offer     | Admin |

### Settings (`/api/v1/admin/settings/`)

| Method | Endpoint  | Description          | Auth  |
| ------ | --------- | -------------------- | ----- |
| POST   | `/index`  | Get current settings | Admin |
| POST   | `/update` | Update settings      | Admin |

### Dashboard (`/api/v1/admin/dashboard`)

| Method | Endpoint | Description             | Auth         |
| ------ | -------- | ----------------------- | ------------ |
| POST   | `/`      | Get dashboard analytics | Admin/Viewer |

## Data Types (from API)

### User

```typescript
interface AdminUser {
    id: number;
    name: string;
    email: string;
    role: 'admin' | 'viewer';
    created_at: string | null;
    updated_at: string | null;
}
```

### Participant

```typescript
type ParticipantStatus = 'in_progress' | 'completed' | 'abandoned' | 'unlocked';

interface Participant {
    id: number;
    guest: { id: number | null; name: string | null; mobile: string | null };
    played_at: string | null;
    status: ParticipantStatus;
    min_score: number;
    max_score: number;
    score: number | null;
    offer: {
        id: number;
        title: string | null;
        score_slot: number | null;
    } | null;
    coupon_code: string | null;
    unlocked_at: string | null;
    completed_at: string | null;
}
```

### Question

```typescript
type QuestionOption = 'A' | 'B' | 'C' | 'D';

interface Question {
    id: number;
    text: string;
    option_a: string;
    option_b: string;
    option_c: string;
    option_d: string;
    correct_option: QuestionOption;
    active: boolean;
    created_at: string | null;
    updated_at: string | null;
}
```

### Offer

```typescript
interface Offer {
    id: number;
    score_slot: number;
    title: string;
    tagline: string;
    terms: string;
    coupon_code: string;
    valid_from: string | null;
    valid_to: string | null;
    active: boolean;
    created_at: string | null;
    updated_at: string | null;
}
```

### Settings

```typescript
interface AdminSettings {
    start_at: string | null;
    end_at: string | null;
    questions_per_quiz: number;
    timer_seconds: number;
    timer_grace_seconds: number;
    attempts_per_number: number;
    app_smartlink_url: string;
}
```

### Dashboard

```typescript
interface DashboardSeriesItem {
    date: string;
    scans: number;
    otp_sent: number;
    otp_verified: number;
    quizzes_started: number;
    quizzes_completed: number;
    offers_unlocked: number;
}

interface DashboardTotals {
    scans: number;
    otp_sent: number;
    otp_verified: number;
    quizzes_started: number;
    quizzes_completed: number;
    offers_unlocked: number;
}

interface DashboardResponse {
    message: string;
    range: { from: string; to: string };
    series: DashboardSeriesItem[];
    totals: DashboardTotals;
}
```

## Implementation Phases

### Phase 1: Foundation (Core Setup)

- [ ] Update `routes/web.php` with admin routes
- [ ] Create admin layout component with sidebar navigation
- [ ] Create admin login page
- [ ] Set up authentication context/state management
- [ ] Configure route protection (middleware)

### Phase 2: Dashboard

- [ ] Create dashboard page with analytics cards
- [ ] Implement date range filter
- [ ] Display series chart (line/bar chart for daily metrics)
- [ ] Show totals summary cards

### Phase 3: User Management (Admin Only)

- [ ] User list page with pagination
- [ ] Create user modal/form
- [ ] Edit user modal/form
- [ ] Delete user confirmation
- [ ] Password reset functionality

### Phase 4: Participant Management

- [ ] Participant list with advanced filters (date range, score, offer, status)
- [ ] Pagination
- [ ] Export to Excel functionality
- [ ] Status badges with color coding

### Phase 5: Question Management (Admin Only)

- [ ] Question list with pagination and active filter
- [ ] Create question form with 4 options + correct answer
- [ ] Edit question form
- [ ] Toggle active/inactive
- [ ] Delete question
- [ ] Import questions (file upload with progress)
- [ ] Download template

### Phase 6: Offer Management (Admin Only)

- [ ] Offer list page
- [ ] Edit offer form (all fields except score_slot)
- [ ] Display offer details

### Phase 7: Settings (Admin Only)

- [ ] Settings form with all configuration fields
- [ ] Date/time pickers for start_at/end_at
- [ ] Number inputs with validation
- [ ] Save/loading states

### Phase 8: Polish & Testing

- [ ] Responsive design for all pages
- [ ] Loading states and error handling
- [ ] Toast notifications for all actions
- [ ] Form validation (client-side)
- [ ] Accessibility improvements
- [ ] Cross-browser testing

## UI Component Requirements

### Reusable Components Needed

1. **DataTable** - Sortable, filterable, paginated table
2. **Modal** - For create/edit forms
3. **ConfirmDialog** - For delete confirmations
4. **Select** - For role, status, option selection
5. **DateRangePicker** - For dashboard/participant filters
6. **FileUpload** - For question import
7. **Chart** - For dashboard analytics (simple line/bar)
8. **Badge** - For status indicators
9. **Pagination** - Reusable pagination component
10. **FormField** - Wrapper for label + input + error

### Navigation Structure

```
Admin Sidebar:
├── Dashboard
├── Users (Admin only)
├── Participants
├── Questions (Admin only)
├── Offers (Admin only)
└── Settings (Admin only)
```

## Authentication Flow

1. User visits `/admin/login`
2. Submits credentials → POST `/api/v1/admin/auth/login`
3. On success: Store token, redirect to `/admin/dashboard`
4. Subsequent requests include token via `apiClient`
5. Logout → POST `/api/v1/admin/auth/logout` → clear token → redirect to login

## Error Handling Strategy

- All API calls wrapped in try/catch
- `ApiError` class provides status code and response data
- Display user-friendly error messages via Sonner toasts
- Handle 401 (unauthorized) → redirect to login
- Handle 403 (forbidden) → show access denied
- Handle 422 (validation) → show field errors on forms

## File Upload Handling

- Question import uses `FormData` with `fetch` directly (not `apiClient`)
- Template download returns Blob → create download link
- Participant export returns Blob (Excel) → create download link

## Responsive Breakpoints

- Mobile: < 640px (collapsed sidebar, stacked layouts)
- Tablet: 640px - 1024px (collapsible sidebar)
- Desktop: > 1024px (full sidebar)

## Performance Considerations

- Lazy load admin pages using React.lazy + Suspense
- Debounce search/filter inputs (300ms)
- Memoize expensive computations
- Virtualize long lists if needed

## Accessibility

- Semantic HTML structure
- ARIA labels for interactive elements
- Keyboard navigation support
- Focus management in modals
- Color contrast compliance
- Screen reader announcements for toasts

## Testing Strategy

- Unit tests for API service functions
- Component tests for forms and tables
- E2E tests for critical flows (login, CRUD operations)
- Visual regression testing for UI components

## Deployment Notes

- Build command: `npm run build` (uses vite-plus)
- Type check: `npm run types:check`
- Lint: `npm run check` / `npm run check:fix`
- Assets served via Laravel Vite plugin
