# Visitor Module

## 1. Pengenalan

Module untuk track dan monitor website visitors — rekod setiap lawatan, device, browser, IP. Ada middleware auto-log, toggle on/off, dan paparan stats.

## 2. Database

**Table:** `visits`

| Column | Type | Description |
|--------|------|-------------|
| id | bigint (PK) | Primary key |
| method | string(255) | HTTP method |
| request | mediumText | Request data |
| url | mediumText | URL yang dilawati |
| referer | mediumText | Source rujukan |
| languages | text | Browser languages |
| useragent | text | User agent string |
| headers | text | Request headers |
| device | text | Device type (mobile/desktop/tablet) |
| platform | text | OS platform |
| browser | text | Browser name |
| ip | ipAddress | Visitor IP |
| geo_raw | json | Geolocation data |
| visitable_type | string (nullable) | Polymorphic model type |
| visitable_id | bigint (nullable) | Polymorphic model ID |
| visitor_type | string (nullable) | Polymorphic visitor type |
| visitor_id | bigint (nullable) | Polymorphic visitor ID |
| timestamps | - | created_at, updated_at |

**Table:** `visitor_settings`

| Column | Type | Description |
|--------|------|-------------|
| id | bigint (PK) | Primary key |
| is_active | boolean (default:true) | Toggle tracking |
| timestamps | - | created_at, updated_at |

## 3. Routes

| Method | URI | Permission | Name |
|--------|-----|------------|------|
| GET | `/admin/visitor` | `visitor.view` | `visitor.index` |
| POST | `/admin/visitor/toggle` | `visitor.update` | `visitor.toggle` |
| POST | `/admin/visitor/clear` | `visitor.delete` | `visitor.clear` |

## 4. Controller — `VisitorController`

**Functions:**
- `index()` — Show stats (totalVisits, uniqueIps, todayVisits) + setting (is_active).
- `toggle()` — Toggle visitor logging on/off.
- `clear()` — Truncate all visit logs.

## 5. Model — `Visit`

- Table: `visits`
- Fillable: method, request, url, referer, languages, useragent, headers, device, platform, browser, ip, visitor_id, visitor_type, visitable_id, visitable_type, geo_raw
- Relations: `visitable()` (morphTo), `visitor()` (morphTo)
- Static methods:
  - `log()` — Create visit record
  - `totalVisits()`, `uniqueIps()`, `todayVisits()` — Stats helpers
  - `detectDevice()`, `detectPlatform()`, `detectBrowser()` — User agent parsing
- Scopes: today, yesterday, thisWeek, thisMonth, online, byDevice, byBrowser, byIp

### Model — `VisitorSetting`

- Table: `visitor_settings`
- Fillable: is_active

## 6. Middleware — `VisitorLogMiddleware`

Dipasang pada public routes:
```php
Route::prefix('/')->middleware('visitor.log')->group(function () {
    Route::get('/', [HomeController::class, 'index']);
    Route::get('/{slug}', [HomeController::class, 'contentArticle']);
});
```

**Cara kerja:**
1. Check `VisitorSetting::is_active` — kalau false, skip
2. Cek session key `visit_{date}_{ip}` — kalau dah ada hari ni, skip (1 lawatan/IP/hari)
3. Panggil `Visit::log()` untuk rekod

## 7. View — `index.blade.php`

- Toggle switch untuk active/deactive logging
- Clear All button dengan SweetAlert confirmation
- Stats cards: Total Visits, Unique IPs, Today Visits

## 8. Seeder

Migration `2026_05_18_194337_create_visitor_settings_table.php` terus seed initial record `is_active = true`.

## 9. Permissions

| Permission | Description |
|------------|-------------|
| `visitor.view` | View visitor stats |
| `visitor.update` | Toggle logging on/off |
| `visitor.delete` | Clear all logs |
