import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Progress } from "~/components/ui/progress"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; import { Truck, Users, MapPin, TrendingUp, TrendingDown, Clock, CheckCircle, AlertTriangle, Calendar, BarChart3, Recycle, Package } from "lucide-react"; // Interface untuk activity interface Activity { id: number; type: string; title: string; time: string; status: string; driver?: string; volume?: string; estimatedComplete?: string; estimatedVolume?: string; reason?: string; } interface Truck { id: string; driver: string; status: string; location: string; capacity: string; lastUpdate: string; } interface WeeklyProgress { day: string; target: number; actual: number; } interface DashboardData { stats: { totalSampahHariIni: number; targetHarian: number; trukAktif: number; totalTruk: number; pegawaiAktif: number; totalPegawai: number; wilayahTerlayani: number; totalWilayah: number; }; recentActivities: Activity[]; trucks: Truck[]; weeklyProgress: WeeklyProgress[]; } // Loader untuk mengambil data dashboard export const loader = async (): Promise => { // Mock data - dalam implementasi nyata, ambil dari database const dashboardData: DashboardData = { stats: { totalSampahHariIni: 2450, // kg targetHarian: 3000, // kg trukAktif: 8, totalTruk: 12, pegawaiAktif: 24, totalPegawai: 30, wilayahTerlayani: 15, totalWilayah: 18 }, recentActivities: [ { id: 1, type: "pickup", title: "Pengangkutan selesai di Kelurahan Merdeka", time: "10 menit yang lalu", status: "completed", driver: "Budi Santoso", volume: "245 kg" }, { id: 2, type: "maintenance", title: "Truk B-002 menjalani maintenance rutin", time: "1 jam yang lalu", status: "in-progress", estimatedComplete: "14:00" }, { id: 3, type: "pickup", title: "Pengangkutan dimulai di Komplek Permata", time: "2 jam yang lalu", status: "in-progress", driver: "Andi Wijaya", estimatedVolume: "180 kg" }, { id: 4, type: "alert", title: "Jadwal pengangkutan tertunda di Jl. Sudirman", time: "3 jam yang lalu", status: "warning", reason: "Kemacetan lalu lintas" } ], trucks: [ { id: "B-001", driver: "Budi Santoso", status: "active", location: "Kelurahan Merdeka", capacity: "85%", lastUpdate: "5 menit yang lalu" }, { id: "B-002", driver: "Andi Wijaya", status: "maintenance", location: "Workshop", capacity: "0%", lastUpdate: "1 jam yang lalu" }, { id: "B-003", driver: "Sari Dewi", status: "active", location: "Komplek Permata", capacity: "60%", lastUpdate: "15 menit yang lalu" }, { id: "B-004", driver: "Dedi Kurniawan", status: "idle", location: "Pool Kendaraan", capacity: "0%", lastUpdate: "2 jam yang lalu" } ], weeklyProgress: [ { day: "Sen", target: 3000, actual: 2800 }, { day: "Sel", target: 3000, actual: 3200 }, { day: "Rab", target: 3000, actual: 2950 }, { day: "Kam", target: 3000, actual: 3100 }, { day: "Jum", target: 3000, actual: 2750 }, { day: "Sab", target: 2500, actual: 2450 }, { day: "Min", target: 2000, actual: 0 } // hari ini ] }; return json(dashboardData); }; export default function PengelolaDashboard() { const data = useLoaderData(); const getStatusBadge = (status: string) => { switch (status) { case "completed": return ( Selesai ); case "in-progress": return ( Berlangsung ); case "warning": return Peringatan; case "active": return ( Aktif ); case "maintenance": return ( Maintenance ); case "idle": return Standby; default: return {status}; } }; const getActivityIcon = (type: string) => { switch (type) { case "pickup": return ; case "maintenance": return ; case "alert": return ; default: return ; } }; const progressPercentage = Math.round( (data.stats.totalSampahHariIni / data.stats.targetHarian) * 100 ); return (
{/* Header Dashboard */}

Dashboard Pengelola

{/* Cards Statistik Utama */}
Sampah Terkumpul Hari Ini
{data.stats.totalSampahHariIni.toLocaleString()} kg

{progressPercentage}% dari target ( {data.stats.targetHarian.toLocaleString()} kg)

Truk Operasional
{data.stats.trukAktif}/{data.stats.totalTruk}

{Math.round((data.stats.trukAktif / data.stats.totalTruk) * 100)}% truk sedang beroperasi

Pegawai Aktif
{data.stats.pegawaiAktif}/{data.stats.totalPegawai}

{Math.round( (data.stats.pegawaiAktif / data.stats.totalPegawai) * 100 )} % pegawai sedang bertugas

Wilayah Terlayani
{data.stats.wilayahTerlayani}/{data.stats.totalWilayah}

{Math.round( (data.stats.wilayahTerlayani / data.stats.totalWilayah) * 100 )} % wilayah tercover hari ini

{/* Tabs untuk konten detail */} Aktivitas Terbaru Status Truk Performa Mingguan Aktivitas Terbaru Pantau semua aktivitas operasional secara real-time
{data.recentActivities.map((activity) => (
{getActivityIcon(activity.type)}

{activity.title}

{activity.time}

{activity.driver && ( • Driver: {activity.driver} )} {activity.volume && ( • {activity.volume} )} {activity.estimatedVolume && ( • Est: {activity.estimatedVolume} )} {activity.estimatedComplete && ( • Selesai: {activity.estimatedComplete} )} {activity.reason && ( • {activity.reason} )}
{getStatusBadge(activity.status)}
))}
Status Truk Real-time Monitor kondisi dan lokasi semua armada truk
{data.trucks.map((truck) => (

{truck.id}

Driver: {truck.driver}

Update: {truck.lastUpdate}

{getStatusBadge(truck.status)}

{truck.location}

Kapasitas: {truck.capacity}

))}
Performa Mingguan Pencapaian target pengumpulan sampah minggu ini
{data.weeklyProgress.map((day, index) => (
{day.day}
Target: {day.target.toLocaleString()} kg Actual: {day.actual.toLocaleString()} kg
0 ? (day.actual / day.target) * 100 : 0 } className="mt-1 h-2" />
{day.actual >= day.target ? ( ) : day.actual > 0 ? ( ) : ( )} {day.actual > 0 ? `${Math.round((day.actual / day.target) * 100)}%` : "-"}
))}
); }