244 lines
8.9 KiB
TypeScript
244 lines
8.9 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import { useState, useEffect } from "react";
|
||
|
|
import { v4 as uuidv4 } from "uuid";
|
||
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/components/ui/tabs";
|
||
|
|
import FormMultiSelect from "@/shared/components/forms/form-multi-select";
|
||
|
|
|
||
|
|
const satupetaCategory = [
|
||
|
|
"Batas Wilayah",
|
||
|
|
"Kependudukan",
|
||
|
|
"Lingkungan Hidup",
|
||
|
|
"Pemerintah Desa",
|
||
|
|
"Pendidikan",
|
||
|
|
"Sosial",
|
||
|
|
"Pendidikan SD",
|
||
|
|
"Pariwisata Kebudayaan",
|
||
|
|
"Kesehatan",
|
||
|
|
"Ekonomi",
|
||
|
|
"Kemiskinan",
|
||
|
|
"Infrastruktur"
|
||
|
|
]
|
||
|
|
const satupetaCategoryId = [
|
||
|
|
"019a0997-5b42-7c34-9ab8-35b4765ecb39",
|
||
|
|
"0196c80b-e680-7dca-9b90-b5ebe65de70d",
|
||
|
|
"0196c80c-855f-77f9-abd0-0c8a30b8c2f5",
|
||
|
|
"0196c80c-f805-76a8-82c7-af50b794871b",
|
||
|
|
"0196c80d-228d-7e1e-9116-78ba912b812c",
|
||
|
|
"0196c80d-3f05-7750-ab2a-f58655fef6ea",
|
||
|
|
"019936a6-4a5b-719f-8d88-d2df0af5aa20",
|
||
|
|
"0196c80c-c4fc-7ea6-afc0-3672a1b44b5b",
|
||
|
|
"0196c80c-61d8-7616-9abc-550a89283a57",
|
||
|
|
"0196c809-a0b0-79fb-b597-422d716fdce8",
|
||
|
|
"0196c80b-bb09-7424-9cd5-e3ec4946c7af",
|
||
|
|
"0196c80b-8710-7577-bc28-3ce66a02f56f"
|
||
|
|
]
|
||
|
|
|
||
|
|
export const getInitialMetadata = (initialValues: any = {}) => {
|
||
|
|
const today = new Date().toISOString().split('T')[0];
|
||
|
|
|
||
|
|
|
||
|
|
function getIndexCategoryId(value: string) {
|
||
|
|
return satupetaCategory.indexOf(value);
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
// Mapping dari API Suggestion (jika ada)
|
||
|
|
title: initialValues.judul || "",
|
||
|
|
abstract: initialValues.abstrak || "",
|
||
|
|
keywords: initialValues.keyword ? (Array.isArray(initialValues.keyword) ? initialValues.keyword.join(', ') : initialValues.keyword) : "",
|
||
|
|
topicCategory: initialValues.kategori || "",
|
||
|
|
|
||
|
|
// Default Values Hardcoded Anda
|
||
|
|
mapsetCategory: satupetaCategoryId[getIndexCategoryId(initialValues.kategori_mapset)] || "",
|
||
|
|
dateCreated: today,
|
||
|
|
status: "completed",
|
||
|
|
language: "eng",
|
||
|
|
|
||
|
|
organization: "PUPR",
|
||
|
|
contactName: "Dimas",
|
||
|
|
contactEmail: "pu@gmail.com",
|
||
|
|
contactPhone: "08222222222",
|
||
|
|
|
||
|
|
// 🌐 Distribusi
|
||
|
|
downloadLink: "",
|
||
|
|
serviceLink: "",
|
||
|
|
format: "",
|
||
|
|
license: "Copyright",
|
||
|
|
|
||
|
|
// 🧭 Referensi Spasial
|
||
|
|
crs: "EPSG:4326",
|
||
|
|
geometryType: "",
|
||
|
|
xmin: "",
|
||
|
|
xmax: "",
|
||
|
|
ymin: "",
|
||
|
|
ymax: "",
|
||
|
|
|
||
|
|
// 🧾 Metadata Umum
|
||
|
|
metadataStandard: "ISO 19115:2003/19139",
|
||
|
|
metadataVersion: "1.0",
|
||
|
|
metadataUUID: "", // Nanti di-generate di useEffect agar tidak hydration error
|
||
|
|
metadataDate: "",
|
||
|
|
charset: "utf8",
|
||
|
|
rsIdentifier: "WGS 1984",
|
||
|
|
|
||
|
|
// Override dengan apapun yang ada di initialValues jika key-nya cocok
|
||
|
|
// ...initialValues
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
export default function MetadataForm({ onChange, initialValues = {} }: { onChange: (val: any) => void, initialValues?: any }) {
|
||
|
|
const [formData, setFormData] = useState(initialValues);
|
||
|
|
|
||
|
|
// Generate UUID saat mount (Client Side Only)
|
||
|
|
// useEffect(() => {
|
||
|
|
// if (!formData.metadataUUID) {
|
||
|
|
// setFormData((prev: any) => {
|
||
|
|
// const updated = {
|
||
|
|
// ...prev,
|
||
|
|
// metadataUUID: uuidv4(),
|
||
|
|
// metadataDate: new Date().toISOString().split("T")[0],
|
||
|
|
// };
|
||
|
|
// // Penting: Kabari parent tentang update UUID ini
|
||
|
|
// onChange(updated);
|
||
|
|
// return updated;
|
||
|
|
// });
|
||
|
|
// }
|
||
|
|
// }, []);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
// Cek jika UUID belum ada (hanya saat mount)
|
||
|
|
if (!formData.metadataUUID) {
|
||
|
|
const generatedUUID = uuidv4();
|
||
|
|
const generatedDate = new Date().toISOString().split("T")[0];
|
||
|
|
|
||
|
|
// 1. Siapkan data baru
|
||
|
|
const updatedData = {
|
||
|
|
...formData, // Menggunakan state saat ini
|
||
|
|
metadataUUID: generatedUUID,
|
||
|
|
metadataDate: generatedDate,
|
||
|
|
};
|
||
|
|
|
||
|
|
// 2. Update State Lokal
|
||
|
|
setFormData((prev: any) => ({
|
||
|
|
...prev,
|
||
|
|
metadataUUID: generatedUUID,
|
||
|
|
metadataDate: generatedDate,
|
||
|
|
}));
|
||
|
|
|
||
|
|
// 3. Update State Parent (PENTING: Dilakukan terpisah di sini, BUKAN di dalam setFormData)
|
||
|
|
onChange(updatedData);
|
||
|
|
}
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||
|
|
const { name, value } = e.target;
|
||
|
|
const updated = { ...formData, [name]: value };
|
||
|
|
setFormData(updated);
|
||
|
|
onChange(updated);
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="w-full">
|
||
|
|
<Tabs defaultValue="identifikasi">
|
||
|
|
{/* <TabsList className="mb-4">
|
||
|
|
<TabsTrigger value="identifikasi">Identifikasi</TabsTrigger>
|
||
|
|
<TabsTrigger value="penanggung">Kontak</TabsTrigger>
|
||
|
|
</TabsList> */}
|
||
|
|
|
||
|
|
<TabsContent value="identifikasi" className="space-y-4">
|
||
|
|
<Input label="Judul Dataset" name="title" value={formData.title} onChange={handleChange} />
|
||
|
|
<Textarea label="Abstrak" name="abstract" value={formData.abstract} onChange={handleChange} />
|
||
|
|
<Input label="Kata Kunci (pisahkan dengan koma)" name="keywords" value={formData.keywords} onChange={handleChange} />
|
||
|
|
|
||
|
|
<SelectMultiple
|
||
|
|
label="Kategori Metadata"
|
||
|
|
name="topicCategory"
|
||
|
|
value={formData.topicCategory}
|
||
|
|
onChange={handleChange}
|
||
|
|
options={[
|
||
|
|
{label: "Biota", value: "Biota"},
|
||
|
|
{label: "Farming", value: "Farming"},
|
||
|
|
{label: "Boundaries", value: "Boundaries"},
|
||
|
|
{label: "Climatology, meteorology, atmospherea", value: "Climatology, meteorology, atmospherea"},
|
||
|
|
{label: "Economy", value: "Economy"},
|
||
|
|
{label: "Elevation", value: "Elevation"},
|
||
|
|
{label: "Environment", value: "Environment"},
|
||
|
|
{label: "Geoscientific information", value: "Geoscientific information"},
|
||
|
|
{label: "Health", value: "Health"},
|
||
|
|
{label: "Imagery base maps earth cover", value: "Imagery base maps earth cover"},
|
||
|
|
{label: "Intelligence military", value: "Intelligence military"},
|
||
|
|
{label: "Inland waters", value: "Inland waters"},
|
||
|
|
{label: "Location", value: "Location"},
|
||
|
|
{label: "Oceans", value: "Oceans"},
|
||
|
|
{label: "Planning cadastre", value: "Planning cadastre"},
|
||
|
|
{label: "Society", value: "Society"},
|
||
|
|
{label: "Structure", value: "Structure"},
|
||
|
|
{label: "Transportation", value: "Transportation"},
|
||
|
|
{label: "Utilities communication", value: "Utilities communication"}
|
||
|
|
]}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{/* Ganti dengan Select shadcn jika mau, ini versi native HTML agar cepat */}
|
||
|
|
<Select
|
||
|
|
label="Kategori Mapset"
|
||
|
|
name="mapsetCategory"
|
||
|
|
value={formData.mapsetCategory}
|
||
|
|
onChange={handleChange}
|
||
|
|
options={satupetaCategory}
|
||
|
|
optValue={satupetaCategoryId}
|
||
|
|
/>
|
||
|
|
</TabsContent>
|
||
|
|
|
||
|
|
{/* <TabsContent value="penanggung" className="space-y-4">
|
||
|
|
<Input label="Organisasi" name="organization" value={formData.organization} onChange={handleChange} />
|
||
|
|
<Input label="Nama Kontak" name="contactName" value={formData.contactName} onChange={handleChange} />
|
||
|
|
<Input label="Email" name="contactEmail" value={formData.contactEmail} onChange={handleChange} />
|
||
|
|
</TabsContent> */}
|
||
|
|
</Tabs>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper Components (Bisa dipisah file atau inline)
|
||
|
|
function Input({ label, name, value, onChange }: any) {
|
||
|
|
return (
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium mb-1">{label} <span className="text-red-500">*</span></label>
|
||
|
|
<input className="w-full border rounded p-2 text-sm" name={name} value={value} onChange={onChange} />
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
function Textarea({ label, name, value, onChange }: any) {
|
||
|
|
return (
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium mb-1">{label} <span className="text-red-500">*</span></label>
|
||
|
|
<textarea className="w-full border rounded p-2 text-sm" rows={3} name={name} value={value} onChange={onChange} />
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
function Select({ label, name, value, onChange, options, optValue }: any) {
|
||
|
|
return (
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium mb-1">{label} <span className="text-red-500">*</span></label>
|
||
|
|
<select className="w-full border rounded p-2 text-sm bg-white" name={name} value={value} onChange={onChange}>
|
||
|
|
{options.map((opt: string, i: number) => <option key={i} value={optValue[i]}>{opt}</option>)}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
function SelectMultiple({ label, name, value, onChange, options = []}: any) {
|
||
|
|
return (
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-semibold text-gray-700 mb-1">
|
||
|
|
{label}{" "}<span className="text-red-500">*</span>
|
||
|
|
</label>
|
||
|
|
<FormMultiSelect
|
||
|
|
name={name}
|
||
|
|
value={value}
|
||
|
|
onChange={onChange}
|
||
|
|
options={options}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|