feat: Menambahkan controller, request, dan halaman index perizinan lingkungan

main
marszayn 2025-03-10 14:01:46 +07:00
parent 113d2eb8d1
commit 2d6918cdbc
3 changed files with 455 additions and 0 deletions

View File

@ -0,0 +1,139 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\PerizinanLingkunganRequest;
use App\Http\Requests\PerusahaanRequest;
use App\Models\JenisDokIL;
use App\Models\JenisKegiatan;
use App\Models\Perusahaan;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
class PerizinanLingkunganController extends Controller
{
public function index()
{
// Mengambil data perusahaan beserta relasinya (misal: jenis kegiatan & jenis dokumen izin)
$perusahaan = Perusahaan::with(['jenisKegiatan', 'jenisDokIL'])->get();
// Mengambil data jenis dokumen izin lingkungan
$jenisKegiatan = JenisKegiatan::all();
$jenisDokIL = JenisDokIL::all();
return Inertia::render('admin/perizinan_lingkungan/index_perizinan_lingkungan', [
'perusahaan' => $perusahaan,
'jenisKegiatan' => $jenisKegiatan,
'jenisDokIL' => $jenisDokIL,
]);
}
// public function update(PerusahaanRequest $request, Perusahaan $perusahaan)
// {
// try {
// DB::beginTransaction();
// $data = $request->validated();
// // Jika tidak ada file ILDokumen yang di-upload, hapus key tersebut agar tidak mengubah nilai sebelumnya
// if (!$request->hasFile('ILDokumen')) {
// unset($data['ILDokumen']);
// } else {
// // Jika sudah ada file sebelumnya, hapus file lama terlebih dahulu
// if ($perusahaan->ILDokumen && Storage::disk('public')->exists($perusahaan->ILDokumen)) {
// Storage::disk('public')->delete($perusahaan->ILDokumen);
// }
// // Buat nama file baru berdasarkan waktu upload dan nama file asli
// $fileName = time() . '_' . $request->file('ILDokumen')->getClientOriginalName();
// $path = $request->file('ILDokumen')->storeAs('files/il', $fileName, 'public');
// $data['ILDokumen'] = $path;
// }
// // Update data perusahaan (termasuk data perizinan lingkungan)
// $perusahaan->update($data);
// DB::commit();
// return redirect()->route('admin.perizinan_lingkungan.index')
// ->with('success', 'Data perizinan lingkungan berhasil diperbarui');
// } catch (\Exception $e) {
// DB::rollBack();
// Log::error('Error updating perizinan lingkungan: ' . $e->getMessage());
// return response()->json(['message' => 'Error: ' . $e->getMessage()], 500);
// }
// }
// public function update(PerizinanLingkunganRequest $request, Perusahaan $perusahaan)
// {
// try {
// DB::beginTransaction();
// $data = $request->validated();
// $perusahaan->ILNomor = $data['ILNomor'] ?? $perusahaan->ILNomor;
// $perusahaan->ILTanggal = $data['ILTanggal'] ?? $perusahaan->ILTanggal;
// $perusahaan->JenisKegiatanId = $data['JenisKegiatanId'] ?? $perusahaan->JenisKegiatanId;
// if ($request->hasFile('ILDokumen')) {
// if ($perusahaan->ILDokumen && Storage::disk('public')->exists($perusahaan->ILDokumen)) {
// Storage::disk('public')->delete($perusahaan->ILDokumen);
// }
// $file = $request->file('ILDokumen');
// $filename = time() . '_' . $file->getClientOriginalName();
// $path = $file->storeAs('files/il', $filename, 'public');
// $perusahaan->ILDokumen = $path;
// }
// $perusahaan->save();
// DB::commit();
// return redirect()->route('admin.perizinan_lingkungan.index')
// ->with('success', 'Data perizinan lingkungan berhasil diperbarui');
// } catch (\Exception $e) {
// DB::rollBack();
// Log::error('Error updating perizinan lingkungan: ' . $e->getMessage());
// return back()->withErrors(['error' => $e->getMessage()]);
// }
// }
public function update(PerizinanLingkunganRequest $request, Perusahaan $perusahaan)
{
try {
DB::beginTransaction();
// Ambil data lengkap dari model (pastikan semua field termasuk yang wajib ada)
$existingData = $perusahaan->getAttributes();
// Ambil data baru hanya dari field perizinan
$newData = $request->only(['ILNomor', 'ILTanggal', 'JenisKegiatanId']);
if ($request->hasFile('ILDokumen')) {
if ($perusahaan->ILDokumen && Storage::disk('public')->exists($perusahaan->ILDokumen)) {
Storage::disk('public')->delete($perusahaan->ILDokumen);
}
$file = $request->file('ILDokumen');
$filename = time() . '_' . $file->getClientOriginalName();
$path = $file->storeAs('files/il', $filename, 'public');
$newData['ILDokumen'] = $path;
}
// Gabungkan data lama dengan data baru (field baru akan override data lama)
$data = array_merge($existingData, $newData);
$perusahaan->update($data);
DB::commit();
return redirect()->route('admin.perizinan_lingkungan.index')
->with('success', 'Data perizinan lingkungan berhasil diperbarui');
} catch (\Exception $e) {
DB::rollBack();
Log::error('Error updating perizinan lingkungan: ' . $e->getMessage());
return back()->withErrors(['error' => $e->getMessage()]);
}
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PerizinanLingkunganRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'ILNomor' => 'nullable|string',
'ILTanggal' => 'nullable|date',
'JenisKegiatanId' => 'nullable|exists:JenisKegiatan,JenisKegiatanId',
'ILDokumen' => 'nullable|file|mimes:pdf|max:20480',
];
}
}

