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

457 lines
15 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 {
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
} from "@radix-ui/react-select";
import { SelectGroup } from "@/components/ui/select";
import dynamic from "next/dynamic";
import { getCuratorUser, getTicketingPriority, saveTicketing } from "@/service/service/communication/communication";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
naration: 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(
() => {
return import("@/components/editor/custom-editor");
},
{ ssr: false }
);
export default function FormCollaboration() {
const MySwal = withReactContent(Swal);
const router = useRouter();
const editor = useRef(null);
type TaskSchema = z.infer<typeof taskSchema>;
const [isSubmitting, setIsSubmitting] = useState(false);
const [taskOutput, setTaskOutput] = useState({
all: false,
video: false,
audio: false,
image: false,
text: false,
});
const [assignmentType, setAssignmentType] = useState("mediahub");
const [assignmentCategory, setAssignmentCategory] = useState("publication");
const [mainType, setMainType] = useState<number>(1);
const [type, setType] = useState<string>("1");
const [options, setOptions] = useState<Option[]>([]);
const [ticketPriority, setTicketPriority] = useState<
{ value: number; label: string }[]
>([]);
const [selectedOption, setSelectedOption] = useState<Option | undefined>(
undefined
);
const animatedComponent = makeAnimated();
const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
const [selectedTarget, setSelectedTarget] = useState<number | null>(null);
const priority = [
{ value: "low", label: "Low" },
{ value: "medium", label: "Medium" },
{ value: "high", label: "High" },
];
const {
control,
handleSubmit,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
});
const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const selectedValue = Number(event.target.value);
setMainType(selectedValue);
setPlatformTypeVisible(selectedValue === 2);
};
useEffect(() => {
getUser();
getTicketPriority();
});
const handleChange = (e: any) => {
const selected = e;
setSelectedOption(selected);
};
const formatOptionLabel = (option: Option) => (
<>
<div className="row">
<div className="col">
{option.value} | {option.fullname}
</div>
</div>
<div className="row">
<div className="col">
<b>{option.userLevel}</b>
</div>
</div>
</>
);
async function getTicketPriority() {
const res = await getTicketingPriority();
if (res?.data !== null) {
const rawData = res?.data?.data;
const priorityOptions = rawData.map((item: any) => ({
value: item.id,
label: item.name,
}));
setTicketPriority(priorityOptions);
}
}
async function getUser() {
const res = await getCuratorUser();
if (res?.data !== null) {
const rawUser = res?.data?.data?.content;
console.log("raw user", rawUser);
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 sebentar",
allowOutsideClick: false,
allowEscapeKey: false,
didOpen: () => {
Swal.showLoading();
},
});
const requestData = {
title: data.title,
typeId: 11,
statusId: 1,
message: data.naration,
priorityId: selectedTarget,
isCollaboration: true,
isEscalation: true,
isCollaborationWithNoneTicket: true,
operatorTeam: selectedOption?.id,
};
const response = await saveTicketing(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/supervisor/communications/collaboration");
});
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 border rounded-lg bg-slate-100">
<p className="text-lg font-semibold mb-3">Form Penugasan</p>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul</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-full">
<div className="mt-5">
<Label>
Priority<span className="text-red-500">*</span>
</Label>
<Select
id="target-select"
options={ticketPriority}
onChange={(selectedOption) =>
setSelectedTarget(Number(selectedOption?.value))
}
placeholder="Pilih"
styles={{
control: (base, state) => ({
...base,
minHeight: "40px",
backgroundColor:
document.documentElement.classList.contains("dark")
? "#1f2937" // gray-800
: "#ffffff",
color: document.documentElement.classList.contains("dark")
? "#f9fafb" // gray-100
: "#111827", // gray-900
borderColor: state.isFocused
? "#2563eb"
: base.borderColor, // biru-600
boxShadow: state.isFocused
? "0 0 0 1px #2563eb"
: base.boxShadow,
"&:hover": {
borderColor: "#2563eb",
},
}),
menu: (base) => ({
...base,
backgroundColor:
document.documentElement.classList.contains("dark")
? "#1f2937"
: "#ffffff",
}),
option: (base, state) => ({
...base,
backgroundColor: state.isSelected
? "#2563eb" // biru solid kalau dipilih
: state.isFocused
? "#2563eb33" // biru transparan kalau hover
: 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="mt-5">
<Label>
Priority<span className="text-red-500">*</span>
</Label>
<Select
className="bg-white dark:bg-black"
id="target-select"
options={ticketPriority}
onChange={(selectedOption) =>
setSelectedTarget(Number(selectedOption?.value))
}
placeholder="Pilih"
styles={{
control: (base) => ({
...base,
minHeight: "40px",
}),
}}
/>
</div> */}
</div>
<div className="w-full">
<div className="mt-5">
<Label>
Eskalasi Untuk <span className="text-red-500">*</span>
</Label>
<Select
options={options}
className="w-100"
closeMenuOnSelect={false}
components={animatedComponent}
onChange={handleChange}
formatOptionLabel={formatOptionLabel}
isMulti={false}
styles={{
control: (base, state) => ({
...base,
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="mt-5">
<Label>
Eskalasi Untuk <span className="text-red-500">*</span>
</Label>
<Select
options={options}
className="w-100"
closeMenuOnSelect={false}
components={animatedComponent}
onChange={handleChange}
formatOptionLabel={formatOptionLabel}
isMulti={false}
/>
</div> */}
</div>
<div className="mt-5">
<Label>Narasi Penugasan</Label>
<Controller
control={control}
name="naration"
render={({ field: { onChange, value } }) => (
<CustomEditor onChange={onChange} initialData={value} />
)}
/>
{errors.naration?.message && (
<p className="text-red-400 text-sm">
{errors.naration.message}
</p>
)}
</div>
</div>
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
</div>
</Card>
);
}