[{"data":1,"prerenderedAt":95},["ShallowReactive",2],{"\u002Fposts\u002Fmembuat-dashboard-admin-dengan-statistik-dan-grafik?{\"username\":\"irezabdullah\"}":3},{"success":4,"message":5,"data":6},true,"Post retrieved successfully",{"post":7,"seriesInfo":25,"seriesItems":28,"seoDescription":94},{"id":8,"title":9,"slug":10,"body":11,"cover_image_path":12,"view_count":13,"part_number":14,"created_at":15,"updated_at":16,"category":17,"author":20},61,"Membuat Dashboard Admin dengan Statistik dan Grafik","membuat-dashboard-admin-dengan-statistik-dan-grafik","# **Materi Lengkap: Membuat Dashboard Admin dengan Statistik dan Grafik di Laravel**\n\n## **1. Persiapan dan Struktur Routing**\n\n#### **A. Update Routing File (`routes\u002Fweb.php`)**\n\n```php\n\u003C?php\n\nuse Illuminate\\Support\\Facades\\Route;\nuse App\\Http\\Controllers\\AuthController;\nuse App\\Http\\Controllers\\ProductController;\nuse App\\Http\\Controllers\\DashboardController;\n\n\u002F\u002F --- ROUTE PUBLIK YANG SUDAH ADA SEBELUMNYA (TANPA MIDDLEWARE) ---\nRoute::get('\u002F', [HomeController::class, 'home']);\nRoute::get('\u002Fabout', [HomeController::class, 'about']);\nRoute::get('\u002Fcontact', [HomeController::class, 'contact']);\n\n\u002F\u002F ROUTE LOGIN\u002FLOGOUT (harus di luar middleware auth)\nRoute::get('\u002Flogin', [AuthController::class, 'showLoginForm'])->name('login');\nRoute::post('\u002Flogin', [AuthController::class, 'login']);\nRoute::post('\u002Flogout', [AuthController::class, 'logout'])->name('logout');\n\n\u002F\u002F ==================== ROUTE PRIVAT (HARUS LOGIN) ====================\n\u002F\u002F Semua route di dalam grup ini dilindungi middleware 'auth'\nRoute::middleware(['auth'])->group(function () {\n    \n    \u002F\u002F -------------------- DASHBOARD ROUTES --------------------\n    Route::prefix('dashboard')->name('dashboard.')->group(function () {\n        \u002F\u002F Dashboard utama\n        Route::get('\u002F', [DashboardController::class, 'index'])->name('index');\n        \n        \u002F\u002F Data untuk AJAX\u002Frefresh\n        Route::get('\u002Fdata', [DashboardController::class, 'getDashboardData'])->name('data');\n    });\n    \n    \u002F\u002F -------------------- PRODUCT ROUTES --------------------\n   \u002F\u002F Contoh: Route untuk manajemen produk\n    Route::get('products\u002Fchart', [ProductController::class, 'chart'])->name('products.chart'); \u002F\u002FUntuk Chart \u002FGrafik\n\n    Route::get('\u002Fproducts', [ProductController::class, 'index'])->name('products.index');\n    Route::get('\u002Fproducts\u002Fcreate', [ProductController::class, 'create'])->name('products.create');\n    Route::post('\u002Fproducts', [ProductController::class, 'store'])->name('products.store');\n    Route::get('\u002Fproducts\u002F{product}\u002Fedit', [ProductController::class, 'edit'])->name('products.edit');\n    Route::put('\u002Fproducts\u002F{product}', [ProductController::class, 'update'])->name('products.update');\n    Route::delete('\u002Fproducts\u002F{product}', [ProductController::class, 'destroy'])->name('products.destroy')\n});\n```\n\n#### **B. Penjelasan Struktur Routing**\n\n```\nROUTING STRUCTURE:\n├── 📍 PUBLIC ROUTES (Tanpa login)\n│   ├── GET  \u002F          → Welcome page\n│   ├── GET  \u002Fabout     → About page  \n│   ├── GET  \u002Fabout     → Contact page  \n│   ├── GET  \u002Flogin     → Form login\n│   └── POST \u002Flogin     → Proses login\n│\n├── 🔒 PRIVATE ROUTES (Harus login) ← Dilindungi middleware 'auth'\n│   │\n│   ├── 📊 DASHBOARD GROUP\n│   │   ├── GET \u002Fdashboard          → Dashboard utama\n│   │   ├── GET \u002Fdashboard\u002Fdata     → Data AJAX\n│   │\n│   └── 📦 PRODUCTS GROUP\n│       ├── GET    \u002Fproducts           → List produk\n│       ├── GET    \u002Fproducts\u002Fcreate    → Form tambah\n│       ├── POST   \u002Fproducts           → Simpan produk  \n│       ├── GET    \u002Fproducts\u002F{id}      → Detail produk\n│       ├── GET    \u002Fproducts\u002F{id}\u002Fedit → Form edit\n│       ├── PUT    \u002Fproducts\u002F{id}      → Update produk\n│       ├── DELETE \u002Fproducts\u002F{id}      → Hapus produk\n│       └── GET    \u002Fproducts\u002Fchart     → Grafik produk\n```\n\n---\n\n## **2. Dashboard Controller Lengkap**\n\n**File: `app\u002FHttp\u002FControllers\u002FDashboardController.php`**\n\n```php\n\u003C?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Product;\nuse App\\Models\\User;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass DashboardController extends Controller\n{\n    \u002F\u002F ==================== METHOD UTAMA ====================\n    \n    \u002F**\n     * Menampilkan halaman dashboard utama\n     * Route: GET \u002Fdashboard\n     *\u002F\n    public function index()\n    {\n        \u002F\u002F 1. Ambil semua data yang diperlukan\n        $data = $this->prepareDashboardData();\n        \n        \u002F\u002F 2. Kirim data ke view\n        return view('dashboard', $data);\n    }\n    \n    \u002F**\n     * API untuk mengambil data dashboard (AJAX refresh)\n     * Route: GET \u002Fdashboard\u002Fdata\n     *\u002F\n    public function getDashboardData()\n    {\n        $data = $this->prepareDashboardData();\n        \n        return response()->json([\n            'success' => true,\n            'data' => $data,\n            'timestamp' => now()->format('Y-m-d H:i:s')\n        ]);\n    }\n    \n    \n    \u002F\u002F ==================== HELPER METHODS ====================\n    \n    \u002F**\n     * Menyiapkan semua data untuk dashboard\n     *\u002F\n    private function prepareDashboardData()\n    {\n        return [\n            'stats' => $this->getDashboardStats(),\n            'chartData' => $this->getStockChartData(),\n            'lowStockProducts' => $this->getLowStockProducts(),\n            'highStockProducts' => $this->getHighStockProducts(),\n            'outOfStockProducts' => $this->getOutOfStockProducts(),\n            'recentProducts' => $this->getRecentProducts(),\n        ];\n    }\n    \n    \u002F**\n     * Mengambil data statistik utama\n     *\u002F\n    private function getDashboardStats()\n    {\n        return [\n            'total_products' => Product::count(),\n            'total_users' => User::count(),\n            'total_stock' => Product::sum('stock') ?? 0,\n            'total_value' => Product::sum(DB::raw('price * stock')) ?? 0,\n            'average_price' => Product::avg('price') ?? 0,\n            'out_of_stock' => Product::where('stock', 0)->count(),\n            'low_stock' => Product::where('stock', '\u003C', 10)\n                             ->where('stock', '>', 0)\n                             ->count(),\n        ];\n    }\n    \n    \u002F**\n     * Menyiapkan data untuk grafik Chart.js\n     *\u002F\n    private function getStockChartData()\n    {\n        \u002F\u002F Ambil 10 produk dengan stok terbanyak\n        $products = Product::orderBy('stock', 'desc')\n            ->limit(10)\n            ->get(['name', 'stock', 'price']);\n\n        \u002F\u002F Format data\n        $labels = $products->pluck('name')->map(function ($name) {\n            return strlen($name) > 15 ? substr($name, 0, 15) . '...' : $name;\n        })->toArray();\n\n        $stocks = $products->pluck('stock')->toArray();\n        $prices = $products->pluck('price')->toArray();\n\n        \u002F\u002F Tentukan warna berdasarkan level stok\n        $backgroundColors = [];\n        $borderColors = [];\n\n        foreach ($stocks as $stock) {\n            if ($stock > 50) {\n                \u002F\u002F Hijau untuk stok tinggi\n                $backgroundColors[] = 'rgba(75, 192, 192, 0.2)';\n                $borderColors[] = 'rgba(75, 192, 192, 1)';\n            } elseif ($stock > 20) {\n                \u002F\u002F Kuning untuk stok menengah\n                $backgroundColors[] = 'rgba(255, 206, 86, 0.2)';\n                $borderColors[] = 'rgba(255, 206, 86, 1)';\n            } elseif ($stock > 0) {\n                \u002F\u002F Merah untuk stok rendah\n                $backgroundColors[] = 'rgba(255, 99, 132, 0.2)';\n                $borderColors[] = 'rgba(255, 99, 132, 1)';\n            } else {\n                \u002F\u002F Abu-abu untuk stok habis\n                $backgroundColors[] = 'rgba(150, 150, 150, 0.2)';\n                $borderColors[] = 'rgba(150, 150, 150, 1)';\n            }\n        }\n\n        return [\n            'labels' => $labels,\n            'stocks' => $stocks,\n            'prices' => $prices,\n            'backgroundColors' => $backgroundColors,\n            'borderColors' => $borderColors\n        ];\n    }\n    \n    \u002F**\n     * Mengambil produk dengan stok rendah (\u003C 10)\n     *\u002F\n    private function getLowStockProducts()\n    {\n        return Product::where('stock', '\u003C', 10)\n            ->where('stock', '>', 0)\n            ->orderBy('stock', 'asc')\n            ->limit(5)\n            ->get();\n    }\n    \n    \u002F**\n     * Mengambil produk dengan stok terbanyak\n     *\u002F\n    private function getHighStockProducts()\n    {\n        return Product::orderBy('stock', 'desc')\n            ->limit(5)\n            ->get();\n    }\n    \n    \u002F**\n     * Mengambil produk yang habis stok\n     *\u002F\n    private function getOutOfStockProducts()\n    {\n        return Product::where('stock', 0)\n            ->latest()\n            ->limit(5)\n            ->get();\n    }\n    \n    \u002F**\n     * Mengambil produk terbaru\n     *\u002F\n    private function getRecentProducts()\n    {\n        return Product::latest()\n            ->limit(5)\n            ->get();\n    }\n}\n```\n\n---\n\n## **3. View Dashboard yang Diperbaiki**\n\n**File: `resources\u002Fviews\u002Fdashboard.blade.php`**\n\n```html\n@extends('layouts.main')\n\n@section('title', 'Dashboard Admin')\n\n@section('content')\n\u003Cdiv class=\"container-fluid px-4\">\n    \u003C!-- HEADER -->\n    \u003Cdiv class=\"d-flex justify-content-between align-items-center mb-4\">\n        \u003Cdiv>\n            \u003Ch1 class=\"h3 mb-0 text-gray-800\">📊 Dashboard Admin\u003C\u002Fh1>\n            \u003Cp class=\"mb-0\">Selamat datang, {{ Auth::user()->name }}!\u003C\u002Fp>\n        \u003C\u002Fdiv>\n        \u003Cdiv class=\"text-end\">\n            \u003Cdiv class=\"small text-muted\">\n                \u003Ci class=\"fas fa-calendar me-1\">\u003C\u002Fi>\n                {{ now()->translatedFormat('l, d F Y') }}\n            \u003C\u002Fdiv>\n            \u003Cdiv class=\"small text-muted\">\n                \u003Ci class=\"fas fa-clock me-1\">\u003C\u002Fi>\n                \u003Cspan id=\"currentTime\">{{ now()->format('H:i:s') }}\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003C!-- STATISTIK CARDS -->\n    \u003Cdiv class=\"row\">\n        \u003C!-- Total Produk -->\n        \u003Cdiv class=\"col-xl-3 col-md-6 mb-4\">\n            \u003Cdiv class=\"card border-left-primary shadow h-100 py-2\">\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"row no-gutters align-items-center\">\n                        \u003Cdiv class=\"col mr-2\">\n                            \u003Cdiv class=\"text-xs font-weight-bold text-primary text-uppercase mb-1\">\n                                Total Produk\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"h5 mb-0 font-weight-bold text-gray-800\">\n                                {{ $stats['total_products'] }}\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"mt-2\">\n                                \u003Ca href=\"{{ route('products.index') }}\" class=\"small text-primary text-decoration-none\">\n                                    \u003Ci class=\"fas fa-eye me-1\">\u003C\u002Fi> Lihat semua\n                                \u003C\u002Fa>\n                            \u003C\u002Fdiv>\n                        \u003C\u002Fdiv>\n                        \u003Cdiv class=\"col-auto\">\n                            \u003Ci class=\"fas fa-box fa-2x text-gray-300\">\u003C\u002Fi>\n                        \u003C\u002Fdiv>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003C!-- Total Stok -->\n        \u003Cdiv class=\"col-xl-3 col-md-6 mb-4\">\n            \u003Cdiv class=\"card border-left-success shadow h-100 py-2\">\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"row no-gutters align-items-center\">\n                        \u003Cdiv class=\"col mr-2\">\n                            \u003Cdiv class=\"text-xs font-weight-bold text-success text-uppercase mb-1\">\n                                Total Stok\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"h5 mb-0 font-weight-bold text-gray-800\">\n                                {{ number_format($stats['total_stock']) }}\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"small text-muted mt-1\">Unit tersedia\u003C\u002Fdiv>\n                        \u003C\u002Fdiv>\n                        \u003Cdiv class=\"col-auto\">\n                            \u003Ci class=\"fas fa-cubes fa-2x text-gray-300\">\u003C\u002Fi>\n                        \u003C\u002Fdiv>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003C!-- Nilai Stok -->\n        \u003Cdiv class=\"col-xl-3 col-md-6 mb-4\">\n            \u003Cdiv class=\"card border-left-info shadow h-100 py-2\">\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"row no-gutters align-items-center\">\n                        \u003Cdiv class=\"col mr-2\">\n                            \u003Cdiv class=\"text-xs font-weight-bold text-info text-uppercase mb-1\">\n                                Nilai Stok\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"h5 mb-0 font-weight-bold text-gray-800\">\n                                Rp{{ number_format($stats['total_value'], 0, ',', '.') }}\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"small text-muted mt-1\">\n                                Rata: Rp{{ number_format($stats['average_price'], 0, ',', '.') }}\n                            \u003C\u002Fdiv>\n                        \u003C\u002Fdiv>\n                        \u003Cdiv class=\"col-auto\">\n                            \u003Ci class=\"fas fa-money-bill-wave fa-2x text-gray-300\">\u003C\u002Fi>\n                        \u003C\u002Fdiv>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003C!-- Produk Habis -->\n        \u003Cdiv class=\"col-xl-3 col-md-6 mb-4\">\n            \u003Cdiv class=\"card border-left-danger shadow h-100 py-2\">\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"row no-gutters align-items-center\">\n                        \u003Cdiv class=\"col mr-2\">\n                            \u003Cdiv class=\"text-xs font-weight-bold text-danger text-uppercase mb-1\">\n                                Produk Habis\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"h5 mb-0 font-weight-bold text-gray-800\">\n                                {{ $stats['out_of_stock'] }}\n                            \u003C\u002Fdiv>\n                            \u003Cdiv class=\"mt-2\">\n                                @if($stats['out_of_stock'] > 0)\n                                \u003Ca href=\"#outOfStockSection\" class=\"small text-danger text-decoration-none\">\n                                    \u003Ci class=\"fas fa-exclamation-circle me-1\">\u003C\u002Fi> Lihat daftar\n                                \u003C\u002Fa>\n                                @else\n                                \u003Cspan class=\"small text-success\">\n                                    \u003Ci class=\"fas fa-check-circle me-1\">\u003C\u002Fi> Semua stok tersedia\n                                \u003C\u002Fspan>\n                                @endif\n                            \u003C\u002Fdiv>\n                        \u003C\u002Fdiv>\n                        \u003Cdiv class=\"col-auto\">\n                            \u003Ci class=\"fas fa-times-circle fa-2x text-gray-300\">\u003C\u002Fi>\n                        \u003C\u002Fdiv>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003C!-- GRAFIK DAN PERINGATAN -->\n    \u003Cdiv class=\"row\">\n        \u003C!-- Grafik -->\n        \u003Cdiv class=\"col-xl-8 mb-4\">\n            \u003Cdiv class=\"card shadow\">\n                \u003Cdiv class=\"card-header py-3\">\n                    \u003Ch6 class=\"m-0 font-weight-bold text-primary\">\n                        \u003Ci class=\"fas fa-chart-bar me-1\">\u003C\u002Fi>\n                        Grafik 10 Produk dengan Stok Terbanyak\n                    \u003C\u002Fh6>\n                \u003C\u002Fdiv>\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"chart-container\" style=\"position: relative; height:300px; width:100%\">\n                        \u003Ccanvas id=\"stockChart\">\u003C\u002Fcanvas>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n                \u003Cdiv class=\"card-footer text-muted small\">\n                    \u003Cdiv class=\"d-flex justify-content-between\">\n                        \u003Cspan>Update: \u003Cspan id=\"chartUpdateTime\">{{ now()->format('H:i:s') }}\u003C\u002Fspan>\u003C\u002Fspan>\n                        \u003Cspan>Total {{ $stats['total_products'] }} produk\u003C\u002Fspan>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003C!-- Peringatan Stok Rendah -->\n        \u003Cdiv class=\"col-xl-4 mb-4\">\n            \u003Cdiv class=\"card border-warning shadow\">\n                \u003Cdiv class=\"card-header bg-warning text-dark py-3\">\n                    \u003Ch6 class=\"m-0 font-weight-bold\">\n                        \u003Ci class=\"fas fa-exclamation-triangle me-1\">\u003C\u002Fi>\n                        Stok Rendah \u003Cspan class=\"badge bg-dark\">{{ $lowStockProducts->count() }}\u003C\u002Fspan>\n                    \u003C\u002Fh6>\n                \u003C\u002Fdiv>\n                \u003Cdiv class=\"card-body\">\n                    @if($lowStockProducts->count() > 0)\n                        \u003Cdiv class=\"alert alert-warning small\">\n                            \u003Ci class=\"fas fa-info-circle me-1\">\u003C\u002Fi>\n                            Ada {{ $lowStockProducts->count() }} produk dengan stok &lt; 10\n                        \u003C\u002Fdiv>\n                        \n                        \u003Cdiv class=\"list-group\">\n                            @foreach($lowStockProducts as $product)\n                            \u003Ca href=\"{{ route('products.edit', $product) }}\" \n                               class=\"list-group-item list-group-item-action d-flex justify-content-between align-items-center\">\n                                \u003Cdiv>\n                                    \u003Cdiv class=\"fw-bold\">{{ Str::limit($product->name, 20) }}\u003C\u002Fdiv>\n                                    \u003Csmall class=\"text-muted\">ID: {{ $product->id }}\u003C\u002Fsmall>\n                                \u003C\u002Fdiv>\n                                \u003Cspan class=\"badge bg-danger rounded-pill\">{{ $product->stock }}\u003C\u002Fspan>\n                            \u003C\u002Fa>\n                            @endforeach\n                        \u003C\u002Fdiv>\n                    @else\n                        \u003Cdiv class=\"text-center py-4\">\n                            \u003Cdiv class=\"text-success mb-2\">\n                                \u003Ci class=\"fas fa-check-circle fa-3x\">\u003C\u002Fi>\n                            \u003C\u002Fdiv>\n                            \u003Ch6 class=\"text-success\">Stok Aman\u003C\u002Fh6>\n                            \u003Cp class=\"small text-muted\">Tidak ada stok rendah\u003C\u002Fp>\n                        \u003C\u002Fdiv>\n                    @endif\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003C!-- PRODUK TERBARU DAN HABIS -->\n    \u003Cdiv class=\"row\">\n        \u003C!-- Produk Terbaru -->\n        \u003Cdiv class=\"col-lg-6 mb-4\">\n            \u003Cdiv class=\"card shadow\">\n                \u003Cdiv class=\"card-header py-3\">\n                    \u003Cdiv class=\"d-flex justify-content-between align-items-center\">\n                        \u003Ch6 class=\"m-0 font-weight-bold text-success\">\n                            \u003Ci class=\"fas fa-history me-1\">\u003C\u002Fi>\n                            Produk Terbaru\n                        \u003C\u002Fh6>\n                        \u003Ca href=\"{{ route('products.create') }}\" class=\"btn btn-sm btn-success\">\n                            \u003Ci class=\"fas fa-plus me-1\">\u003C\u002Fi> Baru\n                        \u003C\u002Fa>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"table-responsive\">\n                        \u003Ctable class=\"table table-hover\">\n                            \u003Cthead>\n                                \u003Ctr>\n                                    \u003Cth>Produk\u003C\u002Fth>\n                                    \u003Cth class=\"text-center\">Stok\u003C\u002Fth>\n                                    \u003Cth>Harga\u003C\u002Fth>\n                                    \u003Cth>Tanggal\u003C\u002Fth>\n                                \u003C\u002Ftr>\n                            \u003C\u002Fthead>\n                            \u003Ctbody>\n                                @foreach($recentProducts as $product)\n                                \u003Ctr>\n                                    \u003Ctd>\n                                        \u003Cdiv class=\"fw-bold\">{{ Str::limit($product->name, 20) }}\u003C\u002Fdiv>\n                                        \u003Csmall class=\"text-muted\">ID: {{ $product->id }}\u003C\u002Fsmall>\n                                    \u003C\u002Ftd>\n                                    \u003Ctd class=\"text-center\">\n                                        \u003Cspan class=\"badge bg-{{ $product->stock > 10 ? 'success' : 'warning' }}\">\n                                            {{ $product->stock }}\n                                        \u003C\u002Fspan>\n                                    \u003C\u002Ftd>\n                                    \u003Ctd>Rp{{ number_format($product->price, 0, ',', '.') }}\u003C\u002Ftd>\n                                    \u003Ctd>\n                                        \u003Cdiv class=\"small\">{{ $product->created_at->format('d\u002Fm\u002Fy') }}\u003C\u002Fdiv>\n                                        \u003Cdiv class=\"text-muted smaller\">{{ $product->created_at->diffForHumans() }}\u003C\u002Fdiv>\n                                    \u003C\u002Ftd>\n                                \u003C\u002Ftr>\n                                @endforeach\n                            \u003C\u002Ftbody>\n                        \u003C\u002Ftable>\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003C!-- Produk Habis Stok -->\n        \u003Cdiv class=\"col-lg-6 mb-4\">\n            \u003Cdiv class=\"card border-danger shadow\" id=\"outOfStockSection\">\n                \u003Cdiv class=\"card-header bg-danger text-white py-3\">\n                    \u003Ch6 class=\"m-0 font-weight-bold\">\n                        \u003Ci class=\"fas fa-times-circle me-1\">\u003C\u002Fi>\n                        Produk Habis Stok \u003Cspan class=\"badge bg-white text-danger\">{{ $outOfStockProducts->count() }}\u003C\u002Fspan>\n                    \u003C\u002Fh6>\n                \u003C\u002Fdiv>\n                \u003Cdiv class=\"card-body\">\n                    @if($outOfStockProducts->count() > 0)\n                        \u003Cdiv class=\"alert alert-danger small\">\n                            \u003Ci class=\"fas fa-exclamation-triangle me-1\">\u003C\u002Fi>\n                            Ada {{ $outOfStockProducts->count() }} produk habis stok\n                        \u003C\u002Fdiv>\n                        \n                        \u003Cdiv class=\"table-responsive\">\n                            \u003Ctable class=\"table table-hover\">\n                                \u003Cthead>\n                                    \u003Ctr>\n                                        \u003Cth>Produk\u003C\u002Fth>\n                                        \u003Cth>Harga\u003C\u002Fth>\n                                        \u003Cth>Aksi\u003C\u002Fth>\n                                    \u003C\u002Ftr>\n                                \u003C\u002Fthead>\n                                \u003Ctbody>\n                                    @foreach($outOfStockProducts as $product)\n                                    \u003Ctr>\n                                        \u003Ctd>\n                                            \u003Cdiv class=\"fw-bold\">{{ Str::limit($product->name, 20) }}\u003C\u002Fdiv>\n                                            \u003Csmall class=\"text-muted\">ID: {{ $product->id }}\u003C\u002Fsmall>\n                                        \u003C\u002Ftd>\n                                        \u003Ctd>Rp{{ number_format($product->price, 0, ',', '.') }}\u003C\u002Ftd>\n                                        \u003Ctd>\n                                            \u003Ca href=\"{{ route('products.edit', $product) }}\" \n                                               class=\"btn btn-sm btn-outline-primary\">\n                                                \u003Ci class=\"fas fa-edit\">\u003C\u002Fi>\n                                            \u003C\u002Fa>\n                                        \u003C\u002Ftd>\n                                    \u003C\u002Ftr>\n                                    @endforeach\n                                \u003C\u002Ftbody>\n                            \u003C\u002Ftable>\n                        \u003C\u002Fdiv>\n                    @else\n                        \u003Cdiv class=\"text-center py-4\">\n                            \u003Cdiv class=\"text-success mb-2\">\n                                \u003Ci class=\"fas fa-check-circle fa-3x\">\u003C\u002Fi>\n                            \u003C\u002Fdiv>\n                            \u003Ch6 class=\"text-success\">Stok Lengkap\u003C\u002Fh6>\n                            \u003Cp class=\"small text-muted\">Tidak ada produk yang habis\u003C\u002Fp>\n                        \u003C\u002Fdiv>\n                    @endif\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003C!-- TOP 5 STOK TERBANYAK -->\n    \u003Cdiv class=\"row\">\n        \u003Cdiv class=\"col-12\">\n            \u003Cdiv class=\"card shadow mb-4\">\n                \u003Cdiv class=\"card-header py-3\">\n                    \u003Ch6 class=\"m-0 font-weight-bold text-primary\">\n                        \u003Ci class=\"fas fa-trophy me-1\">\u003C\u002Fi>\n                        Top 5 Produk dengan Stok Terbanyak\n                    \u003C\u002Fh6>\n                \u003C\u002Fdiv>\n                \u003Cdiv class=\"card-body\">\n                    \u003Cdiv class=\"row\">\n                        @foreach($highStockProducts as $index => $product)\n                        \u003Cdiv class=\"col-lg mb-3\">\n                            \u003Cdiv class=\"card h-100\">\n                                \u003Cdiv class=\"card-body text-center\">\n                                    \u003C!-- Ranking Badge -->\n                                    \u003Cdiv class=\"mb-3\">\n                                        @if($index == 0)\n                                        \u003Cspan class=\"badge bg-warning text-dark px-3 py-2\">\n                                            \u003Ci class=\"fas fa-crown me-1\">\u003C\u002Fi> Juara 1\n                                        \u003C\u002Fspan>\n                                        @elseif($index == 1)\n                                        \u003Cspan class=\"badge bg-secondary px-3 py-2\">\n                                            \u003Ci class=\"fas fa-medal me-1\">\u003C\u002Fi> Juara 2\n                                        \u003C\u002Fspan>\n                                        @elseif($index == 2)\n                                        \u003Cspan class=\"badge bg-danger px-3 py-2\">\n                                            \u003Ci class=\"fas fa-medal me-1\">\u003C\u002Fi> Juara 3\n                                        \u003C\u002Fspan>\n                                        @else\n                                        \u003Cspan class=\"badge bg-primary px-3 py-2\">\n                                            #{{ $index + 1 }}\n                                        \u003C\u002Fspan>\n                                        @endif\n                                    \u003C\u002Fdiv>\n                                    \n                                    \u003C!-- Product Info -->\n                                    \u003Ch6 class=\"card-title\">{{ Str::limit($product->name, 18) }}\u003C\u002Fh6>\n                                    \u003Cdiv class=\"display-5 text-success fw-bold my-2\">{{ $product->stock }}\u003C\u002Fdiv>\n                                    \u003Cdiv class=\"small text-muted mb-3\">unit tersedia\u003C\u002Fdiv>\n                                    \n                                    \u003C!-- Actions -->\n                                    \u003Ca href=\"{{ route('products.edit', $product) }}\" \n                                       class=\"btn btn-sm btn-outline-success\">\n                                        \u003Ci class=\"fas fa-edit me-1\">\u003C\u002Fi> Kelola\n                                    \u003C\u002Fa>\n                                \u003C\u002Fdiv>\n                            \u003C\u002Fdiv>\n                        \u003C\u002Fdiv>\n                        @endforeach\n                    \u003C\u002Fdiv>\n                \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n@endsection\n\n@push('scripts')\n\u003Cscript src=\"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fchart.js\">\u003C\u002Fscript>\n\u003Cscript>\n\u002F\u002F 1. UPDATE WAKTU\nfunction updateTime() {\n    const now = new Date();\n    const timeString = now.toLocaleTimeString('id-ID');\n    document.getElementById('currentTime').textContent = timeString;\n    document.getElementById('chartUpdateTime').textContent = timeString;\n}\nsetInterval(updateTime, 1000);\n\n\u002F\u002F 2. GRAFIK\nconst ctx = document.getElementById('stockChart').getContext('2d');\nconst chart = new Chart(ctx, {\n    type: 'bar',\n    data: {\n        labels: @json($chartData['labels']),\n        datasets: [{\n            label: 'Stok',\n            data: @json($chartData['stocks']),\n            backgroundColor: @json($chartData['backgroundColors']),\n            borderColor: @json($chartData['borderColors']),\n            borderWidth: 1\n        }]\n    },\n    options: {\n        responsive: true,\n        maintainAspectRatio: false,\n        plugins: {\n            legend: { display: false }\n        },\n        scales: {\n            y: {\n                beginAtZero: true,\n                ticks: {\n                    callback: function(value) {\n                        return value.toLocaleString('id-ID');\n                    }\n                }\n            }\n        }\n    }\n});\n\n\u002F\u002F 3. AJAX REFRESH (opsional)\ndocument.getElementById('refreshBtn')?.addEventListener('click', function() {\n    fetch('{{ route(\"dashboard.data\") }}')\n        .then(response => response.json())\n        .then(data => {\n            console.log('Data refreshed:', data);\n            alert('Dashboard diperbarui!');\n        });\n});\n\u003C\u002Fscript>\n@endpush\n```\n\n---\n\n## **4. Ringkasan dan Cara Penggunaan**\n\n##### **A. Langkah-Langkah Implementasi:**\n\n1.**Buat Controller Dashboard:**\n```bash\n   php artisan make:controller DashboardController\n   ```\n  \n2.**Copy kode controller di atas ke file tersebut**\n\n3.**Update `routes\u002Fweb.php`** dengan routing yang sudah disediakan\n\n4.**Buat file view `dashboard.blade.php`** di `resources\u002Fviews\u002F`\n\n5.**Update navbar** untuk menambahkan link ke dashboard\n\n##### **B. Cara Mengakses:**\n\n1. **Login** terlebih dahulu di `\u002Flogin`\n2. **Setelah login**, akan diarahkan ke dashboard\n3. **Atau klik** dropdown user → pilih \"Dashboard\"\n4. **URL langsung:** `\u002Fdashboard`\n\n##### **C. Fitur yang Tersedia:**\n\n| Fitur | URL | Method | Keterangan |\n|-------|-----|--------|------------|\n| Dashboard utama | `\u002Fdashboard` | GET | Halaman utama dashboard |\n| Data AJAX | `\u002Fdashboard\u002Fdata` | GET | Data JSON untuk refresh |\n| List produk | `\u002Fproducts` | GET | Dari ProductController |\n| Tambah produk | `\u002Fproducts\u002Fcreate` | GET | Form tambah produk |\n| Edit produk | `\u002Fproducts\u002F{id}\u002Fedit` | GET | Form edit produk |\n\n##### **D. Keamanan:**\n\n1. **Semua route dashboard** dilindungi middleware `auth`\n2. **Hanya user yang login** bisa mengakses\n3. **Data user** ditampilkan di header dashboard\n4. **Route login\u002Flogout** berada di luar middleware\n\n---\n\n## **5. Testing Dashboard**\n\n**Berikut Merupakan Hasil Dashboard yang telah di kembangkan:**\n\n![](https:\u002F\u002Fcdn.rezweb.my.id\u002Fmedia\u002Ffc4e92ce-e75f-442e-8489-ccba0ad3abb9.webp)\n\n![](https:\u002F\u002Fcdn.rezweb.my.id\u002Fmedia\u002Fd6ceadd1-d2c0-4611-89e0-125717bd9d35.webp)\n\n```bash\n# Test melalui browser:\n1. http:\u002F\u002Flocalhost:8000\u002Flogin          # Login dulu\n2. http:\u002F\u002Flocalhost:8000\u002Fdashboard      # Dashboard utama\n3. http:\u002F\u002Flocalhost:8000\u002Fdashboard\u002Fdata # Data JSON\n```\n\nDashboard siap digunakan dengan **routing yang terstruktur**, **controller yang clean**, dan **tampilan yang informatif**!","https:\u002F\u002Fcdn.rezweb.my.id\u002Fposts\u002FeqIxZg7gGMUzNEKJM1JRByAqMn1YbQC9OWc5tj2A.jpg",1967,13,"2025-10-27T08:32:06+07:00","2026-09-07T11:59:40+07:00",{"name":18,"slug":19},"LARAVEL","laravel",{"id":21,"name":22,"username":23,"avatar":24},1,"Irez Abdullah","irezabdullah","https:\u002F\u002Fcdn.rezweb.my.id\u002Favatars\u002Fd139726e-348f-4dab-95c6-bb87e2ad125e.jpeg",{"name":26,"slug":27},"Belajar Laravel dari Nol (Praktikum Web Framework) – Ringkas & Praktis","belajar-laravel-dari-nol-praktikum-web-framework-ringkas-praktis",[29,33,38,43,48,53,58,63,68,73,78,83,88,89],{"id":30,"slug":31,"title":32,"part_number":21},48,"pengenalan-web-framework-instalasi-laravel","Pengenalan Web Framework & Instalasi Laravel",{"id":34,"slug":35,"title":36,"part_number":37},49,"struktur-folder-routing-dasar","Struktur Folder & Routing Dasar",2,{"id":39,"slug":40,"title":41,"part_number":42},50,"blade-template-layouting-dengan-bootstrap-5-dmwo","Blade Template & Layouting dengan Bootstrap 5",3,{"id":44,"slug":45,"title":46,"part_number":47},51,"database-migration-qbsa","Database & Migration",4,{"id":49,"slug":50,"title":51,"part_number":52},52,"model-seeder","Model & Seeder",5,{"id":54,"slug":55,"title":56,"part_number":57},53,"controller-read-data-menampilkan-produk","Controller & Read Data (Menampilkan Produk)",6,{"id":59,"slug":60,"title":61,"part_number":62},54,"form-tambah-produk-create","Form Tambah Produk (Create)",7,{"id":64,"slug":65,"title":66,"part_number":67},55,"edit-update-produk","Edit & Update Produk",8,{"id":69,"slug":70,"title":71,"part_number":72},56,"hapus-produk-validasi-form","Hapus Produk & Validasi Form",9,{"id":74,"slug":75,"title":76,"part_number":77},63,"upload-file-gambar-dan-validasi-cpw3","Upload File (Gambar) dan Validasi",10,{"id":79,"slug":80,"title":81,"part_number":82},62,"menampilkan-grafik-stok-produk","Menampilkan Grafik Stok Produk",11,{"id":84,"slug":85,"title":86,"part_number":87},64,"login-dan-implementasi-middleware-at","Login Dan Implementasi Middleware",12,{"id":8,"slug":10,"title":9,"part_number":14},{"id":90,"slug":91,"title":92,"part_number":93},65,"teknik-debugging-di-laravel","Teknik Debugging di Laravel",15,"Materi Lengkap: Membuat Dashboard Admin dengan Statistik dan Grafik di Laravel Persiapan dan Struktur Routing A. Update Routing File (`routes\u002Fweb.php`) B. Penje...",1788757405060]