865 lines
37 KiB
TypeScript
865 lines
37 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
||
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
||
import { Head, router } from "@inertiajs/react";
|
||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||
import { Badge } from "@/components/ui/badge";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Checkbox } from "@/components/ui/checkbox";
|
||
import { Label } from "@/components/ui/label";
|
||
import { Textarea } from "@/components/ui/textarea";
|
||
import {
|
||
Select,
|
||
SelectTrigger,
|
||
SelectContent,
|
||
SelectItem,
|
||
SelectValue,
|
||
} from "@/components/ui/select";
|
||
import {
|
||
Tooltip,
|
||
TooltipTrigger,
|
||
TooltipContent,
|
||
} from "@/components/ui/tooltip";
|
||
import {
|
||
ChevronLeft,
|
||
Printer,
|
||
FileDown,
|
||
CircleHelp,
|
||
Upload,
|
||
ArrowUpRight,
|
||
Save,
|
||
} from "lucide-react";
|
||
// import { Inertia } from "@inertiajs/inertia";
|
||
|
||
/* ----------------------------------
|
||
Contoh komponen modal upload
|
||
-------------------------------------*/
|
||
function ModalUploadUmum({
|
||
isOpen,
|
||
onClose,
|
||
onUpload,
|
||
rowCode,
|
||
title,
|
||
}: {
|
||
isOpen: boolean;
|
||
onClose: () => void;
|
||
onUpload: () => void;
|
||
rowCode: string;
|
||
title: string;
|
||
}) {
|
||
if (!isOpen) return null;
|
||
return (
|
||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
|
||
<div className="bg-white rounded-lg shadow-lg w-full max-w-xl">
|
||
<div className="p-4 border-b flex justify-between items-center">
|
||
<h2 className="font-semibold text-gray-800 text-lg">
|
||
Laporan Pengelolaan Air Limbah - {rowCode}. {title}
|
||
</h2>
|
||
<button
|
||
onClick={onClose}
|
||
className="text-gray-500 hover:text-gray-700"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
<div className="p-4">
|
||
<p className="text-sm text-gray-700 mb-3">
|
||
Silahkan unggah dokumen Anda dengan drag & drop atau
|
||
klik pada kotak ini. Ukuran file tidak boleh melebihi 20
|
||
MB.
|
||
</p>
|
||
<div className="border-2 border-dashed border-gray-300 rounded p-6 flex flex-col items-center justify-center text-gray-500">
|
||
<Upload className="w-10 h-10 mb-2" />
|
||
<span className="text-sm">
|
||
Drop file atau klik di sini
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div className="p-4 border-t flex justify-end">
|
||
<Button
|
||
onClick={() => {
|
||
onUpload();
|
||
onClose();
|
||
}}
|
||
>
|
||
Simpan
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
/* ----------------------------------
|
||
Contoh komponen modal khusus A10
|
||
-------------------------------------*/
|
||
function ModalUploadA10({
|
||
isOpen,
|
||
onClose,
|
||
onUpload,
|
||
rowCode,
|
||
title,
|
||
}: {
|
||
isOpen: boolean;
|
||
onClose: () => void;
|
||
onUpload: () => void;
|
||
rowCode: string;
|
||
title: string;
|
||
}) {
|
||
if (!isOpen) return null;
|
||
return (
|
||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
|
||
<div className="bg-white rounded-lg shadow-lg w-full max-w-2xl">
|
||
<div className="p-4 border-b flex justify-between items-center">
|
||
<h2 className="font-semibold text-gray-800 text-lg">
|
||
Laporan Pengelolaan Air Limbah - {rowCode}. {title}
|
||
</h2>
|
||
<button
|
||
onClick={onClose}
|
||
className="text-gray-500 hover:text-gray-700"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
<div className="p-4 space-y-4">
|
||
<div className="border-2 border-dashed border-gray-300 rounded p-6 flex flex-col items-center justify-center text-gray-500">
|
||
<Upload className="w-10 h-10 mb-2" />
|
||
<span className="text-sm">
|
||
Drop file atau klik di sini
|
||
</span>
|
||
</div>
|
||
|
||
{/* Contoh form data sertifikat */}
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<Label htmlFor="noSertifikat">
|
||
Nomor Sertifikat BNSP
|
||
</Label>
|
||
<input
|
||
id="noSertifikat"
|
||
type="text"
|
||
className="mt-1 w-full border-gray-300 rounded"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label htmlFor="namaPemilik">
|
||
Nama Pemilik Sertifikat
|
||
</Label>
|
||
<input
|
||
id="namaPemilik"
|
||
type="text"
|
||
className="mt-1 w-full border-gray-300 rounded"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label htmlFor="tanggalTerbit">
|
||
Tanggal Terbit
|
||
</Label>
|
||
<input
|
||
id="tanggalTerbit"
|
||
type="date"
|
||
className="mt-1 w-full border-gray-300 rounded"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label htmlFor="masaBerlaku">
|
||
Masa Berlaku (tahun)
|
||
</Label>
|
||
<input
|
||
id="masaBerlaku"
|
||
type="number"
|
||
className="mt-1 w-full border-gray-300 rounded"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label htmlFor="namaJabatan">Nama Jabatan</Label>
|
||
<input
|
||
id="namaJabatan"
|
||
type="text"
|
||
className="mt-1 w-full border-gray-300 rounded"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Tabel list sertifikat */}
|
||
<div className="mt-4">
|
||
<table className="w-full text-sm border border-gray-300">
|
||
<thead className="bg-gray-100">
|
||
<tr>
|
||
<th className="p-2 border border-gray-300">
|
||
Nomor Sertifikat
|
||
</th>
|
||
<th className="p-2 border border-gray-300">
|
||
Nama Pemilik
|
||
</th>
|
||
<th className="p-2 border border-gray-300">
|
||
Tanggal Terbit
|
||
</th>
|
||
<th className="p-2 border border-gray-300">
|
||
Masa Berlaku
|
||
</th>
|
||
<th className="p-2 border border-gray-300">
|
||
Nama Jabatan
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{/* Contoh: kosong */}
|
||
<tr>
|
||
<td
|
||
colSpan={5}
|
||
className="p-2 text-center text-gray-500"
|
||
>
|
||
Tidak ada data di tabel
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="p-4 border-t flex justify-end">
|
||
<Button
|
||
onClick={() => {
|
||
onUpload();
|
||
onClose();
|
||
}}
|
||
>
|
||
Simpan
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
/* ----------------------------------
|
||
Struktur data baris table
|
||
-------------------------------------*/
|
||
interface TableRow {
|
||
code: string; // A1, A2, ...
|
||
name: string; // Nama komponen
|
||
tooltip: string; // Keterangan tooltip
|
||
hasLampiran: boolean; // Apakah baris ini punya tombol upload?
|
||
lampiranLabel?: string; // Text di kolom lampiran ("Data...", "Lampiran...")
|
||
dropdownValue: "Ada" | "Tidak Ada"; // Default "Tidak Ada"
|
||
value: number; // 0 atau 100
|
||
isDisabled: boolean; // Dropdown disable?
|
||
verification?: string; // Kosong jika belum diverifikasi
|
||
}
|
||
|
||
/* ----------------------------------
|
||
Halaman utama
|
||
-------------------------------------*/
|
||
export default function PelaporanALForm() {
|
||
// Modal states
|
||
const [modalRowCode, setModalRowCode] = useState<string | null>(null); // untuk row umum
|
||
const [modalA10Open, setModalA10Open] = useState<boolean>(false); // khusus A10
|
||
|
||
// Data baris A1 - A5 (tidak ada lampiran)
|
||
const [rowsNoLampiran, setRowsNoLampiran] = useState<TableRow[]>([
|
||
{
|
||
code: "A1",
|
||
name: "Instalasi pengolah air limbah",
|
||
tooltip:
|
||
"Foto kondisi terkini instalasi pengolahan air limbah pada masa periode pelaporan (ditandai dengan cap waktu)",
|
||
hasLampiran: false,
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: false,
|
||
},
|
||
{
|
||
code: "A2",
|
||
name: "Flowmeter",
|
||
tooltip:
|
||
"Foto kondisi terkini flowmeter pada masa periode pelaporan (ditandai dengan cap waktu)",
|
||
hasLampiran: false,
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: false,
|
||
},
|
||
{
|
||
code: "A3",
|
||
name: "Titik pengambilan sampel",
|
||
tooltip:
|
||
"Foto kondisi terkini titik pengambilan sampel air limbah yang telah dilengkapi dengan penandaan dan koordinat pada masa periode pelaporan (ditandai dengan cap waktu)",
|
||
hasLampiran: false,
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: false,
|
||
},
|
||
{
|
||
code: "A4",
|
||
name: "Saluran air limbah & air hujan terpisah",
|
||
tooltip:
|
||
"Foto kondisi terkini saluran air limbah & air hujan yang terpisah pada masa periode pelaporan (ditandai dengan cap waktu)",
|
||
hasLampiran: false,
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: false,
|
||
},
|
||
{
|
||
code: "A5",
|
||
name: "Izin pembuangan air limbah",
|
||
tooltip:
|
||
"Izin pembuangan air limbah yang masih berlaku atau Persetujuan Teknis Pemenuhan Baku Mutu Air Limbah yang telah dimiliki",
|
||
hasLampiran: false,
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: false,
|
||
},
|
||
]);
|
||
|
||
// Data baris A6 - A10 (beberapa ada lampiran)
|
||
const [rowsWithLampiran, setRowsWithLampiran] = useState<TableRow[]>([
|
||
{
|
||
code: "A6",
|
||
name: "Pengujian air limbah",
|
||
tooltip:
|
||
"Data pengujian, parameter, dll. (nanti dijelaskan detail)",
|
||
hasLampiran: true,
|
||
lampiranLabel: "Data...",
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: true, // Baru aktif setelah upload
|
||
},
|
||
{
|
||
code: "A7",
|
||
name: "Pemenuhan baku mutu air limbah",
|
||
tooltip: "Nilai otomatis dari sistem. Tidak ada lampiran.",
|
||
hasLampiran: false,
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: false,
|
||
},
|
||
{
|
||
code: "A8",
|
||
name: "Pelaksanaan dan pemutusan wewenang",
|
||
tooltip:
|
||
"Hasil pencatatan swapantau harian parameter debit dan pH.",
|
||
hasLampiran: true,
|
||
lampiranLabel: "Lampiran...",
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: true,
|
||
},
|
||
{
|
||
code: "A9",
|
||
name: "Pembuatan neraca air",
|
||
tooltip:
|
||
"Neraca air bersih senyatanya selama periode pelaporan (3 bulan).",
|
||
hasLampiran: true,
|
||
lampiranLabel: "Lampiran...",
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: true,
|
||
},
|
||
{
|
||
code: "A10",
|
||
name: "Sertifikasi kompetensi",
|
||
tooltip:
|
||
"Sertifikat kompetensi personil (BNSP) yang masih berlaku, dsb.",
|
||
hasLampiran: true,
|
||
lampiranLabel: "Lampiran...",
|
||
dropdownValue: "Tidak Ada",
|
||
value: 0,
|
||
isDisabled: true,
|
||
},
|
||
]);
|
||
|
||
// Total I (IKLl) dari A1–A10
|
||
const [totalIKLl, setTotalIKLl] = useState(0);
|
||
// Total II (SPBMAL) => mengikuti A6
|
||
const [totalSPBMAL, setTotalSPBMAL] = useState(0);
|
||
|
||
// Hitung total I setiap ada perubahan data
|
||
useEffect(() => {
|
||
const sumNoLampiran = rowsNoLampiran.reduce(
|
||
(acc, row) => acc + row.value,
|
||
0
|
||
);
|
||
const sumWithLampiran = rowsWithLampiran.reduce(
|
||
(acc, row) => acc + row.value,
|
||
0
|
||
);
|
||
const total = sumNoLampiran + sumWithLampiran; // total 10 komponen
|
||
const average = total / 10; // misalnya kita mau rata-ratakan
|
||
setTotalIKLl(average);
|
||
}, [rowsNoLampiran, rowsWithLampiran]);
|
||
|
||
// Hitung total II berdasarkan A6 (Jika "Ada" => 100, jika "Tidak Ada" => 0)
|
||
useEffect(() => {
|
||
const rowA6 = rowsWithLampiran.find((r) => r.code === "A6");
|
||
if (rowA6) {
|
||
setTotalSPBMAL(rowA6.dropdownValue === "Ada" ? 100 : 0);
|
||
}
|
||
}, [rowsWithLampiran]);
|
||
|
||
// Ubah dropdown value
|
||
const handleDropdownChange = (
|
||
code: string,
|
||
newVal: "Ada" | "Tidak Ada",
|
||
isNoLampiran: boolean
|
||
) => {
|
||
if (isNoLampiran) {
|
||
const updated = rowsNoLampiran.map((row) => {
|
||
if (row.code === code) {
|
||
return {
|
||
...row,
|
||
dropdownValue: newVal,
|
||
value: newVal === "Ada" ? 100 : 0,
|
||
};
|
||
}
|
||
return row;
|
||
});
|
||
setRowsNoLampiran(updated);
|
||
} else {
|
||
const updated = rowsWithLampiran.map((row) => {
|
||
if (row.code === code) {
|
||
return {
|
||
...row,
|
||
dropdownValue: newVal,
|
||
value: newVal === "Ada" ? 100 : 0,
|
||
};
|
||
}
|
||
return row;
|
||
});
|
||
setRowsWithLampiran(updated);
|
||
}
|
||
};
|
||
|
||
// Ketika user klik tombol upload di kolom lampiran
|
||
const handleOpenUploadModal = (row: TableRow) => {
|
||
// Jika baris A6 diklik, arahkan ke route "admin.pelaporan.indexIpal"
|
||
// atau path "/admin/pelaporan/al/ipal"
|
||
if (row.code === "A6") {
|
||
// Contoh menggunakan nama route inertia
|
||
// Inertia.visit(route("admin.pelaporan.indexIpal"));
|
||
|
||
// Atau langsung path
|
||
router.visit("/admin/pelaporan/al/ipal");
|
||
return;
|
||
}
|
||
|
||
// Jika A10, buka modal khusus
|
||
if (row.code === "A10") {
|
||
setModalA10Open(true);
|
||
} else {
|
||
// A8, A9 pakai modal umum
|
||
setModalRowCode(row.code);
|
||
}
|
||
};
|
||
|
||
// Setelah upload berhasil, dropdown diaktifkan
|
||
const handleUploadSuccess = (code: string) => {
|
||
setRowsWithLampiran((prev) =>
|
||
prev.map((row) => {
|
||
if (row.code === code) {
|
||
return {
|
||
...row,
|
||
isDisabled: false, // dropdown baru bisa dipilih
|
||
// lampiranLabel tidak berubah -> tetap "Data..." atau "Lampiran..."
|
||
};
|
||
}
|
||
return row;
|
||
})
|
||
);
|
||
};
|
||
|
||
// Render baris table tanpa lampiran (A1-A5, A7)
|
||
const renderRowNoLampiran = (row: TableRow) => {
|
||
return (
|
||
<tr key={row.code} className="hover:bg-gray-50">
|
||
<td className="border border-gray-300 p-2 font-medium">
|
||
{row.code}
|
||
</td>
|
||
<td className="border border-gray-300 p-2">
|
||
<div className="flex justify-between items-center w-full">
|
||
<div className="text-gray-800">{row.name}</div>
|
||
<Tooltip>
|
||
<TooltipTrigger>
|
||
<CircleHelp className="text-green-600 w-4 h-4 cursor-pointer" />
|
||
</TooltipTrigger>
|
||
<TooltipContent className="bg-white p-3 rounded-lg shadow-lg border max-w-sm whitespace-pre-line">
|
||
<h4 className="font-medium text-green-700 mb-1">
|
||
{row.name}
|
||
</h4>
|
||
<p className="text-sm text-gray-600">
|
||
{row.tooltip}
|
||
</p>
|
||
</TooltipContent>
|
||
</Tooltip>
|
||
</div>
|
||
</td>
|
||
{/* Hasil */}
|
||
<td className="border border-gray-300 p-2">
|
||
<Select
|
||
disabled={row.isDisabled}
|
||
onValueChange={(val: "Ada" | "Tidak Ada") =>
|
||
handleDropdownChange(row.code, val, true)
|
||
}
|
||
value={row.dropdownValue}
|
||
>
|
||
<SelectTrigger className="w-full border-gray-300 text-sm">
|
||
<SelectValue />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="Ada">Ada</SelectItem>
|
||
<SelectItem value="Tidak Ada">Tidak Ada</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</td>
|
||
<td className="border border-gray-300 p-2 text-center">
|
||
{row.value}
|
||
</td>
|
||
{/* Tidak ada kolom lampiran di sini */}
|
||
<td className="border border-gray-300 p-2">
|
||
{row.verification || ""}
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
);
|
||
};
|
||
|
||
// Render baris table dengan lampiran (A6, A8, A9, A10)
|
||
const renderRowWithLampiran = (row: TableRow) => {
|
||
return (
|
||
<tr key={row.code} className="hover:bg-gray-50">
|
||
<td className="border border-gray-300 p-2 font-medium">
|
||
{row.code}
|
||
</td>
|
||
<td className="border border-gray-300 p-2">
|
||
<div className="flex justify-between items-center w-full">
|
||
<div className="text-gray-800">{row.name}</div>
|
||
<Tooltip>
|
||
<TooltipTrigger>
|
||
<CircleHelp className="text-green-600 w-4 h-4 cursor-pointer" />
|
||
</TooltipTrigger>
|
||
<TooltipContent className="bg-white p-3 rounded-lg shadow-lg border max-w-sm whitespace-pre-line">
|
||
<h4 className="font-medium text-green-700 mb-1">
|
||
{row.name}
|
||
</h4>
|
||
<p className="text-sm text-gray-600">
|
||
{row.tooltip}
|
||
</p>
|
||
</TooltipContent>
|
||
</Tooltip>
|
||
</div>
|
||
</td>
|
||
{/* Hasil */}
|
||
<td className="border border-gray-300 p-2">
|
||
<Select
|
||
disabled={row.isDisabled}
|
||
onValueChange={(val: "Ada" | "Tidak Ada") =>
|
||
handleDropdownChange(row.code, val, false)
|
||
}
|
||
value={row.dropdownValue}
|
||
>
|
||
<SelectTrigger className="w-full border-gray-300 text-sm">
|
||
<SelectValue />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="Ada">Ada</SelectItem>
|
||
<SelectItem value="Tidak Ada">Tidak Ada</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</td>
|
||
<td className="border border-gray-300 p-2 text-center">
|
||
{row.value}
|
||
</td>
|
||
{/* Lampiran */}
|
||
<td className="border border-gray-300 p-2">
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
className="flex items-center gap-1 text-green-700 hover:bg-green-50 hover:text-green-800"
|
||
onClick={() => handleOpenUploadModal(row)}
|
||
>
|
||
<Upload className="h-4 w-4" />
|
||
{/* Teks tidak berubah setelah upload */}
|
||
<span>{row.lampiranLabel || "Data..."}</span>
|
||
</Button>
|
||
</td>
|
||
<td className="border border-gray-300 p-2">
|
||
{row.verification || ""}
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
);
|
||
};
|
||
|
||
// Render
|
||
return (
|
||
<AuthenticatedLayout header="Pelaporan Air Limbah">
|
||
<Head title="Pelaporan Air Limbah" />
|
||
<div className="p-4 space-y-6">
|
||
<Card className="shadow-lg border-none">
|
||
<CardHeader className="bg-gradient-to-r from-green-800 to-green-700 text-white rounded-t-lg">
|
||
<div className="flex justify-between items-center">
|
||
<div>
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<Badge className="bg-green-600">
|
||
Nama Perusahaan
|
||
</Badge>
|
||
</div>
|
||
<CardTitle className="text-xl font-bold">
|
||
Laporan Pengelolaan Air Limbah
|
||
</CardTitle>
|
||
<p className="text-sm opacity-90 mt-1">
|
||
Tahun 2025 - Periode Triwulan 1 (Januari -
|
||
Maret)
|
||
</p>
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<Button
|
||
variant="secondary"
|
||
size="sm"
|
||
className="gap-1"
|
||
onClick={() => window.history.back()}
|
||
>
|
||
<ChevronLeft className="h-4 w-4" />
|
||
Kembali
|
||
</Button>
|
||
<Button
|
||
variant="secondary"
|
||
size="sm"
|
||
onClick={() => {
|
||
const style =
|
||
document.createElement("style");
|
||
style.innerHTML = `
|
||
@media print {
|
||
@page {
|
||
size: auto;
|
||
margin: 20mm;
|
||
}
|
||
body {
|
||
zoom: 0.5;
|
||
-webkit-print-color-adjust: exact !important;
|
||
print-color-adjust: exact !important;
|
||
}
|
||
}
|
||
`;
|
||
document.head.appendChild(style);
|
||
window.print();
|
||
document.head.removeChild(style);
|
||
}}
|
||
>
|
||
<Printer className="h-4 w-4" />
|
||
</Button>
|
||
<Button variant="secondary" size="sm">
|
||
<FileDown className="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</CardHeader>
|
||
<CardContent className="p-6">
|
||
{/* Main Table */}
|
||
<div className="border rounded-lg overflow-hidden shadow-sm">
|
||
<table className="w-full border-collapse border border-gray-300 text-sm">
|
||
<thead className="bg-gray-100">
|
||
<tr>
|
||
<th className="border border-gray-300 p-2 w-16">
|
||
No
|
||
</th>
|
||
<th className="border border-gray-300 p-2">
|
||
Komponen
|
||
</th>
|
||
<th className="border border-gray-300 p-2 w-32">
|
||
Hasil
|
||
</th>
|
||
<th className="border border-gray-300 p-2 w-24">
|
||
Nilai
|
||
</th>
|
||
{/* A1-A5 tidak punya lampiran, tapi kolom ini tetap ada
|
||
untuk A6, A8, A9, A10. Nanti baris A1-A5 isinya kosong. */}
|
||
<th className="border border-gray-300 p-2 w-32">
|
||
Lampiran
|
||
</th>
|
||
<th className="border border-gray-300 p-2 w-32">
|
||
Verifikasi
|
||
</th>
|
||
<th className="border border-gray-300 p-2 w-32">
|
||
Keterangan
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{/* Baris I (Nilai IKLl) */}
|
||
<tr className="bg-green-50">
|
||
<td className="border border-gray-300 p-2">
|
||
I
|
||
</td>
|
||
<td className="border border-gray-300 p-2 font-medium">
|
||
Nilai tingkat ketaatan pengelolaan
|
||
air limbah (IKLl) (%)
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td className="border border-gray-300 p-2">
|
||
<span className="font-semibold text-green-700">
|
||
{totalIKLl}
|
||
</span>
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
|
||
{/* Section 1: Persyaratan Teknis => A1-A4 */}
|
||
<tr className="bg-gray-50">
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td
|
||
className="border border-gray-300 p-2 font-semibold text-gray-700"
|
||
colSpan={5}
|
||
>
|
||
1. Persyaratan Teknis
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
{rowsNoLampiran
|
||
.slice(0, 4)
|
||
.map((row) => renderRowNoLampiran(row))}
|
||
|
||
{/* Section 2: Perijinan => A5 */}
|
||
<tr className="bg-gray-50">
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td
|
||
className="border border-gray-300 p-2 font-semibold text-gray-700"
|
||
colSpan={5}
|
||
>
|
||
2. Perijinan
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
{renderRowNoLampiran(rowsNoLampiran[4])}
|
||
|
||
{/* Section 3: Pelaksanaan => A6 - A10 */}
|
||
<tr className="bg-gray-50">
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td
|
||
className="border border-gray-300 p-2 font-semibold text-gray-700"
|
||
colSpan={5}
|
||
>
|
||
3. Pelaksanaan
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
{rowsWithLampiran.map((row) => {
|
||
// A7 tidak punya lampiran => treat like no-lampiran row
|
||
if (row.code === "A7") {
|
||
return renderRowNoLampiran(row);
|
||
}
|
||
// A6, A8, A9, A10 => with lampiran
|
||
return renderRowWithLampiran(row);
|
||
})}
|
||
|
||
{/* Baris II (Nilai SPBMAL) */}
|
||
<tr className="bg-green-50">
|
||
<td className="border border-gray-300 p-2">
|
||
II
|
||
</td>
|
||
<td className="border border-gray-300 p-2 font-medium">
|
||
Nilai tingkat pemenuhan baku mutu
|
||
air limbah * (SPBMAL) (%)
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td className="border border-gray-300 p-2">
|
||
<span className="font-semibold text-green-700">
|
||
{totalSPBMAL}
|
||
</span>
|
||
</td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
<td className="border border-gray-300 p-2"></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
{/* Notes Section */}
|
||
<Card className="border shadow-sm mt-6">
|
||
<CardContent className="p-5">
|
||
<h2 className="text-lg font-semibold mb-3 text-gray-800 flex items-center gap-2">
|
||
<span>Catatan</span>
|
||
</h2>
|
||
<Textarea
|
||
placeholder="Tambahkan catatan atau komentar tambahan di sini..."
|
||
className="min-h-[100px] bg-white border-gray-300 focus:border-green-500 focus:ring-green-500"
|
||
/>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Agreement & Submit Section */}
|
||
<div className="mt-8 space-y-6">
|
||
<div className="flex items-start gap-3 p-4 bg-green-50 rounded-lg border border-green-200">
|
||
<Checkbox
|
||
id="agreement"
|
||
className="mt-1 text-green-600 focus:ring-green-500"
|
||
/>
|
||
<div>
|
||
<Label
|
||
htmlFor="agreement"
|
||
className="text-sm font-medium text-gray-800"
|
||
>
|
||
Pernyataan Kebenaran Data
|
||
</Label>
|
||
<p className="text-sm leading-relaxed text-gray-700 mt-1">
|
||
Kami menyatakan bahwa laporan ini telah
|
||
disusun berdasarkan ketentuan peraturan
|
||
yang berlaku dan kami bersedia
|
||
bertanggung jawab atas kebenaran
|
||
data-data yang kami kirimkan sesuai
|
||
dengan fakta dilapangan.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div className="flex justify-end gap-4">
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-gray-100 gap-2"
|
||
>
|
||
<Save className="h-4 w-4" />
|
||
Simpan Draft
|
||
</Button>
|
||
<Button
|
||
className="bg-green-800 hover:bg-green-700 transition-colors px-8 gap-2"
|
||
onClick={handleSubmit}
|
||
>
|
||
<ArrowUpRight className="h-4 w-4" />
|
||
Kirim Laporan
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
|
||
{/* Modal Upload Umum (A6, A8, A9) */}
|
||
<ModalUploadUmum
|
||
isOpen={!!modalRowCode && modalRowCode !== "A10"}
|
||
onClose={() => setModalRowCode(null)}
|
||
onUpload={() => {
|
||
if (modalRowCode) {
|
||
handleUploadSuccess(modalRowCode);
|
||
}
|
||
}}
|
||
rowCode={modalRowCode || ""}
|
||
title={
|
||
rowsWithLampiran.find((r) => r.code === modalRowCode)
|
||
?.name || ""
|
||
}
|
||
/>
|
||
|
||
{/* Modal Upload A10 */}
|
||
<ModalUploadA10
|
||
isOpen={modalA10Open}
|
||
onClose={() => setModalA10Open(false)}
|
||
onUpload={() => {
|
||
// Setelah upload, dropdown diaktifkan
|
||
handleUploadSuccess("A10");
|
||
}}
|
||
rowCode="A10"
|
||
title="Sertifikasi kompetensi"
|
||
/>
|
||
</AuthenticatedLayout>
|
||
);
|
||
}
|