# Dynamic Navigation & Visitor Tracking System

## Overview
Implementation of a dynamic navbar and visitor tracking system for Laravel-based CMS projects using the reddsis codebase structure.

---

## What Was Done

### 1. Dynamic Navbar System
**Before:** Navbar hardcoded in blade templates. Adding new pages required editing code.
**After:** Navbar auto-generated from database (`frontend_menu` table). Admin can manage menus via dashboard.

**Files Created/Modified:**
- `app/View/Composers/MenuComposer.php` - Class-based View Composer for menu data
- `app/Providers/AppServiceProvider.php` - Registered MenuComposer
- `resources/views/reddsis/layouts/app.blade.php` - Updated navbar to use `$navItems`
- `resources/views/backend/module/menu/frontend/form.blade.php` - Added Parent Menu dropdown
- `app/Http/Controllers/Backend/FrontendMenuController.php` - Added parent menu data, cache clearing

### 2. Visitor Tracking System
**Before:** Visitor logging code commented out, no data collected.
**After:** Automatic visitor logging via Middleware with IP-based daily tracking.

**Files Created/Modified:**
- `app/Http/Middleware/VisitorLogMiddleware.php` - Middleware for visitor logging
- `bootstrap/app.php` - Registered `visitor.log` middleware alias
- `routes/web.php` - Applied middleware to public routes
- `app/Http/Controllers/HomeController.php` - Removed visitor logic (moved to middleware)

### 3. Dynamic Article Routes
**Before:** Each article needed a dedicated route and controller method.
**After:** Catch-all `/{slug}` route auto-fetches articles from database.

**Files Modified:**
- `routes/web.php` - Added `Route::get('/{slug}', ...)`
- `app/Http/Controllers/HomeController.php` - Added `dynamicPage()` method

### 4. Dashboard with Visitor Charts
**Files Created:**
- `app/Http/Controllers/Backend/DashboardController.php` - Controller with visitor stats
- `resources/views/backend/module/dashboard.blade.php` - Dashboard with Chart.js graphs

**Routes Modified:**
- `routes/web.php` - Changed dashboard route from closure to `DashboardController`

### 5. Code Architecture Improvements
- **View Composer Pattern:** Moved menu logic from `AppServiceProvider` to dedicated class
- **Middleware Pattern:** Moved visitor logging from controllers to middleware
- **Caching:** Menu queries cached for 1 hour (`Cache::remember`)
- **Cache Invalidation:** Auto-clear on menu create/update/delete

---

## How It Works

### Navbar Flow
```
User visits page
    ↓
AppServiceProvider boot()
    ↓
MenuComposer::compose() triggered for reddsis.layouts.app
    ↓
Cache::remember('frontend_nav', 3600, ...)
    ↓
Query frontend_menu table (if cache miss)
    ↓
Build nested array (parents + children)
    ↓
Pass $navItems to view
    ↓
Blade renders navbar dynamically
```

### Visitor Tracking Flow
```
User visits public page
    ↓
visitor.log middleware runs
    ↓
Check VisitorSetting::is_active
    ↓
Check session for today's IP key
    ↓
If new: Visit::log() + set session
    ↓
Request continues to controller
```

---

## Database Tables Used

### `frontend_menu`
| Column | Type | Purpose |
|--------|------|---------|
| `menu_id` | int | Primary key |
| `menu_name` | string | Display name |
| `menu_link` | string | URL/slug (e.g., `/about`) |
| `menu_parent_id` | int | Parent menu ID (0 = top level) |
| `menu_status` | boolean | Active/Inactive |
| `menu_icon` | string | Icon class (reserved) |
| `menu_class` | string | CSS class (reserved) |
| `menu_descr` | string | Description (reserved) |
| `menu_img` | string | Image URL (reserved) |

### `visits`
| Column | Type | Purpose |
|--------|------|---------|
| `id` | int | Primary key |
| `ip` | string | Visitor IP |
| `url` | string | Visited URL |
| `useragent` | string | Browser info |
| `device` | string | Device type |
| `browser` | string | Browser name |
| `created_at` | timestamp | Visit time |

### `visitor_settings`
| Column | Type | Purpose |
|--------|------|---------|
| `id` | int | Primary key |
| `is_active` | boolean | Enable/disable logging |

---

## How To Add New Menu

### Via Admin Dashboard
1. Login to Admin → Menu → Frontend Menu → Create
2. Fill in:
   - **Menu Name:** Display name
   - **Parent Menu:** Select parent (or "None" for top level)
   - **Menu Link:** URL slug (e.g., `/new-page`)
   - **Status:** Active checkbox
3. Save → Navbar auto-updates (cache clears automatically)

### Via Tinker (Quick Test)
```php
$menu = new \App\Models\Backend\menu\frontend\Menu;
$menu->menu_name = 'New Page';
$menu->menu_link = '/new-page';
$menu->menu_parent_id = 0; // 0 = top level
$menu->menu_status = true;
$menu->save();
```

---

