743 lines
46 KiB
TypeScript
743 lines
46 KiB
TypeScript
import React, { useState } from "react";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
import {
|
|
CircleHelp,
|
|
FileDown,
|
|
Printer,
|
|
ChevronLeft,
|
|
Upload,
|
|
PlusCircle,
|
|
CheckCircle2,
|
|
Clock,
|
|
AlertCircle,
|
|
ArrowUpRight,
|
|
Save,
|
|
} from "lucide-react";
|
|
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
|
import { Head } from "@inertiajs/react";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
import UploadDoc from "@/components/upload_doc";
|
|
import { Badge } from "@/components/ui/badge";
|
|
|
|
interface PelaporanALFormProps {
|
|
onSubmit: (data: any) => void;
|
|
}
|
|
|
|
const PelaporanALForm = ({ onSubmit }: PelaporanALFormProps) => {
|
|
const [isConnected, setIsConnected] = useState<boolean | null>(null);
|
|
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
|
|
const [uploadedFile, setUploadedFile] = useState<File | null>(null);
|
|
|
|
// Mock data for uploaded files/attachments
|
|
const [attachments, setAttachments] = useState({
|
|
A6: { name: "hasil-uji-lab-q1-2025.pdf", status: "uploaded" },
|
|
A7: null,
|
|
A8: null,
|
|
A9: null,
|
|
A10: null,
|
|
});
|
|
|
|
const openAttachmentUpload = (itemCode: string) => {
|
|
// Implementation for attachment upload
|
|
console.log(`Opening upload for ${itemCode}`);
|
|
};
|
|
|
|
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"
|
|
onClick={() => {
|
|
// Add PDF download logic here
|
|
}}
|
|
>
|
|
<FileDown className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="p-6">
|
|
<div className="space-y-6">
|
|
{/* Connection Status Card */}
|
|
<Card className="border shadow-sm">
|
|
<CardContent className="p-4">
|
|
<div className="flex flex-wrap lg:flex-nowrap justify-between items-center gap-4">
|
|
<div>
|
|
<h3 className="font-medium text-gray-900 mb-1">
|
|
Status Koneksi IPAL Komunal
|
|
</h3>
|
|
<p className="text-sm text-gray-500">
|
|
Pilih status koneksi instalasi
|
|
pengolahan air limbah
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-6">
|
|
<div className="flex items-center gap-2">
|
|
<input
|
|
type="radio"
|
|
id="tersambung"
|
|
name="connection"
|
|
className="w-4 h-4 text-green-600 focus:ring-green-500"
|
|
onChange={() =>
|
|
setIsConnected(true)
|
|
}
|
|
checked={
|
|
isConnected === true
|
|
}
|
|
/>
|
|
<Label
|
|
htmlFor="tersambung"
|
|
className="font-medium"
|
|
>
|
|
Tersambung
|
|
</Label>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<input
|
|
type="radio"
|
|
id="tidak"
|
|
name="connection"
|
|
className="w-4 h-4 text-green-600 focus:ring-green-500"
|
|
onChange={() =>
|
|
setIsConnected(false)
|
|
}
|
|
checked={
|
|
isConnected === false ||
|
|
isConnected === null
|
|
}
|
|
/>
|
|
<Label
|
|
htmlFor="tidak"
|
|
className="font-medium"
|
|
>
|
|
Tidak Tersambung
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
|
|
{isConnected && (
|
|
<div className="flex items-center gap-2 bg-green-50 p-3 rounded-lg border border-green-200">
|
|
<Upload className="h-4 w-4 text-green-600" />
|
|
<span className="text-sm font-medium text-green-800">
|
|
Lampiran Wajib
|
|
<span className="text-red-600 ml-1">
|
|
*
|
|
</span>
|
|
:
|
|
</span>
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
className={`ml-2 ${
|
|
uploadedFile
|
|
? "bg-green-50 text-green-700 border-green-300"
|
|
: ""
|
|
}`}
|
|
onClick={() =>
|
|
setIsUploadModalOpen(
|
|
true
|
|
)
|
|
}
|
|
>
|
|
{uploadedFile ? (
|
|
<div className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-600" />
|
|
<span className="truncate max-w-36">
|
|
{
|
|
uploadedFile.name
|
|
}
|
|
</span>
|
|
</div>
|
|
) : (
|
|
<div className="flex items-center gap-2">
|
|
<PlusCircle className="h-4 w-4" />
|
|
<span>
|
|
Unggah Surat
|
|
Kerjasama
|
|
</span>
|
|
</div>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<UploadDoc
|
|
isOpen={isUploadModalOpen}
|
|
onClose={() => setIsUploadModalOpen(false)}
|
|
onUpload={(file) => {
|
|
setUploadedFile(file);
|
|
// Handle the file upload logic here
|
|
console.log("File uploaded:", file);
|
|
}}
|
|
/>
|
|
|
|
{/* Main Form Table */}
|
|
<div className="border rounded-lg overflow-hidden shadow-sm">
|
|
<table className="w-full">
|
|
<thead>
|
|
<tr className="bg-gradient-to-r from-green-800 to-green-700 text-white">
|
|
<th className="p-3 text-left w-16">
|
|
No
|
|
</th>
|
|
<th className="p-3 text-left">
|
|
Komponen
|
|
</th>
|
|
<th className="p-3 text-left w-32">
|
|
Hasil
|
|
</th>
|
|
<th className="p-3 text-left w-24">
|
|
Nilai
|
|
</th>
|
|
<th className="p-3 text-left w-32">
|
|
Lampiran
|
|
</th>
|
|
<th className="p-3 text-left w-32">
|
|
Verifikasi
|
|
</th>
|
|
<th className="p-3 text-left w-32">
|
|
Keterangan
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{/* Section 1 */}
|
|
<tr className="bg-green-50">
|
|
<td className="p-3">I</td>
|
|
<td
|
|
className="p-3 font-medium"
|
|
colSpan={1}
|
|
>
|
|
Nilai tingkat ketaatan
|
|
pengelolaan air limbah (IKLl)
|
|
(%)
|
|
</td>
|
|
<td className="p-3"></td>
|
|
<td className="p-3">
|
|
<span className="font-semibold text-green-700">
|
|
100
|
|
</span>
|
|
</td>
|
|
<td className="p-3"></td>
|
|
<td className="p-3"></td>
|
|
<td className="p-3"></td>
|
|
</tr>
|
|
|
|
{/* Technical Requirements Section Header */}
|
|
<tr className="bg-gray-100">
|
|
<td className="p-3"></td>
|
|
<td
|
|
className="p-3 font-semibold text-gray-700"
|
|
colSpan={6}
|
|
>
|
|
1. Persyaratan Teknis
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Technical Requirements A1-A5 */}
|
|
{[
|
|
"Instalasi pengolah air limbah",
|
|
"Flowmeter",
|
|
"Titik pengambilan sampel",
|
|
"Saluran air limbah & air hujan terpisah",
|
|
// "Izin pembuangan air limbah",
|
|
].map((item, index) => (
|
|
<tr
|
|
key={index}
|
|
className="border-t hover:bg-gray-50"
|
|
>
|
|
<td className="p-3 font-medium">
|
|
A{index + 1}
|
|
</td>
|
|
<td className="p-3">
|
|
<div className="flex justify-between items-center w-full">
|
|
<div className="text-gray-800">
|
|
{item}
|
|
</div>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<CircleHelp className="text-green-600 w-5 h-5" />
|
|
</TooltipTrigger>
|
|
<TooltipContent className="bg-white p-3 rounded-lg shadow-lg border max-w-sm">
|
|
<h4 className="font-medium text-green-700 mb-1">
|
|
{item}
|
|
</h4>
|
|
<p className="text-sm text-gray-600">
|
|
Deskripsi
|
|
persyaratan
|
|
teknis untuk{" "}
|
|
{item.toLowerCase()}
|
|
. Pastikan
|
|
data yang
|
|
diisi sesuai
|
|
dengan
|
|
kondisi
|
|
aktual.
|
|
</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
</td>
|
|
<td className="p-3">
|
|
<Select>
|
|
<SelectTrigger className="w-28 border-gray-300">
|
|
<SelectValue placeholder="Ada" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="ada">
|
|
Ada
|
|
</SelectItem>
|
|
<SelectItem value="tidak">
|
|
Tidak Ada
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</td>
|
|
<td className="p-3 font-medium">
|
|
100
|
|
</td>
|
|
<td className="p-3">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="flex items-center gap-1 text-green-700 hover:bg-green-50 hover:text-green-800"
|
|
onClick={() =>
|
|
openAttachmentUpload(
|
|
`A${index + 1}`
|
|
)
|
|
}
|
|
>
|
|
<Upload className="h-4 w-4" />
|
|
<span>Unggah</span>
|
|
</Button>
|
|
</td>
|
|
<td className="p-3">
|
|
<Badge
|
|
variant="outline"
|
|
className="bg-amber-50 text-amber-700 border-amber-200"
|
|
>
|
|
<Clock className="h-3 w-3 mr-1" />
|
|
Menunggu
|
|
</Badge>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
|
|
{/* Implementation Section Header */}
|
|
<tr className="bg-gray-100">
|
|
<td className="p-3"></td>
|
|
<td
|
|
className="p-3 font-semibold text-gray-700"
|
|
colSpan={6}
|
|
>
|
|
2. Perijinan
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Implementation Section A6-A10 */}
|
|
{[
|
|
{
|
|
code: "A5",
|
|
name: "Izin pembuangan air limbah",
|
|
hasAttachment: false,
|
|
},
|
|
].map((item) => (
|
|
<tr
|
|
key={item.code}
|
|
className="border-t hover:bg-gray-50"
|
|
>
|
|
<td className="p-3 font-medium">
|
|
{item.code}
|
|
</td>
|
|
<td className="p-3">
|
|
<div className="flex justify-between items-center w-full">
|
|
<div className="text-gray-800">
|
|
{item.name}
|
|
</div>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<CircleHelp className="text-green-600 w-5 h-5" />
|
|
</TooltipTrigger>
|
|
<TooltipContent className="bg-white p-3 rounded-lg shadow-lg border max-w-sm">
|
|
<h4 className="font-medium text-green-700 mb-1">
|
|
Info:{" "}
|
|
{item.name}
|
|
</h4>
|
|
<p className="text-sm text-gray-600">
|
|
Deskripsi
|
|
untuk
|
|
persyaratan{" "}
|
|
{item.name.toLowerCase()}
|
|
. Pastikan
|
|
data yang
|
|
diisi sesuai
|
|
dengan
|
|
dokumen
|
|
pendukung.
|
|
</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
</td>
|
|
<td className="p-3">
|
|
<Select>
|
|
<SelectTrigger className="w-28 border-gray-300">
|
|
<SelectValue placeholder="Ada" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="ada">
|
|
Ada
|
|
</SelectItem>
|
|
<SelectItem value="tidak">
|
|
Tidak Ada
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</td>
|
|
<td className="p-3 font-medium">
|
|
100
|
|
</td>
|
|
<td className="p-3">
|
|
{attachments[
|
|
item.code as keyof typeof attachments
|
|
] ? (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="flex items-center gap-1 text-green-700 bg-green-50 hover:bg-green-100"
|
|
>
|
|
<CheckCircle2 className="h-4 w-4" />
|
|
<span className="truncate max-w-24">
|
|
{
|
|
attachments[
|
|
item.code as keyof typeof attachments
|
|
]?.name
|
|
}
|
|
</span>
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="flex items-center gap-1 text-green-700 hover:bg-green-50 hover:text-green-800"
|
|
onClick={() =>
|
|
openAttachmentUpload(
|
|
item.code
|
|
)
|
|
}
|
|
>
|
|
<Upload className="h-4 w-4" />
|
|
<span>Data...</span>
|
|
</Button>
|
|
)}
|
|
</td>
|
|
<td className="p-3">
|
|
{item.code === "A6" ? (
|
|
<Badge className="bg-green-100 text-green-700 border-none">
|
|
<CheckCircle2 className="h-3 w-3 mr-1" />
|
|
Terverifikasi
|
|
</Badge>
|
|
) : (
|
|
<Badge
|
|
variant="outline"
|
|
className="bg-amber-50 text-amber-700 border-amber-200"
|
|
>
|
|
<Clock className="h-3 w-3 mr-1" />
|
|
Menunggu
|
|
</Badge>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
|
|
{/* Implementation Section Header */}
|
|
<tr className="bg-gray-100">
|
|
<td className="p-3"></td>
|
|
<td
|
|
className="p-3 font-semibold text-gray-700"
|
|
colSpan={6}
|
|
>
|
|
3. Pelaksanaan
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Implementation Section A6-A10 */}
|
|
{[
|
|
{
|
|
code: "A6",
|
|
name: "Pengujian air limbah",
|
|
hasAttachment: true,
|
|
},
|
|
{
|
|
code: "A7",
|
|
name: "Pemenuhan baku mutu air limbah",
|
|
hasAttachment: true,
|
|
},
|
|
{
|
|
code: "A8",
|
|
name: "Pelaksanaan dan pemutusan wewenang",
|
|
hasAttachment: true,
|
|
},
|
|
{
|
|
code: "A9",
|
|
name: "Pembuatan neraca air",
|
|
hasAttachment: true,
|
|
},
|
|
{
|
|
code: "A10",
|
|
name: "Sertifikasi kompetensi",
|
|
hasAttachment: true,
|
|
},
|
|
].map((item) => (
|
|
<tr
|
|
key={item.code}
|
|
className="border-t hover:bg-gray-50"
|
|
>
|
|
<td className="p-3 font-medium">
|
|
{item.code}
|
|
</td>
|
|
<td className="p-3">
|
|
<div className="flex justify-between items-center w-full">
|
|
<div className="text-gray-800">
|
|
{item.name}
|
|
</div>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<CircleHelp className="text-green-600 w-5 h-5" />
|
|
</TooltipTrigger>
|
|
<TooltipContent className="bg-white p-3 rounded-lg shadow-lg border max-w-sm">
|
|
<h4 className="font-medium text-green-700 mb-1">
|
|
Info:{" "}
|
|
{item.name}
|
|
</h4>
|
|
<p className="text-sm text-gray-600">
|
|
Deskripsi
|
|
untuk
|
|
persyaratan{" "}
|
|
{item.name.toLowerCase()}
|
|
. Pastikan
|
|
data yang
|
|
diisi sesuai
|
|
dengan
|
|
dokumen
|
|
pendukung.
|
|
</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
</td>
|
|
<td className="p-3">
|
|
<Select>
|
|
<SelectTrigger className="w-28 border-gray-300">
|
|
<SelectValue placeholder="Ada" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="ada">
|
|
Ada
|
|
</SelectItem>
|
|
<SelectItem value="tidak">
|
|
Tidak Ada
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</td>
|
|
<td className="p-3 font-medium">
|
|
100
|
|
</td>
|
|
<td className="p-3">
|
|
{attachments[
|
|
item.code as keyof typeof attachments
|
|
] ? (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="flex items-center gap-1 text-green-700 bg-green-50 hover:bg-green-100"
|
|
>
|
|
<CheckCircle2 className="h-4 w-4" />
|
|
<span className="truncate max-w-24">
|
|
{
|
|
attachments[
|
|
item.code as keyof typeof attachments
|
|
]?.name
|
|
}
|
|
</span>
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="flex items-center gap-1 text-green-700 hover:bg-green-50 hover:text-green-800"
|
|
onClick={() =>
|
|
openAttachmentUpload(
|
|
item.code
|
|
)
|
|
}
|
|
>
|
|
<Upload className="h-4 w-4" />
|
|
<span>Data...</span>
|
|
</Button>
|
|
)}
|
|
</td>
|
|
<td className="p-3">
|
|
{item.code === "A6" ? (
|
|
<Badge className="bg-green-100 text-green-700 border-none">
|
|
<CheckCircle2 className="h-3 w-3 mr-1" />
|
|
Terverifikasi
|
|
</Badge>
|
|
) : (
|
|
<Badge
|
|
variant="outline"
|
|
className="bg-amber-50 text-amber-700 border-amber-200"
|
|
>
|
|
<Clock className="h-3 w-3 mr-1" />
|
|
Menunggu
|
|
</Badge>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{/* Notes Section */}
|
|
<Card className="border shadow-sm">
|
|
<CardContent className="p-5">
|
|
<h2 className="text-lg font-semibold mb-3 text-gray-800 flex items-center gap-2">
|
|
<span>Catatan</span>
|
|
{/* <span className="text-sm font-normal text-gray-500">
|
|
(Opsional)
|
|
</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">
|
|
<ArrowUpRight className="h-4 w-4" />
|
|
Kirim Laporan
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</AuthenticatedLayout>
|
|
);
|
|
};
|
|
|
|
export default PelaporanALForm;
|