# LANDING PAGE - Advanced Customization

## Menambahkan Filter Tahun Akademik

### 1. Update Controller

```php
// app/Http/Controllers/LandingPageController.php

public function index(Request $request)
{
    // Get filter tahun akademik
    $academicYear = $request->get('year', date('Y'));
    
    // Statistik dengan filter tahun
    $totalSchools = School::where('is_active', true)
        ->whereYear('created_at', '<=', $academicYear)
        ->count();
    
    $totalStudents = Student::where('is_active', true)
        ->whereYear('created_at', $academicYear)
        ->count();
    
    // ... rest of the code
    
    return view('landing', compact(
        'academicYear',
        'totalSchools',
        // ... other variables
    ));
}
```

### 2. Update View

```html
<!-- Tambahkan filter dropdown -->
<div class="container mt-4">
    <div class="row">
        <div class="col-md-6">
            <form method="GET" action="{{ route('landing') }}">
                <div class="input-group">
                    <label class="input-group-text">Tahun Akademik:</label>
                    <select name="year" class="form-select" onchange="this.form.submit()">
                        <option value="2024" {{ $academicYear == 2024 ? 'selected' : '' }}>2024</option>
                        <option value="2025" {{ $academicYear == 2025 ? 'selected' : '' }}>2025</option>
                        <option value="2026" {{ $academicYear == 2026 ? 'selected' : '' }}>2026</option>
                    </select>
                </div>
            </form>
        </div>
    </div>
</div>
```

## Menambahkan Cache untuk Performance

### 1. Install Redis (Optional)

```bash
# Update .env
CACHE_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
```

### 2. Implement Caching

```php
// app/Http/Controllers/LandingPageController.php

use Illuminate\Support\Facades\Cache;

public function index()
{
    // Cache untuk 1 jam (3600 detik)
    $totalSchools = Cache::remember('landing.total_schools', 3600, function () {
        return School::where('is_active', true)->count();
    });
    
    $schoolsNegeri = Cache::remember('landing.schools_negeri', 3600, function () {
        return School::where('is_active', true)
            ->where('status', 'Negeri')
            ->count();
    });
    
    $schoolsSwasta = Cache::remember('landing.schools_swasta', 3600, function () {
        return School::where('is_active', true)
            ->where('status', 'Swasta')
            ->count();
    });
    
    // ... rest of cached queries
}
```

### 3. Clear Cache Otomatis

```php
// app/Models/School.php

protected static function booted()
{
    static::created(function () {
        Cache::tags(['landing'])->flush();
    });
    
    static::updated(function () {
        Cache::tags(['landing'])->flush();
    });
    
    static::deleted(function () {
        Cache::tags(['landing'])->flush();
    });
}
```

## Menambahkan Export Grafik ke PDF

### 1. Install Package

```bash
composer require barryvdh/laravel-dompdf
```

### 2. Create Export Controller

```php
// app/Http/Controllers/LandingExportController.php

<?php

namespace App\Http\Controllers;

use PDF;
use App\Models\School;
use App\Models\UldLocation;
use App\Models\Student;

class LandingExportController extends Controller
{
    public function exportPDF()
    {
        // Get all data
        $totalSchools = School::where('is_active', true)->count();
        $totalUld = UldLocation::count();
        $totalStudents = Student::where('is_active', true)->count();
        
        // Generate PDF
        $pdf = PDF::loadView('exports.landing-stats', compact(
            'totalSchools',
            'totalUld',
            'totalStudents'
        ));
        
        return $pdf->download('statistik-landing-' . date('Y-m-d') . '.pdf');
    }
}
```

### 3. Create PDF View

```php
// resources/views/exports/landing-stats.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>Statistik DIBA GTK</title>
    <style>
        body { font-family: Arial, sans-serif; }
        .header { text-align: center; margin-bottom: 30px; }
        .stat-box { border: 1px solid #ddd; padding: 20px; margin: 10px 0; }
    </style>
</head>
<body>
    <div class="header">
        <h1>DIBA GTK - Statistik</h1>
        <p>Tanggal: {{ date('d F Y') }}</p>
    </div>
    
    <div class="stat-box">
        <h3>Total Sekolah: {{ number_format($totalSchools) }}</h3>
    </div>
    
    <div class="stat-box">
        <h3>Total ULD: {{ number_format($totalUld) }}</h3>
    </div>
    
    <div class="stat-box">
        <h3>Total Siswa: {{ number_format($totalStudents) }}</h3>
    </div>
</body>
</html>
```

