From cae368adc0dcd0b050342ea279278c66fc426076 Mon Sep 17 00:00:00 2001 From: marszayn Date: Mon, 10 Mar 2025 13:59:31 +0700 Subject: [PATCH] feat: Menambahkan validasi file dan relasi model --- app/Http/Requests/PerusahaanRequest.php | 2 +- app/Models/Perusahaan.php | 9 + .../detail_history_perusahaan.tsx | 808 ++++++++++++++++++ .../index_history_perusahaan.tsx | 301 +++++++ resources/js/types/perusahaan.ts | 38 + 5 files changed, 1157 insertions(+), 1 deletion(-) create mode 100644 resources/js/pages/admin/history_perusahaan/detail_history_perusahaan.tsx create mode 100644 resources/js/pages/admin/history_perusahaan/index_history_perusahaan.tsx diff --git a/app/Http/Requests/PerusahaanRequest.php b/app/Http/Requests/PerusahaanRequest.php index ed0f795..f0e6cce 100644 --- a/app/Http/Requests/PerusahaanRequest.php +++ b/app/Http/Requests/PerusahaanRequest.php @@ -40,7 +40,7 @@ class PerusahaanRequest extends FormRequest 'JenisDokILId' => ['integer'], 'VerifikatorId' => ['required', 'integer'], 'IsPublish' => ['required', 'boolean'], - 'ILDokumen' => ['string'], + 'ILDokumen' => 'nullable|file|mimes:pdf|max:2048', 'Kawasan' => ['string'], ]; } diff --git a/app/Models/Perusahaan.php b/app/Models/Perusahaan.php index 1da21e3..9302757 100644 --- a/app/Models/Perusahaan.php +++ b/app/Models/Perusahaan.php @@ -5,6 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; class Perusahaan extends Model @@ -92,7 +93,15 @@ class Perusahaan extends Model return $this->belongsTo(JenisDokIL::class, 'JenisDokILId', 'JenisDokILId'); } + public function historyKegiatan() + { + return $this->belongsTo(HistoryKegiatan::class, 'HistoryKegiatanId', 'HistoryKegiatanId'); + } + public function historyPerusahaan(): HasMany + { + return $this->hasMany(HistoryPerusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } } diff --git a/resources/js/pages/admin/history_perusahaan/detail_history_perusahaan.tsx b/resources/js/pages/admin/history_perusahaan/detail_history_perusahaan.tsx new file mode 100644 index 0000000..a12e636 --- /dev/null +++ b/resources/js/pages/admin/history_perusahaan/detail_history_perusahaan.tsx @@ -0,0 +1,808 @@ +import React, { useEffect, useState } from "react"; +import AuthenticatedLayout from "@/layouts/authenticated-layout"; +import { Head, Link, router, useForm } from "@inertiajs/react"; +import Select from "react-select"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; + +// Komponen shadcn/ui untuk date range (contoh) +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { Calendar } from "@/components/ui/calendar"; +import { Button } from "@/components/ui/button"; +import { ArrowLeft, CalendarIcon, Edit, Printer } from "lucide-react"; +import { format } from "date-fns"; +import { cn } from "@/lib/utils"; // biasanya helper classNames +import { DateRange } from "react-day-picker"; +import { FileText } from "lucide-react"; +import { + Perusahaan, + HistoryKegiatan, + HistoryPerusahaan as HistoryPerusahaanType, +} from "@/types/perusahaan"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { useToast } from "@/hooks/use-toast"; + +type DetailHistoryPerusahaanProps = { + perusahaan: Perusahaan; + historyKegiatan: HistoryKegiatan[]; + historyPerusahaan: HistoryPerusahaanType[]; // data existing +}; + +export default function DetailHistoryPerusahaan({ + perusahaan, + historyKegiatan, + historyPerusahaan = [], +}: DetailHistoryPerusahaanProps) { + const { toast } = useToast(); + + useEffect(() => { + console.log("Isi Data History Perusahaan:", historyPerusahaan); + }, [historyPerusahaan]); + + // -------------------- + // 1. STATE FILTER + // -------------------- + // Date range + const [dateRange, setDateRange] = useState({ + from: undefined, + to: undefined, + }); + // Kelompok Kegiatan + const [selectedKegiatan, setSelectedKegiatan] = useState<{ + value: string; + label: string; + } | null>(null); + + // State data terfilter + const [filteredData, setFilteredData] = + useState(historyPerusahaan); + + // Fungsi untuk memproses filter + function handleFilter() { + let filtered = [...historyPerusahaan]; + + // Filter rentang tanggal + if (dateRange?.from && dateRange?.to) { + const fromDay = format(dateRange.from, "yyyy-MM-dd"); + const toDay = format(dateRange.to, "yyyy-MM-dd"); + + filtered = filtered.filter((item) => { + if (!item.TanggalHistory) return false; + const itemDay = format( + new Date(item.TanggalHistory), + "yyyy-MM-dd" + ); + return itemDay >= fromDay && itemDay <= toDay; + }); + } + + // Filter Kelompok Kegiatan + if (selectedKegiatan) { + filtered = filtered.filter( + (item) => + item.HistoryKegiatanId.toString() === selectedKegiatan.value + ); + } + + setFilteredData(filtered); + } + + // Fungsi untuk mereset filter pencarian + function handleReset() { + setDateRange({ from: undefined, to: undefined }); + setSelectedKegiatan(null); + setFilteredData(historyPerusahaan); + } + + function handleBack() { + // Misal kembali ke halaman sebelumnya + window.history.back(); + } + + function handlePrint() { + // Contoh simpel: memanggil window.print() + window.print(); + } + + function handleExportPDF() { + // Contoh panggil route export PDF, atau link ke PDF + // Misal router.visit(route("pdf.export", { id: 123 })); + // Atau window.open("/path/to/pdf", "_blank"); + alert("Export PDF belum diimplementasikan."); + } + + // -------------------- + // 2. STATE FORM TAMBAH HISTORY + // -------------------- + const [showModal, setShowModal] = useState(false); + + const { data, setData, post, processing, errors, reset } = useForm({ + PerusahaanId: perusahaan.PerusahaanId, + NomorHistory: "", + TanggalHistory: "", + HistoryKegiatanId: "", + KeteranganHistory: "", + DokumenHistory: null as File | null, + }); + + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + post(route("admin.history_perusahaan.store", perusahaan.PerusahaanId), { + onSuccess: () => { + router.visit(window.location.href, { replace: true }); + setShowModal(false); + reset(); + toast({ + title: "Sukses", + description: "History Perusahaan berhasil ditambahkan", + variant: "default", + }); + }, + onError: (errors) => { + toast({ + title: "Error", + description: "Gagal menambahkan history perusahaan", + variant: "destructive", + }); + }, + }); + } + + // -------------------- + // 3. STATE & FORM UNTUK EDIT HISTORY + // -------------------- + const [showEditModal, setShowEditModal] = useState(false); + const [editingItem, setEditingItem] = + useState(null); + + const { + data: editData, + setData: setEditData, + post: postEdit, + processing: editProcessing, + errors: editErrors, + reset: resetEditForm, + } = useForm({ + HistoryPerusahaanId: "", + PerusahaanId: perusahaan.PerusahaanId, + NomorHistory: "", + TanggalHistory: "", + HistoryKegiatanId: "", + KeteranganHistory: "", + DokumenHistory: null as File | null, + }); + + function handleEdit(item: HistoryPerusahaanType) { + setEditingItem(item); + setEditData("HistoryPerusahaanId", item.HistoryPerusahaanId); + setEditData("NomorHistory", item.NomorHistory); + setEditData("TanggalHistory", item.TanggalHistory); + setEditData("HistoryKegiatanId", item.HistoryKegiatanId.toString()); + setEditData("KeteranganHistory", item.KeteranganHistory); + setShowEditModal(true); + } + + function handleEditSubmit(e: React.FormEvent) { + e.preventDefault(); + postEdit( + route( + "admin.history_perusahaan.update", + editData.HistoryPerusahaanId + ), + { + onSuccess: () => { + router.visit(window.location.href, { replace: true }); + setShowEditModal(false); + resetEditForm(); + toast({ + title: "Sukses", + description: "History Perusahaan berhasil diperbarui", + variant: "default", + }); + }, + onError: () => { + toast({ + title: "Error", + description: "Gagal memperbarui history perusahaan", + variant: "destructive", + }); + }, + } + ); + } + + // -------------------- + // 4. RENDER HALAMAN + // -------------------- + return ( + + +
+
+
+

+ History Perusahaan: {perusahaan.NamaPerusahaan} +

+

+ Nomor Induk: {perusahaan.NomorInduk || "-"} +

+
+ +
+ + + +
+
+ {/* Bagian Filter */} +
+ + + + Pencarian + + + +
+ {/* Filter Rentang Tanggal */} +
+ + + + + + + + + +
+ + {/* Filter Kelompok Kegiatan - Using react-select */} +
+ + + setData("NomorHistory", e.target.value) + } + className="border border-gray-300 rounded w-full p-2" + /> + {errors.NomorHistory && ( +
+ {errors.NomorHistory} +
+ )} +
+ + {/* Tanggal Surat */} +
+ + + setData( + "TanggalHistory", + e.target.value + ) + } + className="border border-gray-300 rounded w-full p-2" + /> + {errors.TanggalHistory && ( +
+ {errors.TanggalHistory} +
+ )} +
+ + {/* Kelompok Kegiatan */} +
+ +