kontenhumas-fe/components/form/communication/internal-form.tsx

381 lines
12 KiB
TypeScript

"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useRouter } from "next/navigation";
import makeAnimated from "react-select/animated";
import Select from "react-select";
import dynamic from "next/dynamic";
import { getCuratorUser, getTicketingPriority, saveTicketingInternal } from "@/service/service/communication/communication";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
message: z.string().min(2, {
message: "Narasi Penugasan harus lebih dari 2 karakter.",
}),
});
interface Option {
id: string;
label: string;
value: string;
fullname: string;
userLevel: string;
userLevelId: string;
}
const CustomEditor = dynamic(
() => import("@/components/editor/custom-editor"),
{ ssr: false }
);
export default function FormInternal() {
const MySwal = withReactContent(Swal);
const router = useRouter();
type TaskSchema = z.infer<typeof taskSchema>;
const [options, setOptions] = useState<Option[]>([]);
const [selectedOption, setSelectedOption] = useState<Option | undefined>();
const [selectedTarget, setSelectedTarget] = useState<number | null>(null);
const animatedComponent = makeAnimated();
const [isSubmitting, setIsSubmitting] = useState(false);
const priority = [
{ value: 1, label: "Low" },
{ value: 2, label: "Medium" },
{ value: 3, label: "High" },
];
const {
control,
handleSubmit,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
});
useEffect(() => {
getUser();
getTicketPriority();
}, []);
const handleChange = (e: any) => {
setSelectedOption(e);
};
async function getTicketPriority() {
const res = await getTicketingPriority();
if (res?.data !== null) {
const rawData = res?.data?.data;
// optional: setTicketPriority(rawData);
}
}
async function getUser() {
const res = await getCuratorUser();
if (res?.data !== null) {
const rawUser = res?.data?.data?.content;
const optionArr: Option[] = rawUser.map((option: any) => ({
id: option?.id,
label: option?.username + option?.fullname + option?.userLevel?.name,
value: option?.username,
fullname: option?.fullname,
userLevel: option?.userLevel?.name,
userLevelId: option?.userLevel?.id,
}));
setOptions(optionArr);
}
}
const save = async (data: TaskSchema) => {
setIsSubmitting(true);
MySwal.fire({
title: "Menyimpan...",
text: "Mohon tunggu, data sedang diproses.",
allowOutsideClick: false,
allowEscapeKey: false,
didOpen: () => {
Swal.showLoading();
},
});
try {
const requestData = {
title: data.title,
message: data.message,
target: selectedTarget,
sendToId: selectedOption?.id,
};
const response = await saveTicketingInternal(requestData);
console.log("Form Data Submitted:", requestData);
console.log("response", response);
Swal.close();
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/in/shared/communication");
});
} catch (error) {
Swal.close();
MySwal.fire({
title: "Error",
text: "Terjadi kesalahan saat menyimpan data.",
icon: "error",
});
console.error("Error saat menyimpan data:", error);
} finally {
setIsSubmitting(false);
}
};
const onSubmit = (data: TaskSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
return (
<Card>
<div className="px-6 py-6 ">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex flex-col justify-center items-center gap-5 mb-5 ">
<div className="w-6/12 space-y-2">
<Label>
Judul<span className="text-red-500">*</span>
</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size="md"
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
<div className="w-6/12">
<Label>
Priority <span className="text-red-500">*</span>
</Label>
<Select
id="target-select"
options={priority}
onChange={(selectedOption) =>
setSelectedTarget(selectedOption?.value ?? null)
}
placeholder="Pilih"
styles={{
control: (base, state) => ({
...base,
minHeight: "40px",
backgroundColor:
document.documentElement.classList.contains("dark")
? "#1f2937" // bg-gray-800
: "#ffffff", // bg-white
color: document.documentElement.classList.contains("dark")
? "#f9fafb" // text-gray-100
: "#111827", // text-gray-900
borderColor: state.isFocused ? "#2563eb" : base.borderColor,
boxShadow: state.isFocused
? "0 0 0 1px #2563eb"
: base.boxShadow,
"&:hover": { borderColor: "#2563eb" },
}),
menu: (base) => ({
...base,
backgroundColor:
document.documentElement.classList.contains("dark")
? "#1f2937"
: "#ffffff",
color: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
}),
option: (base, state) => ({
...base,
backgroundColor: state.isSelected
? "#2563eb"
: state.isFocused
? "#2563eb33"
: document.documentElement.classList.contains("dark")
? "#1f2937"
: "#ffffff",
color: state.isSelected
? "#ffffff"
: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
cursor: "pointer",
}),
singleValue: (base) => ({
...base,
color: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
}),
placeholder: (base) => ({
...base,
color: document.documentElement.classList.contains("dark")
? "#9ca3af"
: "#6b7280",
}),
}}
/>
</div>
{/* <div className="w-6/12">
<Label>
Priority <span className="text-red-500">*</span>
</Label>
<Select
id="target-select"
options={priority}
onChange={(selectedOption) =>
setSelectedTarget(selectedOption?.value ?? null)
}
placeholder="Pilih"
styles={{ control: (base) => ({ ...base, minHeight: "40px" }) }}
/>
</div> */}
<div className="w-6/12">
<Label>Ditunjukan Untuk</Label>
<Select
options={options}
className="w-100"
closeMenuOnSelect={false}
components={animatedComponent}
onChange={handleChange}
isMulti={false}
styles={{
control: (base, state) => ({
...base,
minHeight: "40px",
backgroundColor:
document.documentElement.classList.contains("dark")
? "#1f2937"
: "#ffffff",
color: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
borderColor: state.isFocused ? "#2563eb" : base.borderColor,
boxShadow: state.isFocused
? "0 0 0 1px #2563eb"
: base.boxShadow,
"&:hover": { borderColor: "#2563eb" },
}),
menu: (base) => ({
...base,
backgroundColor:
document.documentElement.classList.contains("dark")
? "#1f2937"
: "#ffffff",
color: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
}),
option: (base, state) => ({
...base,
backgroundColor: state.isSelected
? "#2563eb"
: state.isFocused
? "#2563eb33"
: document.documentElement.classList.contains("dark")
? "#1f2937"
: "#ffffff",
color: state.isSelected
? "#ffffff"
: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
cursor: "pointer",
}),
singleValue: (base) => ({
...base,
color: document.documentElement.classList.contains("dark")
? "#f9fafb"
: "#111827",
}),
placeholder: (base) => ({
...base,
color: document.documentElement.classList.contains("dark")
? "#9ca3af"
: "#6b7280",
}),
}}
/>
</div>
{/* <div className="w-6/12">
<Label>Ditunjukan Untuk</Label>
<Select
options={options}
className="w-100"
closeMenuOnSelect={false}
components={animatedComponent}
onChange={handleChange}
isMulti={false}
/>
</div> */}
<div className="w-6/12 mt-5">
<Label>Narasi Penugasan</Label>
<Controller
control={control}
name="message"
render={({ field: { onChange, value } }) => (
<CustomEditor onChange={onChange} initialData={value} />
)}
/>
{errors.message?.message && (
<p className="text-red-400 text-sm">{errors.message.message}</p>
)}
</div>
<div className="w-6/12 flex justify-end gap-3 mt-5">
<Button type="button" color="primary" variant="outline">
Batal
</Button>
<Button type="submit" color="primary" disabled={isSubmitting}>
{isSubmitting ? "Menyimpan..." : "Submit"}
</Button>
</div>
</div>
</form>
</div>
</Card>
);
}