fix user level, category parent

This commit is contained in:
Rama Priyanto 2025-02-27 00:12:10 +07:00
parent fc539c66f7
commit ada307accc
5 changed files with 140 additions and 33 deletions

View File

@ -33,6 +33,7 @@ import {
} from "@/service/master-categories"; } from "@/service/master-categories";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Image from "next/image";
const categorySchema = z.object({ const categorySchema = z.object({
id: z.number(), id: z.number(),
@ -48,6 +49,9 @@ const createArticleSchema = z.object({
message: "Deskripsi harus diisi", message: "Deskripsi harus diisi",
}), }),
tags: z.array(z.string()), tags: z.array(z.string()),
// parent: z.array(categorySchema).nonempty({
// message: "Kategori harus memiliki setidaknya satu item",
// }),
// tags: z.array(z.string()).nonempty({ // tags: z.array(z.string()).nonempty({
// message: "Minimal 1 tag", // message: "Minimal 1 tag",
// }), // }),
@ -69,10 +73,11 @@ export default function MasterCategoryTable() {
const [files, setFiles] = useState<File[]>([]); const [files, setFiles] = useState<File[]>([]);
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [tag, setTag] = useState(""); const [tag, setTag] = useState("");
const [selectedParent, setSelectedParent] = useState<any>();
const formOptions = { const formOptions = {
resolver: zodResolver(createArticleSchema), resolver: zodResolver(createArticleSchema),
defaultValues: { title: "", description: "", category: [], tags: [] }, defaultValues: { title: "", description: "", tags: [] },
}; };
const { getRootProps, getInputProps } = useDropzone({ const { getRootProps, getInputProps } = useDropzone({
@ -122,7 +127,7 @@ export default function MasterCategoryTable() {
const formData = { const formData = {
title: values.title, title: values.title,
statusId: 1, statusId: 1,
parentId: 1, parentId: selectedParent ? selectedParent.id : 0,
tags: values.tags.join(","), tags: values.tags.join(","),
description: values.description, description: values.description,
}; };
@ -250,6 +255,27 @@ export default function MasterCategoryTable() {
</p> </p>
)} )}
</div> </div>
<div className="flex flex-col gap-1">
<p className="text-sm mt-3">Parent</p>
<ReactSelect
className="basic-single text-black z-50"
classNames={{
control: (state: any) =>
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
}}
classNamePrefix="select"
onChange={setSelectedParent}
closeMenuOnSelect={false}
components={animatedComponents}
isClearable={true}
isSearchable={true}
isMulti={false}
placeholder="Kategori..."
name="sub-module"
options={listCategory}
/>
</div>
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<p className="text-sm mt-3">Tag Terkait</p> <p className="text-sm mt-3">Tag Terkait</p>
<Controller <Controller
@ -337,10 +363,12 @@ export default function MasterCategoryTable() {
{files.length > 0 && ( {files.length > 0 && (
<div className="flex flex-row gap-2"> <div className="flex flex-row gap-2">
<img <Image
src={URL.createObjectURL(files[0])} src={URL.createObjectURL(files[0])}
className="w-[30%]" className="w-[30%]"
alt="thumbnail" alt="thumbnail"
width={480}
height={480}
/> />
<Button <Button
className=" border-none rounded-full" className=" border-none rounded-full"

View File

@ -87,6 +87,8 @@ export default function EditUserLevelForm() {
} = useForm<UserSettingSchema>(formOptions); } = useForm<UserSettingSchema>(formOptions);
const watchName = watch("name"); const watchName = watch("name");
const selectedGroup = watch("group");
const generateSlug = (title: string) => { const generateSlug = (title: string) => {
return title return title
.toLowerCase() .toLowerCase()
@ -108,13 +110,15 @@ export default function EditUserLevelForm() {
const findParent = (group: string) => { const findParent = (group: string) => {
if (group === "mabes") { if (group === "mabes") {
return 0; return 0;
} else if (group === "polda" || group === "satker") { }
if (group === "polda") { // else if (group === "polda" || group === "satker") {
return 1; // if (group === "polda") {
} else { // return 1;
return 555; // } else {
} // return 555;
} else { // }
// }
else {
return selectedParent?.id; return selectedParent?.id;
} }
}; };
@ -170,18 +174,23 @@ export default function EditUserLevelForm() {
} }
useEffect(() => { useEffect(() => {
fetchCategory(); if (findSelectedLevel(selectedGroup)?.level !== 1) {
}, []); fetchCategory();
}
}, [selectedGroup]);
const fetchCategory = async () => { const fetchCategory = async () => {
loading(); loading();
const request = { const request = {
limit: 10, limit: 10,
levelNumber: findSelectedLevel(selectedGroup)?.level
? findSelectedLevel(selectedGroup)!.level - 1
: "",
}; };
const res = await getAllUserLevels(request); const res = await getAllUserLevels(request);
close(); close();
if (res?.data?.data) { if (res?.data?.data) {
setupParent(res?.data?.data); return setupParent(res?.data?.data);
} }
}; };
@ -195,21 +204,21 @@ export default function EditUserLevelForm() {
}); });
} }
setParentList(temp); setParentList(temp);
return temp;
}; };
const selectedGroup = watch("group");
useEffect(() => { useEffect(() => {
initFetch(); initFetch();
}, [parentList]); }, []);
const initFetch = async () => { const initFetch = async () => {
const parent = await fetchCategory();
const res = await getUserLevels(String(id)); const res = await getUserLevels(String(id));
const data = res?.data?.data; const data = res?.data?.data;
setValue("name", data?.name); setValue("name", data?.name);
setValue("aliasName", data?.aliasName); setValue("aliasName", data?.aliasName);
setValue("group", data?.group); setValue("group", data?.group);
const parentId = parentList.find((a: any) => a.id === data?.parentLevelId); const parentId = parent?.find((a: any) => a.id === data?.parentLevelId);
setSelectedParent(parentId); setSelectedParent(parentId);
}; };
@ -314,7 +323,7 @@ export default function EditUserLevelForm() {
{needApproval ? "Active" : "Inactive"} {needApproval ? "Active" : "Inactive"}
</p> </p>
</Switch> </Switch>
{findSelectedLevel(selectedGroup)?.level === 3 && ( {selectedGroup && findSelectedLevel(selectedGroup)?.level !== 1 && (
<> <>
<p className="text-sm mt-3">Parent</p> <p className="text-sm mt-3">Parent</p>
<ReactSelect <ReactSelect

View File

@ -83,6 +83,7 @@ export default function CreateMasterUserLevelForm() {
} = useForm<UserSettingSchema>(formOptions); } = useForm<UserSettingSchema>(formOptions);
const watchName = watch("name"); const watchName = watch("name");
const selectedGroup = watch("group");
const generateSlug = (title: string) => { const generateSlug = (title: string) => {
return title return title
.toLowerCase() .toLowerCase()
@ -104,13 +105,15 @@ export default function CreateMasterUserLevelForm() {
const findParent = (group: string) => { const findParent = (group: string) => {
if (group === "mabes") { if (group === "mabes") {
return 0; return 0;
} else if (group === "polda" || group === "satker") { }
if (group === "polda") { // else if (group === "polda" || group === "satker") {
return 1; // if (group === "polda") {
} else { // return 1;
return 555; // } else {
} // return 555;
} else { // }
// }
else {
return selectedParent?.id; return selectedParent?.id;
} }
}; };
@ -166,13 +169,18 @@ export default function CreateMasterUserLevelForm() {
} }
useEffect(() => { useEffect(() => {
fetchCategory(); if (findSelectedLevel(selectedGroup)?.level !== 1) {
}, []); fetchCategory();
}
}, [selectedGroup]);
const fetchCategory = async () => { const fetchCategory = async () => {
loading(); loading();
const request = { const request = {
limit: 10, limit: 10,
levelNumber: findSelectedLevel(selectedGroup)?.level
? findSelectedLevel(selectedGroup)!.level - 1
: "",
}; };
const res = await getAllUserLevels(request); const res = await getAllUserLevels(request);
close(); close();
@ -193,8 +201,6 @@ export default function CreateMasterUserLevelForm() {
setParentList(temp); setParentList(temp);
}; };
const selectedGroup = watch("group");
return ( return (
<form <form
className="flex flex-col lg:flex-row gap-8 text-black p-8" className="flex flex-col lg:flex-row gap-8 text-black p-8"
@ -289,7 +295,7 @@ export default function CreateMasterUserLevelForm() {
{errors?.name && ( {errors?.name && (
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p> <p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
)} )}
{findSelectedLevel(selectedGroup)?.level === 3 && ( {selectedGroup && findSelectedLevel(selectedGroup)?.level !== 1 && (
<> <>
<p className="text-sm mt-3">Parent</p> <p className="text-sm mt-3">Parent</p>
<ReactSelect <ReactSelect

View File

@ -62,6 +62,7 @@ import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import * as z from "zod"; import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import Image from "next/image";
const columns = [ const columns = [
{ name: "No", uid: "no" }, { name: "No", uid: "no" },
@ -123,6 +124,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
resolver: zodResolver(createArticleSchema), resolver: zodResolver(createArticleSchema),
defaultValues: { title: "", description: "", category: [], tags: [] }, defaultValues: { title: "", description: "", category: [], tags: [] },
}; };
const [selectedParent, setSelectedParent] = useState<any>();
const { getRootProps, getInputProps } = useDropzone({ const { getRootProps, getInputProps } = useDropzone({
onDrop: (acceptedFiles) => { onDrop: (acceptedFiles) => {
@ -198,6 +200,29 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
}); });
}; };
useEffect(() => {
fetchCategory();
}, []);
const fetchCategory = async () => {
const res = await getArticleByCategory();
if (res?.data?.data) {
setupCategory(res?.data?.data);
}
};
const setupCategory = (data: any) => {
const temp = [];
for (const element of data) {
temp.push({
id: element.id,
label: element.title,
value: element.id,
});
}
setListCategory(temp);
};
const openModal = async (id: number | string, detail: boolean) => { const openModal = async (id: number | string, detail: boolean) => {
setIsDetail(detail); setIsDetail(detail);
const res = await getCategoryById(Number(id)); const res = await getCategoryById(Number(id));
@ -207,10 +232,19 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
setValue("description", data?.description); setValue("description", data?.description);
setValue("tags", data?.tags); setValue("tags", data?.tags);
setValue("file", data?.thumbnailUrl); setValue("file", data?.thumbnailUrl);
findParent(data?.parentId);
onOpen(); onOpen();
}; };
const findParent = (parent: number | undefined) => {
const finded = listCategory?.find((a: any) => a.id === parent);
console.log("listt", finded);
if (finded) {
setSelectedParent(finded);
}
};
const renderCell = useCallback( const renderCell = useCallback(
(category: ArticleData, columnKey: Key) => { (category: ArticleData, columnKey: Key) => {
const cellValue = category[columnKey as keyof ArticleData]; const cellValue = category[columnKey as keyof ArticleData];
@ -307,7 +341,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
id: Number(values.id), id: Number(values.id),
title: values.title, title: values.title,
statusId: 1, statusId: 1,
parentId: 1, parentId: selectedParent ? selectedParent.id : 0,
tags: values.tags.join(","), tags: values.tags.join(","),
description: values.description, description: values.description,
}; };
@ -522,6 +556,29 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
</p> </p>
)} )}
</div> </div>
<div className="flex flex-col gap-1">
<p className="text-sm mt-3">Parent</p>
<ReactSelect
className="basic-single text-black z-50"
classNames={{
control: (state: any) =>
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
}}
classNamePrefix="select"
value={selectedParent}
isDisabled={isDetail}
onChange={setSelectedParent}
closeMenuOnSelect={false}
components={animatedComponents}
isClearable={true}
isSearchable={true}
isMulti={false}
placeholder="Kategori..."
name="sub-module"
options={listCategory}
/>
</div>
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<p className="text-sm mt-3">Tag Terkait</p> <p className="text-sm mt-3">Tag Terkait</p>
<Controller <Controller
@ -589,10 +646,12 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
/> />
</div> </div>
{isDetail ? ( {isDetail ? (
<img <Image
src={getValues("file")} src={getValues("file")}
className="w-[30%]" className="w-[30%]"
alt="thumbnail" alt="thumbnail"
width={480}
height={480}
/> />
) : ( ) : (
<Controller <Controller

View File

@ -9,7 +9,12 @@ export async function getAllUserLevels(data: any) {
const headers = { const headers = {
"content-type": "application/json", "content-type": "application/json",
}; };
return await httpGet(`user-levels?limit=${data.limit || ""}`, headers); return await httpGet(
`user-levels?limit=${data.limit || ""}&levelNumber=${
data?.levelNumber || ""
}`,
headers
);
} }
export async function getUserLevels(id: string) { export async function getUserLevels(id: string) {
const headers = { const headers = {