39401-vm/dashboard.php
2026-03-30 17:47:50 +00:00

238 lines
14 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
require_user_login();
$errors = [];
$formData = [
'vehicle_name' => '',
'vehicle_category' => 'Motor',
'plate_number' => '',
'service_name' => 'Ganti oli mesin',
'last_service_date' => date('Y-m-d'),
'reminder_interval_days' => 90,
'odometer_km' => '',
'notes' => '',
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$formData = array_merge($formData, $_POST);
$result = validate_service_payload($_POST);
$errors = $result['errors'];
$formData = array_merge($formData, $result['clean']);
if (!$errors) {
$newId = create_service($result['clean']);
set_flash('success', 'Catatan servis berhasil disimpan. Hanya akun kamu yang bisa melihat reminder ini.');
header('Location: ' . app_url('dashboard.php') . '?created=' . $newId);
exit;
}
}
$userId = current_user_id();
$userName = current_user_name();
$services = fetch_services_for_user($userId);
$summary = dashboard_summary_for_user($userId);
$createdId = isset($_GET['created']) ? (int) $_GET['created'] : 0;
$catalog = service_catalog();
render_page_start([
'title' => 'Dashboard reminder servis',
'description' => 'Input servis kendaraan, lihat reminder dashboard, dan cek status item servis yang akan jatuh tempo.',
'page' => 'dashboard',
]);
render_flash(consume_flash());
?>
<section class="py-4 py-lg-5 border-bottom dashboard-head dashboard-hero">
<div class="container">
<div class="row g-4 align-items-start">
<div class="col-xl-7">
<span class="eyebrow">Dashboard pribadi</span>
<h1 class="section-title mt-2 mb-3">Halo, <?= e($userName) ?>. Semua catatan servis di sini hanya milik akun kamu.</h1>
<p class="text-secondary mb-4">Kamu bisa menambah reminder baru, memantau item yang telat, lalu membuka detail tanpa khawatir data user lain ikut terlihat.</p>
<div class="dashboard-summary-grid dashboard-summary-grid-wide">
<div class="dashboard-stat-card dashboard-stat-primary">
<div class="metric-label">Total catatan</div>
<div class="metric-value"><?= (int) $summary['total_services'] ?></div>
<div class="small text-muted">semua item servis aktif</div>
</div>
<div class="dashboard-stat-card dashboard-stat-alert">
<div class="metric-label">Terlambat</div>
<div class="metric-value"><?= (int) $summary['overdue_count'] ?></div>
<div class="small text-muted">prioritas untuk dicek lebih dulu</div>
</div>
<div class="dashboard-stat-card">
<div class="metric-label">Segera jatuh tempo</div>
<div class="metric-value"><?= (int) $summary['due_soon_count'] ?></div>
<div class="small text-muted">siapkan jadwal servis berikutnya</div>
</div>
</div>
</div>
<div class="col-xl-5">
<div class="surface-card dashboard-note-card h-100">
<div class="small text-uppercase text-muted mb-2">Cara paling gampang pakai dashboard</div>
<h2 class="h5 mb-3">Masukkan satu reminder per item servis.</h2>
<div class="d-flex flex-column gap-2 small text-secondary">
<div class="dashboard-note-item">Isi nama kendaraan dan tanggal servis terakhir.</div>
<div class="dashboard-note-item">Pilih item servis, misalnya oli mesin atau CVT.</div>
<div class="dashboard-note-item">Atur interval hari agar dashboard menghitung due date berikutnya.</div>
</div>
<div class="mt-4 d-flex flex-wrap gap-2">
<span class="summary-chip">Privat per akun</span>
<span class="summary-chip">Cocok untuk pemula</span>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="py-4 py-lg-5">
<div class="container">
<div class="row g-4 align-items-start">
<div class="col-xl-4">
<div class="surface-card sticky-card dashboard-form-card">
<div class="d-flex justify-content-between align-items-start mb-3 gap-3">
<div>
<h2 class="h4 mb-1">Tambah catatan servis</h2>
<p class="small text-secondary mb-0">Isi satu item servis per reminder agar jadwalnya tetap akurat dan gampang dicek nanti.</p>
</div>
<span class="badge badge-soft">Privat</span>
</div>
<div class="form-helper-row mb-3">
<span class="summary-chip">Motor &amp; mobil</span>
<span class="summary-chip">Hitung due otomatis</span>
</div>
<form method="post" class="vstack gap-3" novalidate>
<div>
<label for="vehicle_name" class="form-label">Nama kendaraan</label>
<input type="text" class="form-control <?= isset($errors['vehicle_name']) ? 'is-invalid' : '' ?>" id="vehicle_name" name="vehicle_name" value="<?= e((string) $formData['vehicle_name']) ?>" placeholder="Contoh: Vario 125 / Avanza Harian">
<?php if (isset($errors['vehicle_name'])): ?><div class="invalid-feedback"><?= e($errors['vehicle_name']) ?></div><?php endif; ?>
</div>
<div class="row g-3">
<div class="col-sm-6">
<label for="vehicle_category" class="form-label">Jenis</label>
<select class="form-select <?= isset($errors['vehicle_category']) ? 'is-invalid' : '' ?>" id="vehicle_category" name="vehicle_category">
<option value="Motor" <?= ($formData['vehicle_category'] ?? '') === 'Motor' ? 'selected' : '' ?>>Motor</option>
<option value="Mobil" <?= ($formData['vehicle_category'] ?? '') === 'Mobil' ? 'selected' : '' ?>>Mobil</option>
</select>
<?php if (isset($errors['vehicle_category'])): ?><div class="invalid-feedback"><?= e($errors['vehicle_category']) ?></div><?php endif; ?>
</div>
<div class="col-sm-6">
<label for="plate_number" class="form-label">Nomor polisi</label>
<input type="text" class="form-control" id="plate_number" name="plate_number" value="<?= e((string) $formData['plate_number']) ?>" placeholder="B 1234 CD">
</div>
</div>
<div>
<label for="service_name" class="form-label">Item servis</label>
<select class="form-select <?= isset($errors['service_name']) ? 'is-invalid' : '' ?>" id="service_name" name="service_name" data-service-select>
<?php foreach ($catalog as $serviceName => $defaultDays): ?>
<option value="<?= e($serviceName) ?>" data-default-days="<?= (int) $defaultDays ?>" <?= ($formData['service_name'] ?? '') === $serviceName ? 'selected' : '' ?>><?= e($serviceName) ?></option>
<?php endforeach; ?>
</select>
<?php if (isset($errors['service_name'])): ?><div class="invalid-feedback"><?= e($errors['service_name']) ?></div><?php endif; ?>
</div>
<div class="row g-3 align-items-end">
<div class="col-sm-6">
<label for="last_service_date" class="form-label">Servis terakhir</label>
<input type="date" class="form-control <?= isset($errors['last_service_date']) ? 'is-invalid' : '' ?>" id="last_service_date" name="last_service_date" value="<?= e((string) $formData['last_service_date']) ?>">
<?php if (isset($errors['last_service_date'])): ?><div class="invalid-feedback"><?= e($errors['last_service_date']) ?></div><?php endif; ?>
</div>
<div class="col-sm-6">
<label for="reminder_interval_days" class="form-label">Interval (hari)</label>
<div class="input-group has-validation">
<input type="number" class="form-control <?= isset($errors['reminder_interval_days']) ? 'is-invalid' : '' ?>" id="reminder_interval_days" name="reminder_interval_days" min="1" max="730" value="<?= e((string) $formData['reminder_interval_days']) ?>" data-interval-input>
<button class="btn btn-outline-secondary" type="button" data-apply-default>Default</button>
</div>
<?php if (isset($errors['reminder_interval_days'])): ?><div class="invalid-feedback d-block"><?= e($errors['reminder_interval_days']) ?></div><?php endif; ?>
</div>
</div>
<div class="row g-3">
<div class="col-sm-6">
<label for="odometer_km" class="form-label">Kilometer</label>
<input type="number" class="form-control <?= isset($errors['odometer_km']) ? 'is-invalid' : '' ?>" id="odometer_km" name="odometer_km" min="0" value="<?= e((string) $formData['odometer_km']) ?>" placeholder="Contoh: 18250">
<?php if (isset($errors['odometer_km'])): ?><div class="invalid-feedback"><?= e($errors['odometer_km']) ?></div><?php endif; ?>
</div>
<div class="col-sm-6">
<label for="notes" class="form-label">Catatan</label>
<input type="text" class="form-control" id="notes" name="notes" value="<?= e((string) $formData['notes']) ?>" placeholder="Contoh: Pakai oli 10W-40">
</div>
</div>
<button type="submit" class="btn btn-dark w-100">Simpan dan aktifkan reminder</button>
<div class="small text-muted">Tips: tombol <strong>Default</strong> akan mengisi interval umum sesuai item servis yang dipilih.</div>
</form>
</div>
</div>
<div class="col-xl-8">
<div class="surface-card mb-4 dashboard-list-panel">
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3 mb-3">
<div>
<h2 class="h4 mb-1">Daftar reminder servis</h2>
<p class="small text-secondary mb-0">Semua catatan di bawah ini hanya milik akun <?= e($userName) ?>.</p>
</div>
<div class="d-flex flex-wrap gap-2" role="tablist" aria-label="Filter status reminder">
<button type="button" class="btn btn-sm btn-dark filter-button is-active" data-filter="all">Semua</button>
<button type="button" class="btn btn-sm btn-outline-secondary filter-button" data-filter="status-overdue">Terlambat</button>
<button type="button" class="btn btn-sm btn-outline-secondary filter-button" data-filter="status-soon">Segera</button>
<button type="button" class="btn btn-sm btn-outline-secondary filter-button" data-filter="status-ok">Aman</button>
</div>
</div>
<?php if ($services): ?>
<div class="list-grid" data-reminder-list>
<?php foreach ($services as $service): ?>
<?php $state = due_state($service['next_due_date'] ?? null); ?>
<article class="list-card <?= e($state['class']) ?> <?= $createdId === (int) $service['id'] ? 'list-card-highlight' : '' ?>" data-status="<?= e($state['class']) ?>">
<div class="list-card-top d-flex justify-content-between align-items-start gap-3 mb-3">
<div>
<div class="small text-muted mb-1"><?= e($service['vehicle_category']) ?><?= !empty($service['plate_number']) ? ' · ' . e($service['plate_number']) : '' ?></div>
<h3 class="h5 mb-1"><?= e($service['vehicle_name']) ?></h3>
<div class="text-secondary small"><?= e($service['service_name']) ?></div>
</div>
<span class="status-pill <?= e($state['class']) ?>"><?= e($state['label']) ?></span>
</div>
<div class="list-meta-grid mb-3">
<div class="detail-box">
<div class="detail-label">Terakhir servis</div>
<div class="detail-number"><?= e(date('d M Y', strtotime((string) $service['last_service_date']))) ?></div>
</div>
<div class="detail-box">
<div class="detail-label">Next due</div>
<div class="detail-number"><?= e(date('d M Y', strtotime((string) $service['next_due_date']))) ?></div>
</div>
<div class="detail-box">
<div class="detail-label">Interval</div>
<div class="detail-number"><?= (int) $service['reminder_interval_days'] ?> hari</div>
</div>
</div>
<div class="d-flex justify-content-between align-items-center gap-2 flex-wrap">
<div class="small text-muted"><?= $service['odometer_km'] ? number_format((int) $service['odometer_km']) . ' km' : 'Kilometer belum diisi' ?></div>
<a class="btn btn-sm btn-outline-secondary" href="<?= e(app_url('service.php')) ?>?id=<?= (int) $service['id'] ?>">Buka detail</a>
</div>
</article>
<?php endforeach; ?>
</div>
<?php else: ?>
<div class="empty-state text-center py-5 px-3">
<h3 class="h5 mb-2">Belum ada reminder di akun ini</h3>
<p class="text-secondary mb-0">Mulai dari satu catatan sederhana — misalnya ganti oli mesin — lalu dashboard akan langsung menghitung servis berikutnya untuk akun kamu sendiri.</p>
</div>
<?php endif; ?>
</div>
<div class="surface-card muted-panel admin-info-card">
<div class="row g-3 align-items-center">
<div class="col-md-8">
<h2 class="h6 mb-1">Data kamu tetap privat</h2>
<p class="small text-secondary mb-0">Dashboard ini hanya menampilkan reminder milik akun yang sedang login, jadi catatan servis pengguna lain tidak ikut terlihat di sini.</p>
</div>
<div class="col-md-4 text-md-end">
<span class="small text-muted">Aman dipakai untuk banyak akun.</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<?php render_page_end(); ?>