## How To Add New Article

1. Admin → Content Article → Create
2. Set `article_code` = `your-slug` (e.g., `climate-change`)
3. Set `article_status` = `Published`
4. Article accessible at: `/climate-change`
5. Add menu item pointing to `/climate-change` to show in navbar

---

## Reusable Prompt for Other Projects

Copy this prompt to use in other projects with the same codebase:

```
Implement the following features in this Laravel project:

1. **Dynamic Navbar via View Composer**
   - Create `app/View/Composers/MenuComposer.php`
   - Fetch menus from `frontend_menu` table where `menu_status = true`
   - Build nested array structure (parent/children based on `menu_parent_id`)
   - Cache results for 1 hour using `Cache::remember('frontend_nav', 3600, ...)`
   - Register in `AppServiceProvider::boot()`: `View::composer('layouts.app', MenuComposer::class)`
   - Pass `$navItems` to view
   - In navbar blade: loop `$navItems`, render parent/children structure

2. **Visitor Tracking via Middleware**
   - Create `app/Http/Middleware/VisitorLogMiddleware.php`
   - Check `VisitorSetting::first()?->is_active`
   - Use session key `visit_YYYY-MM-DD_IP` to track once per day per IP
   - Call `Visit::log()` if not logged today
   - Register alias in `bootstrap/app.php`: `'visitor.log' => VisitorLogMiddleware::class`
   - Apply to public routes: `Route::middleware('visitor.log')->group(...)`

3. **Dynamic Article Routes**
   - Add catch-all route: `Route::get('/{slug}', [HomeController::class, 'dynamicPage'])`
   - In `HomeController::dynamicPage($slug)`: fetch `ContentArticle` by `article_code`
   - Return `404` if article not found
   - Place this route LAST in route group (after specific routes)

4. **Menu Form Enhancement**
   - Add Parent Menu dropdown in create/edit form
   - Populate dropdown with top-level menus (`menu_parent_id = 0`)
   - Validate `menu_parent_id` as nullable integer
   - Clear `frontend_nav` cache on menu create/update/delete/disable

5. **Dashboard with Charts**
   - Create `DashboardController` with visitor stats
   - Pass: total visits, today visits, unique IPs, last 7 days, last 30 days, devices, browsers
   - Use Chart.js in dashboard view for line/bar/doughnut charts

Key files to reference:
- `app/Models/Backend/menu/frontend/Menu.php`
- `app/Models/Backend/Visit.php`
- `app/Models/Backend/VisitorSetting.php`
- Existing `AppServiceProvider` structure
- Existing `bootstrap/app.php` middleware configuration
```

---

## Important Notes

1. **Route Order:** The `/{slug}` route MUST be last in the route group. Specific routes (like `/contact`, `/login`) must be defined before it.

2. **Cache Invalidation:** Always call `Cache::forget('frontend_nav')` when modifying menus. This is handled in `FrontendMenuController`.

3. **Visitor Session Key:** Format is `visit_YYYY-MM-DD_IP`. This ensures:
   - Same IP, same day = 1 visit
   - Same IP, next day = new visit
   - Different IP = new visit

4. **Menu Link Format:** Use leading slash (e.g., `/about`, not `about`). The navbar view uses `url($link)` which handles this correctly.

5. **Active State:** Navbar uses `request()->is(trim($link, '/'))` to determine active state. This matches Laravel's route matching.

---

## Troubleshooting

### Navbar not showing new menu
- Check `menu_status = true` in database
- Clear cache: `php artisan cache:clear`
- Verify `menu_parent_id` is correct (0 for top level)

### Visitor count not increasing
- Check `visitor_settings` table: `is_active = true`
- Clear session (different IP or incognito) to test
- Check `visits` table for entries

### Article returns 404
- Verify `article_code` matches URL slug exactly
- Check `article_status = 'Published'`
- Ensure route `/{slug}` is AFTER specific routes in `web.php`

---

## File Structure Summary

```
app/
├── Http/
│   ├── Controllers/
│   │   ├── Backend/
│   │   │   ├── DashboardController.php      [NEW]
│   │   │   └── FrontendMenuController.php   [MODIFIED]
│   │   └── HomeController.php               [MODIFIED]
│   └── Middleware/
│       └── VisitorLogMiddleware.php         [NEW]
├── Providers/
│   └── AppServiceProvider.php              [MODIFIED]
└── View/
    └── Composers/
        └── MenuComposer.php                [NEW]

bootstrap/
└── app.php                                  [MODIFIED]

resources/
└── views/
    ├── backend/
    │   └── module/
    │       ├── dashboard.blade.php         [MODIFIED]
    │       └── menu/frontend/
    │           ├── form.blade.php          [MODIFIED]
    │           ├── create.blade.php        [MODIFIED]
    │           └── edit.blade.php          [MODIFIED]
    └── reddsis/
        └── layouts/
            └── app.blade.php               [MODIFIED]

routes/
└── web.php                                  [MODIFIED]
```