View File

@ -0,0 +1,285 @@
import React, { useState } from "react";
import AuthenticatedLayout from "@/layouts/authenticated-layout";
import { Head } from "@inertiajs/react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import FilterPerizinanLingkungan from "@/components/PerizinanLingkungan/FilterPencarian";
import { Perusahaan, JenisDokIL, JenisKegiatan } from "@/types/perusahaan";
import { FileText } from "lucide-react";
import { ModalIzinLingkungan } from "@/components/PerizinanLingkungan/ModalIzinLingkungan";
type PerizinanLingkunganIndexProps = {
perusahaan: Perusahaan[];
jenisDokIL: JenisDokIL[];
jenisKegiatan: JenisKegiatan[];
};
export default function PerizinanLingkunganIndex({
perusahaan,
jenisDokIL,
jenisKegiatan,
}: PerizinanLingkunganIndexProps) {
const [selectedPerusahaan, setSelectedPerusahaan] =
useState<Perusahaan | null>(null);
const [showModal, setShowModal] = useState(false);
// Handler ketika klik kolom "Jenis Izin"
const handleJenisIzinClick = (p: Perusahaan) => {
setSelectedPerusahaan(p);
setShowModal(true);
};
const handleModalClose = () => {
setShowModal(false);
setSelectedPerusahaan(null);
};
// Callback jika upload dokumen sukses, maka reload atau refresh data
const handleUploadSuccess = () => {
setShowModal(false);
setSelectedPerusahaan(null);
// contoh reload:
// window.location.reload();
// atau bisa panggil inertia visit:
// router.reload();
};
// State untuk data yang ditampilkan pada tabel
const [filteredPerusahaan, setFilteredPerusahaan] =
useState<Perusahaan[]>(perusahaan);
// Callback dari FilterPerizinanLingkungan
const handleSearch = (filters: {
selectedPerusahaan: { value: string; label: string } | null;
selectedJenisKegiatan: { value: string; label: string } | null;
Alamat: string;
TeleponFax: string;
Email: string;
selectedJenisIzin: { value: string; label: string } | null;
ILNomor: string;
ILTanggal: string | null;
}) => {
let result = [...perusahaan];
if (filters.selectedPerusahaan) {
result = result.filter(
(p) =>
p.PerusahaanId.toString() ===
filters.selectedPerusahaan?.value
);
}
if (filters.selectedJenisKegiatan) {
result = result.filter(
(p) =>
p.JenisKegiatanId?.toString() ===
filters.selectedJenisKegiatan?.value
);
}
if (filters.Alamat.trim() !== "") {
result = result.filter((p) =>
p.Alamat?.toLowerCase().includes(filters.Alamat.toLowerCase())
);
}
if (filters.TeleponFax.trim() !== "") {
result = result.filter((p) => {
const telMatch = p.Telepon?.toLowerCase().includes(
filters.TeleponFax.toLowerCase()
);
const faxMatch = p.Fax?.toLowerCase().includes(
filters.TeleponFax.toLowerCase()
);
return telMatch || faxMatch;
});
}
if (filters.Email.trim() !== "") {
result = result.filter((p) =>
p.Email?.toLowerCase().includes(filters.Email.toLowerCase())
);
}
if (filters.selectedJenisIzin) {
result = result.filter(
(p) =>
p.JenisDokILId?.toString() ===
filters.selectedJenisIzin?.value
);
}
if (filters.ILNomor.trim() !== "") {
result = result.filter((p) =>
p.ILNomor?.toLowerCase().includes(filters.ILNomor.toLowerCase())
);
}
if (filters.ILTanggal) {
// Asumsikan format filter "yyyy-MM-dd" atau "yyyy-MM-dd - yyyy-MM-dd"
if (filters.ILTanggal.includes(" - ")) {
const [from, to] = filters.ILTanggal.split(" - ");
result = result.filter((p) => {
if (!p.ILTanggal) return false;
const itemDate = format(
new Date(p.ILTanggal),
"yyyy-MM-dd"
);
return itemDate >= from && itemDate <= to;
});
} else {
result = result.filter((p) => {
if (!p.ILTanggal) return false;
const itemDate = format(
new Date(p.ILTanggal),
"yyyy-MM-dd"
);
return itemDate === filters.ILTanggal;
});
}
}
setFilteredPerusahaan(result);
};
return (
<AuthenticatedLayout header="Perizinan Lingkungan">
<Head title="Perizinan Lingkungan" />
<ModalIzinLingkungan
open={showModal}
onClose={handleModalClose}
onSuccess={handleUploadSuccess}
selectedPerusahaan={selectedPerusahaan}
// jenisDokIL={jenisDokIL}
jenisKegiatan={jenisKegiatan}
/>
{/* Komponen Filter */}
<FilterPerizinanLingkungan
perusahaan={perusahaan}
jenisDokIL={jenisDokIL}
jenisKegiatan={jenisKegiatan}
izinLingkungan={[]} // bisa dihilangkan jika filtering dilakukan pada data perusahaan
onSearch={handleSearch}
/>
{/* Tabel Data */}
<div className="w-full overflow-x-auto">
<Table className="min-w-[900px] border-collapse">
<TableHeader>
<TableRow className="border-b bg-green-800">
<TableHead className="text-white text-center border-r w-16">
No.
</TableHead>
<TableHead className="text-white text-center border-r">
Nama Perusahaan
</TableHead>
<TableHead className="text-white text-center border-r">
Jenis Kegiatan
</TableHead>
<TableHead className="text-white text-center border-r">
Alamat
</TableHead>
<TableHead className="text-white text-center border-r">
Telepon / Fax
</TableHead>
<TableHead className="text-white text-center border-r">
Email
</TableHead>
<TableHead className="text-white text-center border-r">
Jenis Izin
</TableHead>
<TableHead className="text-white text-center border-r">
Nomor Izin
</TableHead>
<TableHead className="text-white text-center border-r">
Tanggal Izin
</TableHead>
<TableHead className="text-white text-center border-r">
Dok
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredPerusahaan.length === 0 ? (
<TableRow>
<TableCell
colSpan={9}
className="text-center py-4"
>
Tidak ada data
</TableCell>
</TableRow>
) : (
filteredPerusahaan.map((p, index) => (
<TableRow
key={p.PerusahaanId}
className="border-b"
>
<TableCell className="text-center border-r">
{index + 1}
</TableCell>
<TableCell className="border-r">
{p.NamaPerusahaan || "N/A"}
</TableCell>
<TableCell className="text-center border-r">
{p.jenis_kegiatan?.NamaJenisKegiatan ||
"N/A"}
</TableCell>
<TableCell className="text-center border-r">
{p.Alamat || "N/A"}
</TableCell>
<TableCell className="text-center border-r">
{p.Telepon || "N/A"} / {p.Fax || "N/A"}
</TableCell>
<TableCell className="text-center border-r">
{p.Email || "N/A"}
</TableCell>
{/* <TableCell className="text-center border-r">
{p.jenis_dok_i_l?.NamaJenisDokIL ||
"N/A"}
</TableCell> */}
<TableCell className="border-r text-center">
<button
className="text-blue-600 hover:underline"
onClick={() =>
handleJenisIzinClick(p)
}
>
{p.jenis_dok_i_l?.NamaJenisDokIL ??
"Klik di sini"}
</button>
</TableCell>
<TableCell className="text-center border-r">
{p.ILNomor || "-"}
</TableCell>
<TableCell className="text-center border-r">
{p.ILTanggal
? new Date(
p.ILTanggal
).toLocaleDateString("en-GB")
: "-"}
</TableCell>
<TableCell className="text-center border-r">
{p.ILDokumen ? (
<a
href={`/storage/${p.ILDokumen}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center"
>
<FileText className="w-4 h-4 text-green-600 hover:text-green-800" />
</a>
) : (
"-"
)}
</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</div>
</AuthenticatedLayout>
);
}