### 4. Add Route

```php
// routes/web.php

Route::get('/landing/export-pdf', [LandingExportController::class, 'exportPDF'])
    ->name('landing.export');
```

### 5. Add Button to Landing Page

```html
<!-- Di landing.blade.php, tambahkan tombol export -->
<div class="text-end mb-3">
    <a href="{{ route('landing.export') }}" class="btn btn-primary">
        <i class="bi bi-download me-2"></i>
        Export PDF
    </a>
</div>
```

## Menambahkan Animasi Loading

### 1. Add Loading Overlay

```html
<!-- Di landing.blade.php, sebelum closing body tag -->

<!-- Loading Overlay -->
<div id="loadingOverlay" style="display: none;">
    <div class="loading-spinner">
        <div class="spinner-border text-light" role="status">
            <span class="visually-hidden">Loading...</span>
        </div>
        <p class="text-white mt-3">Memuat data...</p>
    </div>
</div>

<style>
#loadingOverlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    z-index: 9999;
    display: flex;
    justify-content: center;
    align-items: center;
}

.loading-spinner {
    text-align: center;
}
</style>

<script>
// Show loading saat halaman dimuat
window.addEventListener('load', function() {
    document.getElementById('loadingOverlay').style.display = 'none';
});

// Show loading saat form disubmit
document.querySelectorAll('form').forEach(function(form) {
    form.addEventListener('submit', function() {
        document.getElementById('loadingOverlay').style.display = 'flex';
    });
});
</script>
```

## Menambahkan Chart Animation

### 1. Custom Animation Options

```javascript
// Di script Chart.js, tambahkan animasi

const schoolsCtx = document.getElementById('schoolsChart').getContext('2d');
new Chart(schoolsCtx, {
    type: 'bar',
    data: {
        // ... data
    },
    options: {
        // ... existing options
        animation: {
            duration: 2000,
            easing: 'easeInOutQuart',
            onComplete: function() {
                console.log('Chart animation completed');
            }
        },
        // Delayed animation per bar
        animations: {
            y: {
                duration: 2000,
                delay: (context) => context.dataIndex * 100
            }
        }
    }
});
```

## Menambahkan Real-time Updates (WebSocket)

### 1. Install Laravel Echo & Pusher

```bash
composer require pusher/pusher-php-server
npm install --save laravel-echo pusher-js
```

### 2. Configure Broadcasting

```php
// .env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=your-cluster
```

### 3. Create Event

```php
// app/Events/StatsUpdated.php

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class StatsUpdated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $stats;

    public function __construct($stats)
    {
        $this->stats = $stats;
    }

    public function broadcastOn()
    {
        return new Channel('landing-stats');
    }
}
```

### 4. Listen in View

```javascript
// Di landing.blade.php

import Echo from "laravel-echo"
import Pusher from "pusher-js"

window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: true
});

Echo.channel('landing-stats')
    .listen('StatsUpdated', (e) => {
        // Update stats in real-time
        document.querySelector('.stat-number.text-primary').textContent = 
            e.stats.totalSchools.toLocaleString();
        
        // Update charts
        updateCharts(e.stats);
    });
```

## Menambahkan Dark Mode

### 1. Add Toggle Button

```html
<!-- Di hero section -->
<button id="darkModeToggle" class="btn btn-outline-light">
    <i class="bi bi-moon-fill"></i> Dark Mode
</button>
```

### 2. Add Dark Mode Styles

```css
body.dark-mode {
    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
}

body.dark-mode .stat-card {
    background: #2c3e50;
    color: white;
}

body.dark-mode .chart-container {
    background: #34495e;
    color: white;
}
```

### 3. Add Toggle Script

