# System Map

Scope: lead capture, public forms, lead tracking, auth, dashboard, database, notifications, and connected assets.

## Main Files

- Routes: `routes/web.php`, `routes/api.php`
- Controllers: `app/Http/Controllers/LeadController.php`, `app/Http/Controllers/LeadDashboardController.php`, `app/Http/Controllers/AuthController.php`, `app/Http/Controllers/ContactController.php`, `app/Http/Controllers/CalculatorController.php`, `app/Http/Controllers/Dashboard/DesignSystemController.php`
- Models: `app/Models/Lead.php`, `app/Models/LeadEvent.php`, `app/Models/User.php`
- Middleware: `app/Http/Kernel.php`, `app/Http/Middleware/VerifyCsrfToken.php`, `app/Http/Middleware/LocaleMiddleware.php`, `app/Http/Middleware/RedirectIfAuthenticated.php`, `app/Http/Middleware/PublicPageCache.php`, `app/Http/Middleware/CacheHeaders.php`
- Views: `resources/views/pages/contact.blade.php`, `resources/views/pages/calculator.blade.php`, `resources/views/auth/login.blade.php`, `resources/views/dashboard/leads/index.blade.php`, `resources/views/dashboard/leads/show.blade.php`, `resources/views/dashboard/design-system/index.blade.php`, `resources/views/layouts/app.blade.php`
- JavaScript: `public/js/lead-tracking.js`, `public/js/quote-calculator.js`, inline scripts in dashboard and form views
- Config: `config/auth.php`, `config/session.php`, `config/database.php`, `config/leads.php`, `config/beams.php`, `config/broadcasting.php`
- Database: `database/migrations/*leads*`, `database/migrations/*users*`, `database/seeders/DatabaseSeeder.php`

No `app/Http/Requests` directory was found. No `resources/js` or `resources/css` directories were found.

## Routes

### Lead Tracking API In Web Routes

Defined in `routes/web.php` under `Route::middleware('throttle:lead-api')->prefix('api/leads')`.

- `POST /api/leads/track-click`, name `leads.track-click`, controller `App\Http\Controllers\LeadController::trackClick`
- `POST /api/leads/capture`, name `leads.capture`, controller `LeadController::captureFormData`
- `POST /api/leads/form-started`, name `leads.form-started`, controller `LeadController::formStarted`
- `POST /api/leads/form-abandoned`, name `leads.form-abandoned`, controller `LeadController::formAbandoned`
- `POST /api/leads/submit`, name `leads.submit`, controller `LeadController::submitForm`
- `GET /api/leads/data`, name `leads.data`, controller `LeadController::getLeadData`

These routes are in `routes/web.php`, not `routes/api.php`. They use the web middleware stack, but `app/Http/Middleware/VerifyCsrfToken.php` exempts `api/leads/*`. They are rate-limited by `lead-api` in `app/Providers/RouteServiceProvider.php`.

### Public Contact And Calculator

English routes in `routes/web.php`:

- `GET /contact`, name `contact.index`, controller `ContactController::index`, view `resources/views/pages/contact.blade.php`
- `POST /contact`, name `contact.submit`, controller `ContactController::submit`
- `GET /thank-you`, name `contact.thank-you`, controller `ContactController::thankYou`, view `resources/views/pages/thank-you.blade.php`
- `GET /get-a-quote`, name `calculator.index`, controller `CalculatorController::index`, view `resources/views/pages/calculator.blade.php`

Localized equivalents exist inside the `{locale}` route group:

- `GET /{locale}/contact`, name `contact.index.localized`
- `POST /{locale}/contact`, name `contact.submit.localized`
- `GET /{locale}/thank-you`, name `contact.thank-you.localized`
- `GET /{locale}/get-a-quote`, name `calculator.index.localized`

### Auth

Defined in `routes/web.php`.

- `GET /login`, name `login`, middleware `guest`, controller `AuthController::showLoginForm`, view `resources/views/auth/login.blade.php`
- `POST /login`, middleware `guest`, controller `AuthController::login`
- `POST /logout`, name `logout`, controller `AuthController::logout`

### Dashboard

Defined in `routes/web.php` inside `Route::middleware(['auth', 'admin'])->prefix('dashboard')`.

