467 lines
21 KiB
TypeScript
467 lines
21 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import { Head, router } from "@inertiajs/react";
|
|
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
|
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
|
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 {
|
|
ChevronLeft,
|
|
Printer,
|
|
FileDown,
|
|
ArrowUpRight,
|
|
Save,
|
|
} from "lucide-react";
|
|
import axios from "axios";
|
|
|
|
// Import components
|
|
import ALTable from "@/components/AL/ALTable";
|
|
import LampiranModal from "@/components/AL/LampiranModal";
|
|
import SplModal from "@/components/AL/SplModal";
|
|
|
|
interface PelaporanALProps {
|
|
idmcpelaporan: number;
|
|
nama_perusahaan: string;
|
|
tahun: number;
|
|
periode: string;
|
|
editable: boolean;
|
|
ipal_komunal: string;
|
|
lampiran_sk: number;
|
|
verifikasi_sk: string | null;
|
|
ket_sk: string | null;
|
|
catatan: string;
|
|
// Table data props
|
|
data_table: Record<string, any>;
|
|
nilai_komponen: Record<string, any>;
|
|
nilai_syarat_teknis: Record<string, number>;
|
|
nilai_A6: number;
|
|
nilai_A7: number;
|
|
idrefpelaporan: number;
|
|
rowspan_1: number;
|
|
spl: number;
|
|
spl_2: number;
|
|
}
|
|
|
|
const ALForm: React.FC<PelaporanALProps> = (props) => {
|
|
const [ipalKomunal, setIpalKomunal] = useState<string>(props.ipal_komunal);
|
|
const [lampiranSK, setLampiranSK] = useState<number>(props.lampiran_sk);
|
|
const [catatan, setCatatan] = useState<string>(props.catatan);
|
|
const [showSkFields, setShowSkFields] = useState<boolean>(
|
|
props.ipal_komunal === "Iya"
|
|
);
|
|
const [agreement, setAgreement] = useState<boolean>(false);
|
|
|
|
// Modals state
|
|
const [lampiranModalOpen, setLampiranModalOpen] = useState<boolean>(false);
|
|
const [selectedKomponen, setSelectedKomponen] = useState<string>("");
|
|
const [selectedIdRefKomponen, setSelectedIdRefKomponen] =
|
|
useState<number>(0);
|
|
const [splModalOpen, setSplModalOpen] = useState<boolean>(false);
|
|
|
|
// Table related states
|
|
const [dataTable, setDataTable] = useState(props.data_table);
|
|
const [nilaiKomponen, setNilaiKomponen] = useState(props.nilai_komponen);
|
|
|
|
useEffect(() => {
|
|
// Check for lampiran SK on component mount
|
|
if (ipalKomunal === "Iya") {
|
|
checkLampiranSK();
|
|
}
|
|
}, []);
|
|
|
|
const checkLampiranSK = async () => {
|
|
try {
|
|
const response = await axios.get(
|
|
`/pelaporan/al/cek-surat-kerjasama/${props.idmcpelaporan}`
|
|
);
|
|
if (response.data.lampiran && ipalKomunal === "Iya") {
|
|
setLampiranSK(1);
|
|
// If connected to communal IPAL and attachment exists, disable all fields
|
|
disableLampiran();
|
|
changeNilai();
|
|
} else {
|
|
setLampiranSK(0);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error checking SK:", error);
|
|
}
|
|
};
|
|
|
|
const handleIpalKomunalChange = (value: string) => {
|
|
setIpalKomunal(value);
|
|
setShowSkFields(value === "Iya");
|
|
|
|
if (value === "Tidak") {
|
|
// Enable all inputs if not connected to communal IPAL
|
|
enableLampiran();
|
|
} else {
|
|
if (lampiranSK) {
|
|
// If connected to communal IPAL and attachment exists, disable all fields
|
|
disableLampiran();
|
|
changeNilai();
|
|
}
|
|
}
|
|
};
|
|
|
|
const disableLampiran = () => {
|
|
// This function would disable all lampiran links in UI
|
|
// In React we handle this through state/props rather than direct DOM manipulation
|
|
};
|
|
|
|
const enableLampiran = () => {
|
|
// This function would enable all lampiran links in UI
|
|
// In React we handle this through state/props rather than direct DOM manipulation
|
|
};
|
|
|
|
const changeNilai = () => {
|
|
// If SK is verified and not rejected, set all values to 100
|
|
// If rejected, set all to 0
|
|
const newNilaiKomponen = { ...nilaiKomponen };
|
|
|
|
const nilai = props.verifikasi_sk === "Not Approved" ? 0 : 100;
|
|
|
|
// Update all nilai komponen
|
|
Object.keys(newNilaiKomponen).forEach((key) => {
|
|
if (newNilaiKomponen[key]) {
|
|
newNilaiKomponen[key].nilai = nilai;
|
|
}
|
|
});
|
|
|
|
setNilaiKomponen(newNilaiKomponen);
|
|
};
|
|
|
|
const handleUpdateNilai = (kode: string, nilai: number) => {
|
|
const newNilaiKomponen = { ...nilaiKomponen };
|
|
if (newNilaiKomponen[kode]) {
|
|
newNilaiKomponen[kode].nilai = nilai;
|
|
} else {
|
|
newNilaiKomponen[kode] = { nilai };
|
|
}
|
|
setNilaiKomponen(newNilaiKomponen);
|
|
};
|
|
|
|
const handleOpenLampiranModal = (kode: string, idrefkomponen: number) => {
|
|
setSelectedKomponen(kode);
|
|
setSelectedIdRefKomponen(idrefkomponen);
|
|
setLampiranModalOpen(true);
|
|
};
|
|
|
|
const handleOpenSplModal = () => {
|
|
setSplModalOpen(true);
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
// Handle form submission - save and send report
|
|
if (ipalKomunal === "Iya" && lampiranSK === 0) {
|
|
alert("Silahkan Upload Lampiran Surat Kerjasama terlebih dahulu");
|
|
return;
|
|
}
|
|
|
|
// Prepare data
|
|
const formData = {
|
|
ipal_komunal: ipalKomunal,
|
|
catatan: catatan,
|
|
nilai_komponen: nilaiKomponen,
|
|
send: true,
|
|
};
|
|
|
|
// Submit data
|
|
router.post(`/pelaporan/al/simpan/${props.idmcpelaporan}`, formData);
|
|
};
|
|
|
|
const handleSaveDraft = () => {
|
|
// Save form as draft
|
|
if (ipalKomunal === "Iya" && lampiranSK === 0) {
|
|
alert("Silahkan Upload Lampiran Surat Kerjasama terlebih dahulu");
|
|
return;
|
|
}
|
|
|
|
// Prepare data
|
|
const formData = {
|
|
ipal_komunal: ipalKomunal,
|
|
catatan: catatan,
|
|
nilai_komponen: nilaiKomponen,
|
|
send: false,
|
|
};
|
|
|
|
// Submit data
|
|
router.post(`/pelaporan/al/simpan/${props.idmcpelaporan}`, formData);
|
|
};
|
|
|
|
const handlePrint = () => {
|
|
window.print();
|
|
};
|
|
|
|
const handleExport = () => {
|
|
window.location.href = `/pelaporan/al/export-pdf/${props.idmcpelaporan}`;
|
|
};
|
|
|
|
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>
|
|
<h1 className="text-xl font-bold">
|
|
Laporan Pengelolaan Air Limbah
|
|
</h1>
|
|
<p>{props.nama_perusahaan}</p>
|
|
<p>
|
|
Tahun {props.tahun} - Periode{" "}
|
|
{props.periode}
|
|
</p>
|
|
</div>
|
|
<div className="flex gap-2">
|
|
<Button
|
|
variant="secondary"
|
|
size="sm"
|
|
onClick={handlePrint}
|
|
>
|
|
<Printer className="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
variant="secondary"
|
|
size="sm"
|
|
onClick={handleExport}
|
|
>
|
|
<FileDown className="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
variant="secondary"
|
|
size="sm"
|
|
onClick={() =>
|
|
router.get("/pelaporan", {
|
|
save_search: 1,
|
|
})
|
|
}
|
|
>
|
|
<ChevronLeft className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="p-6">
|
|
<form id="al-form">
|
|
{/* IPAL Komunal Section */}
|
|
<div className="flex flex-wrap mb-6 border p-4 rounded-lg bg-gray-50">
|
|
<div
|
|
className={`${
|
|
showSkFields ? "w-1/4" : "w-full"
|
|
}`}
|
|
>
|
|
<Label className="font-medium mb-2 block">
|
|
Tersambung ke IPAL Komunal:
|
|
</Label>
|
|
<div className="space-x-4">
|
|
<label className="inline-flex items-center">
|
|
<input
|
|
type="radio"
|
|
name="ipal_komunal"
|
|
value="Iya"
|
|
checked={ipalKomunal === "Iya"}
|
|
onChange={(e) =>
|
|
handleIpalKomunalChange(
|
|
e.target.value
|
|
)
|
|
}
|
|
disabled={!props.editable}
|
|
className="form-radio text-green-600"
|
|
/>
|
|
<span className="ml-2">Iya</span>
|
|
</label>
|
|
<label className="inline-flex items-center">
|
|
<input
|
|
type="radio"
|
|
name="ipal_komunal"
|
|
value="Tidak"
|
|
checked={
|
|
ipalKomunal === "Tidak"
|
|
}
|
|
onChange={(e) =>
|
|
handleIpalKomunalChange(
|
|
e.target.value
|
|
)
|
|
}
|
|
disabled={!props.editable}
|
|
className="form-radio text-green-600"
|
|
/>
|
|
<span className="ml-2">Tidak</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
{showSkFields && (
|
|
<>
|
|
<div className="w-1/4">
|
|
<Label className="font-medium mb-2 block">
|
|
Lampiran:
|
|
</Label>
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
handleOpenLampiranModal(
|
|
"SK",
|
|
0
|
|
)
|
|
}
|
|
disabled={!props.editable}
|
|
className="text-blue-600 hover:text-blue-800 hover:underline"
|
|
>
|
|
Surat Kerjasama
|
|
</button>
|
|
</div>
|
|
{props.verifikasi_sk && (
|
|
<>
|
|
<div className="w-1/4">
|
|
<Label className="font-medium mb-2 block">
|
|
Verifikasi:
|
|
</Label>
|
|
<span
|
|
className={
|
|
props.verifikasi_sk ===
|
|
"Approved"
|
|
? "text-green-600"
|
|
: "text-red-600"
|
|
}
|
|
>
|
|
{props.verifikasi_sk}
|
|
</span>
|
|
</div>
|
|
<div className="w-1/4">
|
|
<Label className="font-medium mb-2 block">
|
|
Keterangan:
|
|
</Label>
|
|
<p className="text-sm">
|
|
{props.ket_sk}
|
|
</p>
|
|
</div>
|
|
</>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
{/* Main Table */}
|
|
<div className="border rounded-lg overflow-x-auto shadow-sm mb-6">
|
|
<ALTable
|
|
dataTable={dataTable}
|
|
nilaiKomponen={nilaiKomponen}
|
|
nilaiSyaratTeknis={
|
|
props.nilai_syarat_teknis
|
|
}
|
|
nilai_A6={props.nilai_A6}
|
|
nilai_A7={props.nilai_A7}
|
|
idmcpelaporan={props.idmcpelaporan}
|
|
idrefpelaporan={props.idrefpelaporan}
|
|
rowspan_1={props.rowspan_1}
|
|
spl={props.spl}
|
|
spl_2={props.spl_2}
|
|
editable={props.editable}
|
|
onUpdateNilai={handleUpdateNilai}
|
|
onOpenLampiranModal={
|
|
handleOpenLampiranModal
|
|
}
|
|
onOpenSplModal={handleOpenSplModal}
|
|
/>
|
|
</div>
|
|
|
|
{/* Notes Section */}
|
|
<div className="mb-6">
|
|
<Label className="font-medium mb-2 block">
|
|
Catatan:
|
|
</Label>
|
|
<Textarea
|
|
value={catatan}
|
|
onChange={(e) => setCatatan(e.target.value)}
|
|
disabled={!props.editable}
|
|
className="min-h-[100px] bg-white border-gray-300 focus:border-green-500 focus:ring-green-500"
|
|
/>
|
|
</div>
|
|
|
|
{/* Submit buttons */}
|
|
{props.editable && (
|
|
<>
|
|
<div className="flex items-start gap-3 p-4 bg-green-50 rounded-lg border border-green-200 mb-6">
|
|
<Checkbox
|
|
id="agreement"
|
|
checked={agreement}
|
|
onCheckedChange={(checked) =>
|
|
setAgreement(checked as boolean)
|
|
}
|
|
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"
|
|
onClick={handleSaveDraft}
|
|
>
|
|
<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}
|
|
disabled={!agreement}
|
|
>
|
|
<ArrowUpRight className="h-4 w-4" />
|
|
Kirim Laporan
|
|
</Button>
|
|
</div>
|
|
</>
|
|
)}
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Modals */}
|
|
<LampiranModal
|
|
isOpen={lampiranModalOpen}
|
|
onClose={() => {
|
|
setLampiranModalOpen(false);
|
|
if (selectedKomponen === "SK") {
|
|
checkLampiranSK();
|
|
}
|
|
}}
|
|
idMcIpal={0} // For SK this needs to be handled differently
|
|
kodeKomponen={selectedKomponen}
|
|
namaKomponen={
|
|
selectedKomponen === "SK" ? "Surat Kerjasama" : ""
|
|
}
|
|
editable={props.editable}
|
|
/>
|
|
|
|
<SplModal
|
|
isOpen={splModalOpen}
|
|
onClose={() => setSplModalOpen(false)}
|
|
idMcPelaporan={props.idmcpelaporan}
|
|
/>
|
|
</AuthenticatedLayout>
|
|
);
|
|
};
|
|
|
|
export default ALForm;
|