From 45350a7132f8a949e5ad8a7ece933146850b1ced Mon Sep 17 00:00:00 2001 From: Rama Priyanto Date: Tue, 20 Jan 2026 14:23:38 +0700 Subject: [PATCH] fix:select polres category autoselect polda --- app/(admin)/admin/master-category/page.tsx | 11 ++-- .../form/article/create-article-form.tsx | 55 +++++++++++++++---- components/form/article/edit-article-form.tsx | 45 ++++++++++++--- .../master-categories/categories-table.tsx | 11 ++-- 4 files changed, 97 insertions(+), 25 deletions(-) diff --git a/app/(admin)/admin/master-category/page.tsx b/app/(admin)/admin/master-category/page.tsx index 8ca8eb8..aeadde9 100644 --- a/app/(admin)/admin/master-category/page.tsx +++ b/app/(admin)/admin/master-category/page.tsx @@ -138,7 +138,7 @@ export default function MasterCategoryTable() { console.log(); if ( response.message?.messages[0]?.includes( - "article_categories_title_unique" + "article_categories_title_unique", ) ) { error("Judul sudah tersedia, silahkan buat dengan judul berbeda"); @@ -222,6 +222,7 @@ export default function MasterCategoryTable() { "border-1 rounded-lg", "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", ], + input: "outline-none", }} variant="bordered" /> @@ -253,6 +254,7 @@ export default function MasterCategoryTable() { "border-1 rounded-lg", "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", ], + input: "outline-none", }} variant="bordered" /> @@ -314,7 +316,7 @@ export default function MasterCategoryTable() { className="" onClose={() => { const filteredTags = value.filter( - (tag) => tag !== item + (tag) => tag !== item, ); if (filteredTags.length === 0) { setError("tags", { @@ -325,7 +327,7 @@ export default function MasterCategoryTable() { clearErrors("tags"); setValue( "tags", - filteredTags as [string, ...string[]] + filteredTags as [string, ...string[]], ); } }} @@ -349,8 +351,9 @@ export default function MasterCategoryTable() { classNames={{ inputWrapper: [ "border-1 rounded-lg", - "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", + "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400 outline-none", ], + input: "outline-none", }} variant="bordered" /> diff --git a/components/form/article/create-article-form.tsx b/components/form/article/create-article-form.tsx index 671583a..2853e7d 100644 --- a/components/form/article/create-article-form.tsx +++ b/components/form/article/create-article-form.tsx @@ -74,7 +74,7 @@ const CustomEditor = dynamic( () => { return import("@/components/editor/custom-editor"); }, - { ssr: false } + { ssr: false }, ); interface FileWithPreview extends File { @@ -85,11 +85,13 @@ interface CategoryType { id: number; label: string; value: number; + parentId: number; } const categorySchema = z.object({ id: z.number(), label: z.string(), value: z.number(), + parentId: z.number(), }); interface DiseData { @@ -150,7 +152,7 @@ export default function CreateArticleForm() { const [thumbnailDocumentImg, setThumbnailDocumentImg] = useState([]); const [documentFiles, setDocumentFiles] = useState([]); const [selectedMainImage, setSelectedMainImage] = useState( - null + null, ); const [thumbnailValidation, setThumbnailValidation] = useState(""); const [thumbnailDocumentValidation, setThumbnailDocumentValidation] = @@ -160,7 +162,7 @@ export default function CreateArticleForm() { const [diseData, setDiseData] = useState(); const [selectedWritingType, setSelectedWritingType] = useState("single"); const [status, setStatus] = useState<"publish" | "draft" | "scheduled">( - "publish" + "publish", ); const [isScheduled, setIsScheduled] = useState(false); const [timeValue, setTimeValue] = useState(""); @@ -235,6 +237,7 @@ export default function CreateArticleForm() { id: element.id, label: element.title, value: element.id, + parentId: element.parentId, }); } setListCategory(temp); @@ -303,7 +306,7 @@ export default function CreateArticleForm() { } const saveArticleToDise = async ( - values: z.infer + values: z.infer, ) => { if (useAi) { const request = { @@ -576,7 +579,7 @@ export default function CreateArticleForm() { const handleFileChange = ( event: React.ChangeEvent, - type: string + type: string, ) => { const selectedFiles = event.target.files; if (selectedFiles) { @@ -611,6 +614,28 @@ export default function CreateArticleForm() { // setValue("tags", uniqueArray as [string, ...string[]]); // }; + const ensureParentSelected = (selected: any[], allOptions: any[]) => { + if (!selected || selected.length === 0) return []; + + const mapByValue = new Map(allOptions.map((o) => [o.value, o])); + + const result = [...selected]; + + for (const item of selected) { + if (item?.parentId) { + const parent = mapByValue.get(item.parentId); + if (parent) { + const alreadySelected = result.some((x) => x.value === parent.value); + if (!alreadySelected) { + result.push(parent); + } + } + } + } + + return result; + }; + return (
@@ -720,7 +745,7 @@ export default function CreateArticleForm() { setDiseData(data); setValue( "description", - data?.articleBody ? data?.articleBody : "" + data?.articleBody ? data?.articleBody : "", ); }} /> @@ -917,7 +942,16 @@ export default function CreateArticleForm() { "!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500", }} classNamePrefix="select" - onChange={onChange} + onChange={(selectedOptions) => { + const fixed = ensureParentSelected( + (selectedOptions as any[]) ?? [], + listCategory, + ); + + console.log("fixed", fixed); + + onChange(fixed); + }} closeMenuOnSelect={false} components={animatedComponents} isClearable={true} @@ -926,6 +960,7 @@ export default function CreateArticleForm() { placeholder="Kategori..." name="sub-module" options={listCategory} + value={value} /> )} /> @@ -956,7 +991,7 @@ export default function CreateArticleForm() { className="" onClose={() => { const filteredTags = value.filter( - (tag) => tag !== item + (tag) => tag !== item, ); if (filteredTags.length === 0) { setError("tags", { @@ -967,7 +1002,7 @@ export default function CreateArticleForm() { clearErrors("tags"); setValue( "tags", - filteredTags as [string, ...string[]] + filteredTags as [string, ...string[]], ); } }} diff --git a/components/form/article/edit-article-form.tsx b/components/form/article/edit-article-form.tsx index 9b57e3a..af334cc 100644 --- a/components/form/article/edit-article-form.tsx +++ b/components/form/article/edit-article-form.tsx @@ -64,13 +64,13 @@ const ViewEditor = dynamic( () => { return import("@/components/editor/view-editor"); }, - { ssr: false } + { ssr: false }, ); const CustomEditor = dynamic( () => { return import("@/components/editor/custom-editor"); }, - { ssr: false } + { ssr: false }, ); interface FileWithPreview extends File { @@ -81,11 +81,13 @@ interface CategoryType { id: number; label: string; value: number; + parentId: number; } const categorySchema = z.object({ id: z.number(), label: z.string(), value: z.number(), + parentId: z.number(), }); const createArticleSchema = z.object({ @@ -153,7 +155,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const [diseId, setDiseId] = useState(0); const [thumbnailImg, setThumbnailImg] = useState([]); const [selectedMainImage, setSelectedMainImage] = useState( - null + null, ); const [thumbnailValidation, setThumbnailValidation] = useState(""); const { isOpen, onOpen, onOpenChange } = useDisclosure(); @@ -271,6 +273,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { id: element.id, label: element.title, value: element.id, + parentId: element.parentId, }); } setListCategory(temp); @@ -601,6 +604,28 @@ export default function EditArticleForm(props: { isDetail: boolean }) { router.push("/admin/article"); } + const ensureParentSelected = (selected: any[], allOptions: any[]) => { + if (!selected || selected.length === 0) return []; + + const mapByValue = new Map(allOptions.map((o) => [o.value, o])); + + const result = [...selected]; + + for (const item of selected) { + if (item?.parentId) { + const parent = mapByValue.get(item.parentId); + if (parent) { + const alreadySelected = result.some((x) => x.value === parent.value); + if (!alreadySelected) { + result.push(parent); + } + } + } + } + + return result; + }; + return ( 1000 ? ( <> {(Math.round(file?.size / 100) / 10000).toFixed( - 1 + 1, )} ) : ( @@ -1007,7 +1032,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) { }} classNamePrefix="select" value={value} - onChange={onChange} + onChange={(selectedOptions) => { + const fixed = ensureParentSelected( + (selectedOptions as any[]) ?? [], + listCategory, + ); + onChange(fixed); + }} closeMenuOnSelect={false} components={animatedComponents} isClearable={true} @@ -1048,7 +1079,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { className="" onClose={() => { const filteredTags = value.filter( - (tag) => tag !== item + (tag) => tag !== item, ); if (filteredTags.length === 0) { setError("tags", { @@ -1059,7 +1090,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { clearErrors("tags"); setValue( "tags", - filteredTags as [string, ...string[]] + filteredTags as [string, ...string[]], ); } }} diff --git a/components/table/master-categories/categories-table.tsx b/components/table/master-categories/categories-table.tsx index 06923fe..352f818 100644 --- a/components/table/master-categories/categories-table.tsx +++ b/components/table/master-categories/categories-table.tsx @@ -320,7 +320,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { return cellValue; } }, - [listCategory] + [listCategory], ); let typingTimer: NodeJS.Timeout; @@ -397,7 +397,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { aria-label="Search" classNames={{ inputWrapper: "bg-default-100", - input: "text-sm", + input: "text-sm outline-none", }} labelPlacement="outside" startContent={ @@ -511,6 +511,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { "border-1 rounded-lg", "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", ], + input: "outline-none", }} variant="bordered" /> @@ -543,6 +544,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { "border-1 rounded-lg", "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", ], + input: "outline-none", }} variant="bordered" /> @@ -600,7 +602,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { className="" onClose={() => { const filteredTags = value.filter( - (tag) => tag !== item + (tag) => tag !== item, ); if (filteredTags.length === 0) { setError("tags", { @@ -611,7 +613,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { clearErrors("tags"); setValue( "tags", - filteredTags as [string, ...string[]] + filteredTags as [string, ...string[]], ); } }} @@ -637,6 +639,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) { "border-1 rounded-lg", "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", ], + input: "outline-none", }} variant="bordered" />