narasi-ahli/components/form/user-form.tsx

557 lines
17 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
createUser,
updateUser,
getUserDetail,
createWorkHistory,
createEducationHistory,
UserData,
WorkHistoryData,
EducationHistoryData,
} from "@/service/user";
import { toast } from "react-hot-toast";
import Navbar from "../navbar";
interface UserFormProps {
userId?: number;
mode: "create" | "edit";
}
interface EducationItem {
schoolName: string;
major: string;
educationLevel: string;
graduationYear: string;
}
interface WorkItem {
jobTitle: string;
companyName: string;
startDate: string;
endDate: string;
}
export default function UserForm({ userId, mode }: UserFormProps) {
const router = useRouter();
const [mounted, setMounted] = useState(false);
const [loading, setLoading] = useState(false);
const [userType, setUserType] = useState<"tenaga_ahli" | "pengguna_umum">(
"tenaga_ahli",
);
const [educationList, setEducationList] = useState<EducationItem[]>([
{ schoolName: "", major: "", educationLevel: "", graduationYear: "" },
]);
const [workList, setWorkList] = useState<WorkItem[]>([
{ jobTitle: "", companyName: "", startDate: "", endDate: "" },
]);
const [formData, setFormData] = useState<UserData>({
username: "",
email: "",
fullname: "",
address: "",
phoneNumber: "",
whatsappNumber: "",
password: "",
dateOfBirth: "",
genderType: "male",
degree: "",
userLevelId: 3,
userRoleId: 3,
});
// Handle mounting and load user data for edit mode
useEffect(() => {
setMounted(true);
if (mode === "edit" && userId) {
loadUserData();
}
}, [userId, mode]);
const loadUserData = async () => {
try {
setLoading(true);
const response = await getUserDetail(userId!);
if (response.success) {
const data = response.data;
setFormData({
username: data.username,
email: data.email,
fullname: data.fullname,
address: data.address,
phoneNumber: data.phoneNumber,
whatsappNumber: data.whatsappNumber,
password: "", // Don't load password for security
dateOfBirth: data.dateOfBirth,
genderType: data.genderType as "male" | "female",
degree: data.degree || "",
userLevelId: data.userLevelId,
userRoleId: data.userRoleId,
});
// Set user type based on role
setUserType(data.userRoleId === 2 ? "tenaga_ahli" : "pengguna_umum");
}
} catch (error) {
toast.error("Gagal memuat data user");
} finally {
setLoading(false);
}
};
const handleInputChange = (field: keyof UserData, value: any) => {
setFormData((prev) => ({
...prev,
[field]: value,
}));
};
const handleAddEducation = () => {
setEducationList([
...educationList,
{ schoolName: "", major: "", educationLevel: "", graduationYear: "" },
]);
};
const handleAddWork = () => {
setWorkList([
...workList,
{ jobTitle: "", companyName: "", startDate: "", endDate: "" },
]);
};
const handleEducationChange = (
index: number,
field: keyof EducationItem,
value: string,
) => {
const updated = [...educationList];
updated[index][field] = value;
setEducationList(updated);
};
const handleWorkChange = (
index: number,
field: keyof WorkItem,
value: string,
) => {
const updated = [...workList];
updated[index][field] = value;
setWorkList(updated);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
setLoading(true);
// Set user role and level based on user type
const userData = {
...formData,
userRoleId: userType === "tenaga_ahli" ? 3 : 4,
userLevelId: userType === "tenaga_ahli" ? 3 : 4,
};
let response;
if (mode === "create") {
response = await createUser(userData);
} else {
// Remove password from update if empty
const updateData = { ...userData };
if (!updateData.password) {
const { password, ...updateDataWithoutPassword } = updateData;
response = await updateUser(userId!, updateDataWithoutPassword);
} else {
response = await updateUser(userId!, updateData);
}
}
if (!response?.error) {
const userId = response?.data?.data?.id;
if (userId && userType === "tenaga_ahli") {
// Create education history
for (const education of educationList) {
if (
education.schoolName &&
education.major &&
education.educationLevel &&
education.graduationYear
) {
const educationData: EducationHistoryData = {
userId: userId,
schoolName: education.schoolName,
major: education.major,
educationLevel: education.educationLevel,
graduationYear: parseInt(education.graduationYear),
};
await createEducationHistory(educationData);
}
}
// Create work history
for (const work of workList) {
if (
work.jobTitle &&
work.companyName &&
work.startDate &&
work.endDate
) {
const workData: WorkHistoryData = {
userId: userId,
jobTitle: work.jobTitle,
companyName: work.companyName,
startDate: work.startDate,
endDate: work.endDate,
};
await createWorkHistory(workData);
}
}
}
toast.success(
`User berhasil ${mode === "create" ? "dibuat" : "diperbarui"}`,
);
router.push("/admin/management-user");
} else {
toast.error(response.message || "Terjadi kesalahan");
}
} catch (error) {
toast.error("Terjadi kesalahan saat menyimpan user");
} finally {
setLoading(false);
}
};
if (!mounted) {
return (
<div className="flex justify-center items-center h-64">
<div className="text-lg">Loading...</div>
</div>
);
}
if (loading && mode === "edit") {
return (
<div className="flex justify-center items-center h-64">
<div className="text-lg">Memuat data...</div>
</div>
);
}
return (
<div className="flex-1 overflow-hidden flex flex-col h-[90vh]">
<Navbar
title="Management User,/admin/management-user"
subTitle="Edit User"
/>
<div className="flex items-center justify-between mt-10">
<h1 className="text-2xl font-semibold">
{mode === "create" ? "Tambah User Baru" : "Edit User"}
</h1>
<Button variant="outline" onClick={() => router.back()}>
Kembali
</Button>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
{/* User Type Selection */}
<div className="bg-white p-6 rounded-lg border">
<h2 className="text-lg font-semibold mb-4">Jenis Pengguna</h2>
<RadioGroup
value={userType}
onValueChange={(value: "tenaga_ahli" | "pengguna_umum") =>
setUserType(value)
}
className="flex space-x-6"
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="tenaga_ahli" id="tenaga_ahli" />
<Label htmlFor="tenaga_ahli">Tenaga Ahli</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="pengguna_umum" id="pengguna_umum" />
<Label htmlFor="pengguna_umum">Pengguna Umum</Label>
</div>
</RadioGroup>
</div>
{/* Basic Information */}
<div className="bg-white p-6 rounded-lg border">
<h2 className="text-lg font-semibold mb-4">Informasi Dasar</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<Label htmlFor="fullname">Nama Lengkap *</Label>
<Input
id="fullname"
value={formData.fullname}
onChange={(e) => handleInputChange("fullname", e.target.value)}
placeholder="Masukkan Nama Lengkap"
required
/>
</div>
<div>
<Label htmlFor="username">Username *</Label>
<Input
id="username"
value={formData.username}
onChange={(e) => handleInputChange("username", e.target.value)}
placeholder="Masukkan Username"
required
/>
</div>
{userType === "tenaga_ahli" && (
<div>
<Label htmlFor="degree">Gelar</Label>
<Input
id="degree"
value={formData.degree}
onChange={(e) => handleInputChange("degree", e.target.value)}
placeholder="Masukkan Gelar"
/>
</div>
)}
<div>
<Label htmlFor="email">Email *</Label>
<Input
id="email"
type="email"
value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
placeholder="Masukkan Email"
required
/>
</div>
<div>
<Label htmlFor="phoneNumber">No Telepon *</Label>
<Input
id="phoneNumber"
value={formData.phoneNumber}
onChange={(e) =>
handleInputChange("phoneNumber", e.target.value)
}
placeholder="Masukkan No Telepon"
required
/>
</div>
<div>
<Label htmlFor="whatsappNumber">No Whatsapp *</Label>
<Input
id="whatsappNumber"
value={formData.whatsappNumber}
onChange={(e) =>
handleInputChange("whatsappNumber", e.target.value)
}
placeholder="Masukkan No Whatsapp"
required
/>
</div>
<div>
<Label htmlFor="dateOfBirth">Tanggal Lahir *</Label>
<Input
id="dateOfBirth"
type="date"
value={formData.dateOfBirth}
onChange={(e) =>
handleInputChange("dateOfBirth", e.target.value)
}
required
/>
</div>
<div>
<Label htmlFor="genderType">Jenis Kelamin *</Label>
<Select
value={formData.genderType}
onValueChange={(value: "male" | "female") =>
handleInputChange("genderType", value)
}
>
<SelectTrigger>
<SelectValue placeholder="Pilih Jenis Kelamin" />
</SelectTrigger>
<SelectContent>
<SelectItem value="male">Laki-laki</SelectItem>
<SelectItem value="female">Perempuan</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="address">Alamat *</Label>
<Input
id="address"
value={formData.address}
onChange={(e) => handleInputChange("address", e.target.value)}
placeholder="Masukkan Alamat"
required
/>
</div>
{mode === "create" && (
<div>
<Label htmlFor="password">Kata Sandi *</Label>
<Input
id="password"
type="password"
value={formData.password}
onChange={(e) =>
handleInputChange("password", e.target.value)
}
placeholder="Masukkan Kata Sandi"
required={mode === "create"}
/>
</div>
)}
</div>
</div>
{/* Education History - only for Tenaga Ahli */}
{userType === "tenaga_ahli" && (
<div className="bg-white p-6 rounded-lg border">
<h2 className="text-lg font-semibold mb-4">Riwayat Pendidikan</h2>
{educationList.map((education, index) => (
<div
key={index}
className="grid grid-cols-1 md:grid-cols-5 gap-4 mb-4"
>
<Input
placeholder="Masukkan Nama Sekolah/Universitas"
value={education.schoolName}
onChange={(e) =>
handleEducationChange(index, "schoolName", e.target.value)
}
/>
<Input
placeholder="Masukkan Jurusan"
value={education.major}
onChange={(e) =>
handleEducationChange(index, "major", e.target.value)
}
/>
<Input
placeholder="Masukkan Tingkat Pendidikan"
value={education.educationLevel}
onChange={(e) =>
handleEducationChange(
index,
"educationLevel",
e.target.value,
)
}
/>
<Input
placeholder="Masukkan Tahun Lulus"
type="number"
value={education.graduationYear}
onChange={(e) =>
handleEducationChange(
index,
"graduationYear",
e.target.value,
)
}
/>
<div className="flex gap-2">
<Button variant="secondary" className="whitespace-nowrap">
+ Ijazah
</Button>
{index === educationList.length - 1 && (
<Button
type="button"
variant="outline"
onClick={handleAddEducation}
>
+ Tambah
</Button>
)}
</div>
</div>
))}
</div>
)}
{/* Work History - only for Tenaga Ahli */}
{userType === "tenaga_ahli" && (
<div className="bg-white p-6 rounded-lg border">
<h2 className="text-lg font-semibold mb-4">Riwayat Pekerjaan</h2>
{workList.map((work, index) => (
<div
key={index}
className="grid grid-cols-1 md:grid-cols-5 gap-4 mb-4"
>
<Input
placeholder="Masukkan Jabatan"
value={work.jobTitle}
onChange={(e) =>
handleWorkChange(index, "jobTitle", e.target.value)
}
/>
<Input
placeholder="Masukkan Nama Perusahaan"
value={work.companyName}
onChange={(e) =>
handleWorkChange(index, "companyName", e.target.value)
}
/>
<Input
placeholder="Tanggal Mulai"
type="date"
value={work.startDate}
onChange={(e) =>
handleWorkChange(index, "startDate", e.target.value)
}
/>
<Input
placeholder="Tanggal Selesai"
type="date"
value={work.endDate}
onChange={(e) =>
handleWorkChange(index, "endDate", e.target.value)
}
/>
{index === workList.length - 1 && (
<Button
type="button"
variant="outline"
onClick={handleAddWork}
>
+ Tambah
</Button>
)}
</div>
))}
</div>
)}
{/* Submit Button */}
<div className="flex justify-end space-x-4">
<Button type="button" variant="outline" onClick={() => router.back()}>
Batal
</Button>
<Button type="submit" disabled={loading}>
{loading
? "Menyimpan..."
: mode === "create"
? "Buat User"
: "Perbarui User"}
</Button>
</div>
</form>
</div>
);
}