[QUDO-65] feat:Fixing Kurasi Konten Ask the expert & Do it Yourself

This commit is contained in:
Anang Yusman 2025-05-14 17:44:27 +08:00
parent 1962f7b735
commit 1572534bd4
2 changed files with 112 additions and 407 deletions

View File

@ -25,6 +25,7 @@ import {
createTaskTa,
getTask,
getUserLevelForAssignments,
getUserLevelForExpert,
} from "@/service/task";
import {
Dialog,
@ -55,6 +56,7 @@ import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
import "react-clock/dist/Clock.css";
import { detailMedia } from "@/service/curated-content/curated-content";
import { getListCompetencies } from "@/service/management-user/management-user";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@ -130,12 +132,17 @@ export default function FormAskExpert() {
const [detail, setDetail] = useState<taskDetail>();
const [refresh] = useState(false);
const [listDest, setListDest] = useState([]);
const [checkedLevels, setCheckedLevels] = useState(new Set());
const [checkedLevels, setCheckedLevels] = useState<Set<number>>(new Set());
const [expandedPolda, setExpandedPolda] = useState([{}]);
const [isLoading, setIsLoading] = useState(false);
const [audioFile, setAudioFile] = useState<File | null>(null);
const [isRecording, setIsRecording] = useState(false);
const [timer, setTimer] = useState<number>(120);
const [userCompetencies, setUserCompetencies] = useState<any[]>([]);
const [selectedCompetencies, setSelectedCompetencies] = useState<Set<number>>(
new Set()
);
const [listExpert, setListExpert] = useState<any[]>([]);
const t = useTranslations("Form");
const [imageFiles, setImageFiles] = useState<FileWithPreview[]>([]);
@ -151,21 +158,6 @@ export default function FormAskExpert() {
from: new Date(2024, 0, 1),
});
const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
const [unitSelection, setUnitSelection] = useState({
semua: false,
mabes: false,
polda: false,
polres: false,
satker: false,
});
const [taskOutput, setTaskOutput] = useState({
all: false,
video: false,
audio: false,
image: false,
text: false,
});
const [links, setLinks] = useState<string[]>([""]);
const {
@ -179,37 +171,68 @@ export default function FormAskExpert() {
mode: "all",
});
// const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
// const selectedValue = Number(event.target.value);
// setMainType(selectedValue);
useEffect(() => {
getDataAdditional();
}, []);
// setPlatformTypeVisible(selectedValue === 2);
async function getDataAdditional() {
const resCompetencies = await getListCompetencies();
console.log("competency", resCompetencies);
setUserCompetencies(resCompetencies?.data?.data);
}
useEffect(() => {
async function fetchPoldaPolres() {
async function fetchListExpert() {
setIsLoading(true);
try {
const response = await getUserLevelForAssignments();
setListDest(response?.data?.data.list);
console.log("polda", response?.data?.data?.list);
const initialExpandedState = response?.data?.data.list.reduce(
(acc: any, polda: any) => {
acc[polda.id] = false;
return acc;
},
{}
);
setExpandedPolda(initialExpandedState);
console.log("polres", initialExpandedState);
const response = await getUserLevelForExpert(id);
setListExpert(response?.data?.data);
console.log("tenaga ahli", response?.data?.data);
} catch (error) {
console.error("Error fetching Polda/Polres data:", error);
} finally {
setIsLoading(false);
}
}
fetchPoldaPolres();
fetchListExpert();
}, []);
useEffect(() => {
async function initState() {
if (id) {
const response = await detailMedia(id);
const details = response?.data?.data;
setDetail(details);
}
}
initState();
}, [id, refresh]);
useEffect(() => {
const fetchExpertsForCompetencies = async () => {
const allExperts: any[] = [];
for (const compId of Array.from(selectedCompetencies)) {
const response = await getUserLevelForExpert(compId);
const experts = response?.data?.data || [];
allExperts.push(...experts);
}
const uniqueExperts = Array.from(
new Map(allExperts.map((e) => [e.id, e])).values()
);
setListExpert(uniqueExperts);
};
if (selectedCompetencies.size > 0) {
fetchExpertsForCompetencies();
} else {
setListExpert([]);
}
}, [selectedCompetencies]);
// };
const handleCheckboxChange = (levelId: number) => {
setCheckedLevels((prev) => {
@ -223,217 +246,39 @@ export default function FormAskExpert() {
});
};
const handlePoldaPolresChange = () => {
return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
const handleExpertChange = () => {
return Array.from(checkedLevels).join(",");
};
const handleUnitChange = (
key: keyof typeof unitSelection,
value: boolean
) => {
if (key === "semua") {
const newState = {
semua: value,
mabes: value,
polda: value,
polres: value,
satker: value,
};
setUnitSelection(newState);
} else {
const updatedSelection = {
...unitSelection,
[key]: value,
};
const allChecked = ["mabes", "polda", "polres", "satker"].every(
(k) => updatedSelection[k as keyof typeof unitSelection]
);
updatedSelection.semua = allChecked;
setUnitSelection(updatedSelection);
}
};
const handleExpertiseOutputChange = (
key: keyof typeof expertise,
value: boolean
) => {
if (key === "semua") {
const newState = {
semua: value,
komunikasi: value,
hukum: value,
bahasa: value,
ekonomi: value,
politik: value,
sosiologi: value,
ilmuadministrasipemerintah: value,
ti: value,
};
setExpertiseOutput(newState);
} else {
const updated = {
...expertise,
[key]: value,
};
const allChecked = [
"komunikasi",
"hukum",
"bahasa",
"ekonomi",
"politik",
"sosiologi",
"ilmuadministrasipemerintah",
"ti",
].every((k) => updated[k as keyof typeof expertise]);
updated.semua = allChecked;
setExpertiseOutput(updated);
}
};
const handleExpertOutputChange = (
key: keyof typeof expert,
value: boolean
) => {
if (key === "semua") {
const newState = {
semua: value,
};
setExpertOutput(newState);
} else {
const updated = {
...expert,
[key]: value,
};
const allChecked = ["video", "audio", "image", "text"].every(
(k) => updated[k as keyof typeof expert]
);
updated.semua = allChecked;
setExpertOutput(updated);
}
};
useEffect(() => {
async function initState() {
if (id) {
const response = await detailMedia(id);
const details = response?.data?.data;
setDetail(details);
const handleCompetencyChange = async (competencyId: number) => {
setSelectedCompetencies((prev) => {
const updated = new Set(prev);
if (updated.has(competencyId)) {
updated.delete(competencyId);
} else {
updated.add(competencyId);
}
}
initState();
}, [id, refresh]);
const handleTaskOutputChange = (
key: keyof typeof taskOutput,
value: boolean
) => {
if (key === "all") {
const newState = {
all: value,
video: value,
audio: value,
image: value,
text: value,
};
setTaskOutput(newState);
} else {
const updated = {
...taskOutput,
[key]: value,
};
const allChecked = ["video", "audio", "image", "text"].every(
(k) => updated[k as keyof typeof taskOutput]
);
updated.all = allChecked;
setTaskOutput(updated);
}
return updated;
});
};
const save = async (data: TaskSchema) => {
const fileTypeMapping = {
all: "1",
video: "2",
audio: "4",
image: "3",
text: "5",
};
const areasMapping = {
semua: "0",
komunikasi: "1",
hukum: "2",
bahasa: "3",
ekonomi: "4",
politik: "5",
sosiologi: "6",
ilmuadministrasipemerintah: "7",
ti: "8",
};
const unitMapping = {
allUnit: "0",
mabes: "1",
polda: "2",
polres: "3",
satker: "4",
};
const assignmentPurposeString = Object.keys(unitSelection)
.filter((key) => unitSelection[key as keyof typeof unitSelection])
.map((key) => unitMapping[key as keyof typeof unitMapping])
.join(",");
const selectedOutputs = Object.keys(taskOutput)
.filter((key) => taskOutput[key as keyof typeof taskOutput])
.map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping])
.join(",");
const selectedAreaExpert = Object.keys(expertise)
.filter((key) => expertise[key as keyof typeof expertise])
.map((key) => areasMapping[key as keyof typeof areasMapping])
.join(",");
const requestData: {
id?: number;
title: string;
assignedToLevel: any;
assignedToUsers: any;
assignmentTypeId: string;
fileTypeOutput: string;
areasExpertise: string;
narration: string;
platformType: string | null;
assignmentMainTypeId: any;
assignmentType: string;
assignedToRole: string;
broadcastType: string;
expertCompetencies: string;
attachmentUrl: string[];
} = {
...data,
// assignmentType,
// assignmentCategory,
assignedToLevel: handlePoldaPolresChange(),
assignedToUsers: assignmentPurposeString,
assignedToRole: selectedTarget,
assignedToUsers: handleExpertChange(),
assignmentType: taskType,
broadcastType: broadcastType,
assignmentMainTypeId: mainType,
areasExpertise: selectedAreaExpert,
assignmentTypeId: type,
fileTypeOutput: selectedOutputs,
narration: data.naration,
platformType: "",
expertCompetencies: "1,2,3",
expertCompetencies: Array.from(selectedCompetencies).join(","),
title: data.title,
attachmentUrl: links,
};
@ -676,7 +521,6 @@ export default function FormAskExpert() {
{detail !== undefined ? (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>{t("title")}</Label>
<Controller
@ -696,53 +540,6 @@ export default function FormAskExpert() {
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
<div className="mt-5">
<Label>Ditujukan Kepada :</Label>
</div>
<div className=" space-y-2">
<Label>{t("areas-expertise")}</Label>
<div className="flex flex-wrap gap-4">
{Object.keys(expertise).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={expertise[key as keyof typeof expertise]}
onCheckedChange={(value) =>
handleExpertiseOutputChange(
key as keyof typeof expertise,
value as boolean
)
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5 space-y-2">
<Label>{t("choose-expert")}</Label>
<div className="flex flex-wrap gap-4">
{Object.keys(expert).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={expert[key as keyof typeof expert]}
onCheckedChange={(value) =>
handleExpertOutputChange(
key as keyof typeof expert,
value as boolean
)
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="flex flex-col space-y-2 mt-5">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
@ -784,27 +581,54 @@ export default function FormAskExpert() {
</Popover>
</div>
<div className="mt-5 space-y-2">
<Label>{t("output-task")}</Label>
<Label>{t("areas-expertise")}</Label>
<div className="flex flex-wrap gap-4">
{Object.keys(taskOutput).map((key) => (
<div className="flex items-center gap-2" key={key}>
{userCompetencies?.map((item: any) => (
<div className="flex items-center gap-2" key={item.id}>
<Checkbox
id={key}
checked={taskOutput[key as keyof typeof taskOutput]}
onCheckedChange={(value) =>
handleTaskOutputChange(
key as keyof typeof taskOutput,
value as boolean
)
}
id={`comp-${item.id}`}
checked={selectedCompetencies.has(item.id)}
onCheckedChange={() => handleCompetencyChange(item.id)}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
<Label htmlFor={`comp-${item.id}`}>{item.name}</Label>
</div>
))}
</div>
</div>
<div className="mt-5 space-y-2">
<Label>{t("choose-expert")}</Label>
<div className="flex flex-wrap gap-4">
<Dialog>
<DialogTrigger asChild>
<Button variant="soft" size="sm" color="primary">
[{"Pilih Tenaga Ahli"}]
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
<DialogHeader>
<DialogTitle>Daftar Tenaga Ahli</DialogTitle>
</DialogHeader>
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
{listExpert?.map((expert: any) => (
<div key={expert.id} className="border p-2">
<Label className="flex items-center">
<Checkbox
checked={checkedLevels.has(expert.id)}
onCheckedChange={() =>
handleCheckboxChange(expert.id)
}
className="mr-3"
/>
{expert.fullname}
</Label>
</div>
))}
</div>
</DialogContent>
</Dialog>
</div>
</div>
<div className="mt-5 space-y-2">
<Label>{t("description")}</Label>
<Controller

View File

@ -383,32 +383,22 @@ export default function FormDoItYourself() {
const requestData: {
id?: number;
title: string;
assignedToLevel: any;
assignedToUsers: any;
assignmentTypeId: string;
fileTypeOutput: string;
narration: string;
platformType: string | null;
assignmentMainTypeId: any;
assignmentType: string;
assignedToRole: string;
broadcastType: string;
expertCompetencies: string;
attachmentUrl: string[];
} = {
...data,
// assignmentType,
// assignmentCategory,
assignedToLevel: handlePoldaPolresChange(),
assignedToUsers: assignmentPurposeString,
assignedToRole: selectedTarget,
assignmentType: taskType,
broadcastType: broadcastType,
assignmentMainTypeId: mainType,
assignmentTypeId: type,
fileTypeOutput: selectedOutputs,
narration: data.naration,
platformType: "",
expertCompetencies: "1,2,3",
title: data.title,
attachmentUrl: links,
@ -695,116 +685,7 @@ export default function FormDoItYourself() {
))}
</div>
</div>
<div className="mt-5 space-y-2">
<Label>{t("assignment-selection")}</Label>
<div className="flex flex-wrap gap-3 ">
{Object.keys(unitSelection).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={
unitSelection[key as keyof typeof unitSelection]
}
onCheckedChange={(value) =>
handleUnitChange(
key as keyof typeof unitSelection,
value as boolean
)
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
<div className=" lg:pl-3">
<Dialog>
<DialogTrigger asChild>
<Button variant="soft" size="sm" color="primary">
[{t("custom")}]
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
<DialogHeader>
<DialogTitle>
Daftar Wilayah Polda dan Polres
</DialogTitle>
</DialogHeader>
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
{listDest.map((polda: any) => (
<div key={polda.id} className="border p-2">
<Label className="flex items-center">
<Checkbox
checked={checkedLevels.has(polda.id)}
onCheckedChange={() =>
handleCheckboxChange(polda.id)
}
className="mr-3"
/>
{polda.name}
<button
onClick={() => toggleExpand(polda.id)}
className="ml-2 focus:outline-none"
>
{expandedPolda[polda.id] ? (
<ChevronUp size={16} />
) : (
<ChevronDown size={16} />
)}
</button>
</Label>
{expandedPolda[polda.id] && (
<div className="ml-6 mt-2">
<Label className="block">
<Checkbox
checked={polda?.subDestination?.every(
(polres: any) =>
checkedLevels.has(polres.id)
)}
onCheckedChange={(isChecked) => {
const updatedLevels = new Set(
checkedLevels
);
polda?.subDestination?.forEach(
(polres: any) => {
if (isChecked) {
updatedLevels.add(polres.id);
} else {
updatedLevels.delete(polres.id);
}
}
);
setCheckedLevels(updatedLevels);
}}
className="mr-2"
/>
Pilih Semua Polres
</Label>
{polda?.subDestination?.map((polres: any) => (
<Label
key={polres.id}
className="block mt-1"
>
<Checkbox
checked={checkedLevels.has(polres.id)}
onCheckedChange={() =>
handleCheckboxChange(polres.id)
}
className="mr-2"
/>
{polres.name}
</Label>
))}
</div>
)}
</div>
))}
</div>
</DialogContent>
</Dialog>
</div>
</div>
</div>
<div className="mt-5 space-y-2">
<Label>{t("type-of-task")}</Label>
<RadioGroup