- `GET /dashboard`, name `dashboard`, redirects to `dashboard.leads.index`
- `GET /dashboard/design-system`, name `dashboard.design-system`, controller `Dashboard\DesignSystemController::index`
- `GET /dashboard/leads`, name `dashboard.leads.index`, controller `LeadDashboardController::index`
- `GET /dashboard/leads/export`, name `dashboard.leads.export`, controller `LeadDashboardController::export`
- `POST /dashboard/leads/bulk-delete`, name `dashboard.leads.bulk-delete`, controller `LeadDashboardController::destroyBulk`
- `GET /dashboard/leads/{lead}`, name `dashboard.leads.show`, controller `LeadDashboardController::show`
- `PATCH /dashboard/leads/{lead}/status`, name `dashboard.leads.update-status`, controller `LeadDashboardController::updateStatus`
- `DELETE /dashboard/leads/{lead}`, name `dashboard.leads.destroy`, controller `LeadDashboardController::destroy`

### API Routes File

`routes/api.php` only defines `GET /api/user` with `auth:sanctum`. It is unrelated to leads.

## Middleware

- `app/Http/Kernel.php` web stack: `NormalizeLocalizedPath`, cookies, sessions, CSRF, bindings, `CacheHeaders`.
- `app/Http/Middleware/VerifyCsrfToken.php`: excludes `api/leads/*`. Dashboard POST/PATCH/DELETE still require CSRF.
- `app/Http/Middleware/LocaleMiddleware.php`: excludes first path segments `api`, `dashboard`, `sitemap`, `language`, `livewire`, `_debugbar`.
- `app/Http/Middleware/RedirectIfAuthenticated.php`: authenticated visitors hitting guest routes redirect to `/dashboard/leads`.
- `app/Http/Middleware/PublicPageCache.php`: caches selected public GET routes only; excludes dashboard via config prefix checks.

## Main Flows

### Lead Form Submission

```mermaid
flowchart TD
    A["Visitor opens /contact"] --> B["resources/views/pages/contact.blade.php"]
    B --> C["public/js/lead-tracking.js intercepts #contact-form submit"]
    C --> D["POST /api/leads/submit"]
    D --> E["LeadController::submitForm"]
    E --> F["LeadController::submitFormHandler validation"]
    F --> G["Lead model saved/updated in leads table"]
    G --> H["LeadEvent form_submitted saved in lead_events table"]
    H --> I["LeadNotification broadcast + Pusher Beams notification"]
    I --> J["JSON redirect_url returned"]
    J --> K["Browser redirects to /thank-you or localized thank-you"]
```

### Dashboard Data Flow

```mermaid
flowchart TD
    A["Authenticated user visits /dashboard/leads"] --> B["auth middleware"]
    B --> C["LeadDashboardController::index"]
    C --> D["Lead query with filters/search/market/range"]
    C --> E["getStatistics/getTopSources/getTopReferralSources/getServiceBreakdown/getMarketBreakdown"]
    D --> F["resources/views/dashboard/leads/index.blade.php"]
    E --> F
```

### Login Flow

```mermaid
flowchart TD
    A["GET /login"] --> B["AuthController::showLoginForm"]
    B --> C["resources/views/auth/login.blade.php"]
    C --> D["POST /login"]
    D --> E["AuthController::login validates email/password"]
    E --> F["Auth::attempt with remember flag"]
    F --> G["session regenerate"]
    G --> H["redirect dashboard.leads.index"]
```

## Notifications

- Broadcast event: `app/Events/LeadNotification.php`
- Broadcast channel: public channel `leads`
- Event names used: `lead.cold`, `lead.abandoned`, `lead.submitted`
- Browser dashboard listener: `resources/views/dashboard/leads/index.blade.php`
- Push service: `app/Services/LeadBeamsNotificationService.php`
- Config: `config/beams.php`, `config/broadcasting.php`

No Laravel `Mail::`, mailables, notification classes, or outbound webhooks were found for lead/contact submission. The only external call found in this area is optional IP geolocation in `app/Helpers/LeadTrackingEnrichment.php` using `Http::timeout(1)->get("http://ip-api.com/json/...")` when `LEADS_ENABLE_IP_GEOLOCATION=true`.

## Risks / Needs Verification

- Production migrations must be run before deploying code that depends on `users.is_admin`, `leads.status = archived`, or calculator lead columns.
- Lead API routes remain public and CSRF-exempt by design for tracking and form submission, but are now rate-limited and protected by a hidden form honeypot on submit paths.
- `LeadController::submitForm` now returns a proper 500 JSON error for database/save failures. Notification failures are logged separately and do not block valid submissions.