```javascript
const darkModeToggle = document.getElementById('darkModeToggle');
const body = document.body;

// Check saved preference
if (localStorage.getItem('darkMode') === 'enabled') {
    body.classList.add('dark-mode');
}

darkModeToggle.addEventListener('click', () => {
    body.classList.toggle('dark-mode');
    
    if (body.classList.contains('dark-mode')) {
        localStorage.setItem('darkMode', 'enabled');
        darkModeToggle.innerHTML = '<i class="bi bi-sun-fill"></i> Light Mode';
    } else {
        localStorage.setItem('darkMode', null);
        darkModeToggle.innerHTML = '<i class="bi bi-moon-fill"></i> Dark Mode';
    }
});
```

## Menambahkan API Endpoint

### 1. Create API Controller

```php
// app/Http/Controllers/Api/LandingStatsController.php

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\School;
use App\Models\UldLocation;
use App\Models\Student;

class LandingStatsController extends Controller
{
    public function index()
    {
        return response()->json([
            'success' => true,
            'data' => [
                'total_schools' => School::where('is_active', true)->count(),
                'schools_negeri' => School::where('is_active', true)
                    ->where('status', 'Negeri')->count(),
                'schools_swasta' => School::where('is_active', true)
                    ->where('status', 'Swasta')->count(),
                'total_uld' => UldLocation::count(),
                'total_students' => Student::where('is_active', true)->count(),
            ],
            'timestamp' => now()->toIso8601String()
        ]);
    }
}
```

### 2. Add API Route

```php
// routes/api.php

use App\Http\Controllers\Api\LandingStatsController;

Route::get('/landing/stats', [LandingStatsController::class, 'index']);
```

### 3. Use API with AJAX

```javascript
// Fetch stats via API
async function fetchStats() {
    try {
        const response = await fetch('/api/landing/stats');
        const data = await response.json();
        
        if (data.success) {
            updateStatsDisplay(data.data);
        }
    } catch (error) {
        console.error('Error fetching stats:', error);
    }
}

// Auto-refresh every 30 seconds
setInterval(fetchStats, 30000);
```

## Testing

### 1. Feature Test

```php
// tests/Feature/LandingPageTest.php

<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\School;
use App\Models\Student;
use Illuminate\Foundation\Testing\RefreshDatabase;

class LandingPageTest extends TestCase
{
    use RefreshDatabase;

    public function test_landing_page_displays_correctly()
    {
        // Arrange
        School::factory()->count(10)->create();
        Student::factory()->count(50)->create();
        
        // Act
        $response = $this->get('/');
        
        // Assert
        $response->assertStatus(200);
        $response->assertSee('DIBA GTK');
        $response->assertSee('Total Sekolah');
    }
    
    public function test_stats_are_accurate()
    {
        // Arrange
        School::factory()->count(5)->create(['status' => 'Negeri']);
        School::factory()->count(3)->create(['status' => 'Swasta']);
        
        // Act
        $response = $this->get('/');
        
        // Assert
        $response->assertSee('8'); // Total schools
    }
}
```

### 2. Run Tests

```bash
php artisan test --filter LandingPageTest
```

## Monitoring & Analytics

### 1. Add Google Analytics

```html
<!-- Di head section -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'GA_MEASUREMENT_ID');
</script>
```

### 2. Track Events

```javascript
// Track chart interactions
document.querySelectorAll('canvas').forEach(canvas => {
    canvas.addEventListener('click', () => {
        gtag('event', 'chart_interaction', {
            'event_category': 'engagement',
            'event_label': canvas.id
        });
    });
});
```

## Best Practices

1. **Always cache expensive queries**
2. **Use lazy loading for images**
3. **Minify CSS/JS in production**
4. **Implement error handling**
5. **Add loading states**
6. **Test on multiple devices**
7. **Monitor performance metrics**
8. **Keep dependencies updated**

## Security

```php
// Add rate limiting to API
Route::middleware('throttle:60,1')->group(function () {
    Route::get('/api/landing/stats', [LandingStatsController::class, 'index']);
});

// Sanitize user input
$year = filter_var($request->year, FILTER_VALIDATE_INT);
```
