import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { useState } from "react"; // Interface untuk data waste interface WasteData { id: string; trash_name: string; trash_icon: string; estimated_price: number; variety: string; created_at: string; updated_at: string; } import { Recycle, Plus, Search, Filter, MoreHorizontal, Edit, Trash2, TrendingUp, TrendingDown, Package, FileText, Coffee, Cpu, Archive, Glasses, X, Save } from "lucide-react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import { Badge } from "~/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "~/components/ui/dropdown-menu"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "~/components/ui/dialog"; import { Label } from "~/components/ui/label"; import { Textarea } from "~/components/ui/textarea"; // Icon mapping untuk setiap jenis sampah const getWasteIcon = (trashName: string) => { const name = trashName.toLowerCase(); if (name.includes("plastik")) return Package; if (name.includes("kertas")) return FileText; if (name.includes("kaleng")) return Coffee; if (name.includes("besi") || name.includes("tembaga")) return Cpu; if (name.includes("kardus")) return Archive; if (name.includes("kaca") || name.includes("beling")) return Glasses; return Recycle; // default icon }; export const loader = async () => { // Simulasi data API sesuai format yang diminta const wasteData = { meta: { status: 200, message: "Trash categories retrieved successfully" }, data: [ { id: "9520dfd4-3bc8-4173-ac3d-4b17d466bc90", trash_name: "Plastik", trash_icon: "/uploads/icontrash/a4e99d8c-8380-470f-87f1-01dc62fbe114_icontrash.png", estimated_price: 1500, variety: "Jerigen plastik, tempat makanan thin wall, ember, galon air mineral, botol sabun, botol, sampo dan plastik keras sejenisnya", created_at: "2025-06-12T05:08:43+07:00", updated_at: "2025-06-12T05:08:43+07:00" }, { id: "8636ceee-6c13-41ab-abc6-5b0c603ba360", trash_name: "Kertas", trash_icon: "/uploads/icontrash/a6414ed3-0675-4b38-a2c7-c6d3d24810cf_icontrash.png", estimated_price: 1250, variety: "Kertas HVS, koran, majalah, buku, kertas, karton dan sejenisnya", created_at: "2025-06-12T05:10:21+07:00", updated_at: "2025-06-12T05:10:21+07:00" }, { id: "bec932a7-da0a-4e7b-b33c-a5e225e56cef", trash_name: "Kaleng", trash_icon: "/uploads/icontrash/49b2ca06-cbfe-4650-bfb9-7d14aff2e09b_icontrash.png", estimated_price: 1000, variety: "Kaleng sarden, kaleng aerosol, kaleng makanan, dll", created_at: "2025-06-12T05:14:38+07:00", updated_at: "2025-06-12T05:14:38+07:00" }, { id: "9af0a2f2-4c9c-49b0-8f0b-ea8c38d9edd3", trash_name: "Besi/Tembaga", trash_icon: "/uploads/icontrash/2a80005a-3038-4192-b70c-b22a54f11ae6_icontrash.png", estimated_price: 3500, variety: "Besi, tembaga, aluminium", created_at: "2025-06-12T05:16:44+07:00", updated_at: "2025-06-12T05:16:44+07:00" }, { id: "c5319782-b658-4639-83aa-8b88feb1b2a8", trash_name: "Kardus", trash_icon: "/uploads/icontrash/1d900090-4b24-4d42-9c0e-e486839b9f63_icontrash.png", estimated_price: 1500, variety: "Kardus paket, kardus kemasan produk, dll", created_at: "2025-06-12T05:19:15+07:00", updated_at: "2025-06-12T05:19:15+07:00" }, { id: "131c7ca9-6f2d-4e98-a016-916c23ec45e9", trash_name: "Kaca/Beling", trash_icon: "/uploads/icontrash/3be4f3ab-99a2-4b3c-930b-b2e0055cd705_icontrash.png", estimated_price: 500, variety: "Botol kaca minuman, botol kaca kosmetik, botol sirup, botol saus, botol kecap, gelas kaca, piring kaca dan sejenisnya", created_at: "2025-06-12T05:21:55+07:00", updated_at: "2025-06-12T05:21:55+07:00" } ] }; // Hitung summary dari data const summary = { totalTypes: wasteData.data.length, totalVolume: 0, // Tidak ada data volume di API baru avgPrice: Math.round( wasteData.data.reduce((sum, item) => sum + item.estimated_price, 0) / wasteData.data.length ), trending: "up" }; return json({ wasteData: wasteData.data, summary }); }; export default function WasteManagement() { const { wasteData, summary } = useLoaderData(); // State untuk modal const [showAddModal, setShowAddModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); const [selectedWaste, setSelectedWaste] = useState(null); // State untuk form const [formData, setFormData] = useState({ trash_name: "", estimated_price: "", variety: "" }); // Handle form change const handleFormChange = (field: string, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })); }; // Handle add const handleAdd = () => { setFormData({ trash_name: "", estimated_price: "", variety: "" }); setShowAddModal(true); }; // Handle edit const handleEdit = (waste: WasteData) => { setSelectedWaste(waste); setFormData({ trash_name: waste.trash_name, estimated_price: waste.estimated_price.toString(), variety: waste.variety }); setShowEditModal(true); }; // Handle delete const handleDelete = (waste: WasteData) => { setSelectedWaste(waste); setShowDeleteModal(true); }; // Handle save (add/edit) const handleSave = () => { // Di sini Anda bisa menambahkan logika untuk menyimpan data console.log("Saving data:", formData); setShowAddModal(false); setShowEditModal(false); // Reset form setFormData({ trash_name: "", estimated_price: "", variety: "" }); }; // Handle confirm delete const handleConfirmDelete = () => { // Di sini Anda bisa menambahkan logika untuk menghapus data if (selectedWaste) { console.log("Deleting:", selectedWaste); } setShowDeleteModal(false); setSelectedWaste(null); }; return (
{/* Header */}

Manajemen Data Sampah

Kelola jenis sampah, harga, dan variety transaksi

{/* Summary Cards */}
Total Jenis
{summary.totalTypes}

jenis sampah terdaftar

Rata-rata Harga
Rp {summary.avgPrice.toLocaleString()}

per kilogram

Trend Harga {summary.trending === "up" ? ( ) : ( )}
Naik

dibanding bulan lalu

{/* Filter and Search */}
Daftar Jenis Sampah Kelola jenis sampah dan harga terkini
Icon Nama Sampah Harga Estimasi Variety Aksi {wasteData.map((waste) => { const IconComponent = getWasteIcon(waste.trash_name); return (
{waste.trash_name} Rp {waste.estimated_price.toLocaleString()}
{waste.variety}
handleEdit(waste)} > Edit handleDelete(waste)} > Hapus
); })}
{/* Add Modal */} Tambah Jenis Sampah Tambahkan jenis sampah baru dengan detail lengkap
handleFormChange("trash_name", e.target.value)} placeholder="Masukkan nama sampah" />
handleFormChange("estimated_price", e.target.value) } placeholder="Masukkan harga per kg" />