import { useState } from "react"; import { trpc } from "@/providers/trpc"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Search, Plus, MapPin, Pencil, Trash2, Users, CheckCircle, AlertCircle, XCircle, Eye, } from "lucide-react"; const STATUS_OPTIONS = [ { value: "all", label: "Semua" }, { value: "active", label: "Aktif" }, { value: "pending", label: "Menunggu" }, { value: "rejected", label: "Ditolak" }, { value: "suspended", label: "Ditangguhkan" }, ]; export default function RecipientsPage() { const [search, setSearch] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const [isAddOpen, setIsAddOpen] = useState(false); const [isEditOpen, setIsEditOpen] = useState(false); const [isViewOpen, setIsViewOpen] = useState(false); const [selectedRecipient, setSelectedRecipient] = useState(null); const [formData, setFormData] = useState({ nik: "", name: "", birthDate: "", gender: "male" as "male" | "female", address: "", phone: "", familyMembers: 1, incomePerMonth: 0, placeOfWorshipId: 1, notes: "", latitude: "", longitude: "", }); const utils = trpc.useUtils(); const { data: recipients, isLoading } = trpc.recipient.list.useQuery({ search: search || undefined, status: statusFilter === "all" ? undefined : statusFilter, }); const { data: places } = trpc.placeOfWorship.list.useQuery({}); const createMutation = trpc.recipient.create.useMutation({ onSuccess: () => { utils.recipient.list.invalidate(); utils.dashboard.stats.invalidate(); setIsAddOpen(false); resetForm(); }, }); const updateMutation = trpc.recipient.update.useMutation({ onSuccess: () => { utils.recipient.list.invalidate(); setIsEditOpen(false); resetForm(); }, }); const deleteMutation = trpc.recipient.delete.useMutation({ onSuccess: () => { utils.recipient.list.invalidate(); utils.dashboard.stats.invalidate(); }, }); const resetForm = () => { setFormData({ nik: "", name: "", birthDate: "", gender: "male", address: "", phone: "", familyMembers: 1, incomePerMonth: 0, placeOfWorshipId: 1, notes: "", latitude: "", longitude: "", }); setSelectedRecipient(null); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!formData.nik || !formData.name) return; createMutation.mutate({ nik: formData.nik, name: formData.name, birthDate: formData.birthDate || undefined, gender: formData.gender, address: formData.address || undefined, phone: formData.phone || undefined, familyMembers: formData.familyMembers, incomePerMonth: formData.incomePerMonth, placeOfWorshipId: formData.placeOfWorshipId, notes: formData.notes || undefined, latitude: formData.latitude ? parseFloat(formData.latitude) : undefined, longitude: formData.longitude ? parseFloat(formData.longitude) : undefined, }); }; const handleEdit = (recipient: NonNullable[number]) => { setFormData({ nik: recipient.nik, name: recipient.name, birthDate: recipient.birthDate ?? "", gender: (recipient.gender as "male" | "female") ?? "male", address: recipient.address ?? "", phone: recipient.phone ?? "", familyMembers: recipient.familyMembers ?? 1, incomePerMonth: recipient.incomePerMonth ?? 0, placeOfWorshipId: recipient.placeOfWorshipId, notes: recipient.notes ?? "", latitude: recipient.latitude?.toString() ?? "", longitude: recipient.longitude?.toString() ?? "", }); setSelectedRecipient(recipient.id); setIsEditOpen(true); }; const handleUpdate = (e: React.FormEvent) => { e.preventDefault(); if (!selectedRecipient) return; updateMutation.mutate({ id: selectedRecipient, nik: formData.nik, name: formData.name, birthDate: formData.birthDate || undefined, gender: formData.gender, address: formData.address || undefined, phone: formData.phone || undefined, familyMembers: formData.familyMembers, incomePerMonth: formData.incomePerMonth, placeOfWorshipId: formData.placeOfWorshipId, notes: formData.notes || undefined, latitude: formData.latitude ? parseFloat(formData.latitude) : undefined, longitude: formData.longitude ? parseFloat(formData.longitude) : undefined, }); }; const statusBadge = (status: string) => { switch (status) { case "active": return Aktif; case "pending": return Menunggu; case "rejected": return Ditolak; case "suspended": return Ditangguhkan; default: return {status}; } }; const selectedRec = recipients?.find((r) => r.id === selectedRecipient); return (

Penerima Bantuan

Kelola data warga penerima bantuan sosial

Tambah Penerima Baru
setFormData({ ...formData, nik: e.target.value })} placeholder="16 digit" maxLength={16} className="h-9" />
setFormData({ ...formData, name: e.target.value })} placeholder="Nama" className="h-9" />
setFormData({ ...formData, birthDate: e.target.value })} className="h-9" />
setFormData({ ...formData, address: e.target.value })} placeholder="Alamat lengkap" className="h-9" />
setFormData({ ...formData, phone: e.target.value })} placeholder="08xxxxxxxxxx" className="h-9" />
setFormData({ ...formData, familyMembers: parseInt(e.target.value) || 1 })} className="h-9" />
setFormData({ ...formData, incomePerMonth: parseInt(e.target.value) || 0 })} className="h-9" />
setFormData({ ...formData, latitude: e.target.value })} placeholder="-6.xxxx" className="h-9" />
setFormData({ ...formData, longitude: e.target.value })} placeholder="106.xxxx" className="h-9" />
setFormData({ ...formData, notes: e.target.value })} placeholder="Catatan tambahan" className="h-9" />
{/* Filters */}
setSearch(e.target.value)} className="pl-9 h-9" />
{/* Table */} {isLoading ? (
{Array.from({ length: 5 }).map((_, i) => ( ))}
) : (recipients ?? []).length === 0 ? (

Belum ada data penerima

Tambahkan penerima baru untuk memulai

) : (
NIK Nama Status Rumah Ibadah Keluarga Pendapatan Aksi {(recipients ?? []).map((r) => ( {r.nik} {r.name} {statusBadge(r.status)} {places?.find((p) => p.id === r.placeOfWorshipId)?.name ?? "-"} {r.familyMembers} Rp {(r.incomePerMonth ?? 0).toLocaleString("id-ID")}
))}
)}
{/* Edit Dialog */} Edit Penerima
setFormData({ ...formData, nik: e.target.value })} className="h-9" />
setFormData({ ...formData, name: e.target.value })} className="h-9" />
setFormData({ ...formData, birthDate: e.target.value })} className="h-9" />
setFormData({ ...formData, address: e.target.value })} className="h-9" />
setFormData({ ...formData, phone: e.target.value })} className="h-9" />
setFormData({ ...formData, familyMembers: parseInt(e.target.value) || 1 })} className="h-9" />
setFormData({ ...formData, incomePerMonth: parseInt(e.target.value) || 0 })} className="h-9" />
setFormData({ ...formData, latitude: e.target.value })} className="h-9" />
setFormData({ ...formData, longitude: e.target.value })} className="h-9" />
{/* View Dialog */} Detail Penerima {selectedRec && (
{selectedRec.name} {statusBadge(selectedRec.status)}
NIK: {selectedRec.nik}
Telepon: {selectedRec.phone ?? "-"}
Tgl Lahir: {selectedRec.birthDate ?? "-"}
JK: {selectedRec.gender === "male" ? "Laki-laki" : "Perempuan"}
Keluarga: {selectedRec.familyMembers} orang
Pendapatan: Rp {(selectedRec.incomePerMonth ?? 0).toLocaleString()}
{selectedRec.address && (
Alamat: {selectedRec.address}
)} {selectedRec.latitude && selectedRec.longitude && (
{selectedRec.latitude}, {selectedRec.longitude}
)} {selectedRec.notes && (
Catatan: {selectedRec.notes}
)}
)}
); }