fix:select polres category autoselect polda

This commit is contained in:
Rama Priyanto 2026-01-20 14:23:38 +07:00
parent 962b9708bf
commit 45350a7132
4 changed files with 97 additions and 25 deletions

View File

@ -138,7 +138,7 @@ export default function MasterCategoryTable() {
console.log(); console.log();
if ( if (
response.message?.messages[0]?.includes( response.message?.messages[0]?.includes(
"article_categories_title_unique" "article_categories_title_unique",
) )
) { ) {
error("Judul sudah tersedia, silahkan buat dengan judul berbeda"); error("Judul sudah tersedia, silahkan buat dengan judul berbeda");
@ -222,6 +222,7 @@ export default function MasterCategoryTable() {
"border-1 rounded-lg", "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",
], ],
input: "outline-none",
}} }}
variant="bordered" variant="bordered"
/> />
@ -253,6 +254,7 @@ export default function MasterCategoryTable() {
"border-1 rounded-lg", "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",
], ],
input: "outline-none",
}} }}
variant="bordered" variant="bordered"
/> />
@ -314,7 +316,7 @@ export default function MasterCategoryTable() {
className="" className=""
onClose={() => { onClose={() => {
const filteredTags = value.filter( const filteredTags = value.filter(
(tag) => tag !== item (tag) => tag !== item,
); );
if (filteredTags.length === 0) { if (filteredTags.length === 0) {
setError("tags", { setError("tags", {
@ -325,7 +327,7 @@ export default function MasterCategoryTable() {
clearErrors("tags"); clearErrors("tags");
setValue( setValue(
"tags", "tags",
filteredTags as [string, ...string[]] filteredTags as [string, ...string[]],
); );
} }
}} }}
@ -349,8 +351,9 @@ export default function MasterCategoryTable() {
classNames={{ classNames={{
inputWrapper: [ inputWrapper: [
"border-1 rounded-lg", "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" variant="bordered"
/> />

View File

@ -74,7 +74,7 @@ const CustomEditor = dynamic(
() => { () => {
return import("@/components/editor/custom-editor"); return import("@/components/editor/custom-editor");
}, },
{ ssr: false } { ssr: false },
); );
interface FileWithPreview extends File { interface FileWithPreview extends File {
@ -85,11 +85,13 @@ interface CategoryType {
id: number; id: number;
label: string; label: string;
value: number; value: number;
parentId: number;
} }
const categorySchema = z.object({ const categorySchema = z.object({
id: z.number(), id: z.number(),
label: z.string(), label: z.string(),
value: z.number(), value: z.number(),
parentId: z.number(),
}); });
interface DiseData { interface DiseData {
@ -150,7 +152,7 @@ export default function CreateArticleForm() {
const [thumbnailDocumentImg, setThumbnailDocumentImg] = useState<File[]>([]); const [thumbnailDocumentImg, setThumbnailDocumentImg] = useState<File[]>([]);
const [documentFiles, setDocumentFiles] = useState<File[]>([]); const [documentFiles, setDocumentFiles] = useState<File[]>([]);
const [selectedMainImage, setSelectedMainImage] = useState<number | null>( const [selectedMainImage, setSelectedMainImage] = useState<number | null>(
null null,
); );
const [thumbnailValidation, setThumbnailValidation] = useState(""); const [thumbnailValidation, setThumbnailValidation] = useState("");
const [thumbnailDocumentValidation, setThumbnailDocumentValidation] = const [thumbnailDocumentValidation, setThumbnailDocumentValidation] =
@ -160,7 +162,7 @@ export default function CreateArticleForm() {
const [diseData, setDiseData] = useState<DiseData>(); const [diseData, setDiseData] = useState<DiseData>();
const [selectedWritingType, setSelectedWritingType] = useState("single"); const [selectedWritingType, setSelectedWritingType] = useState("single");
const [status, setStatus] = useState<"publish" | "draft" | "scheduled">( const [status, setStatus] = useState<"publish" | "draft" | "scheduled">(
"publish" "publish",
); );
const [isScheduled, setIsScheduled] = useState(false); const [isScheduled, setIsScheduled] = useState(false);
const [timeValue, setTimeValue] = useState(""); const [timeValue, setTimeValue] = useState("");
@ -235,6 +237,7 @@ export default function CreateArticleForm() {
id: element.id, id: element.id,
label: element.title, label: element.title,
value: element.id, value: element.id,
parentId: element.parentId,
}); });
} }
setListCategory(temp); setListCategory(temp);
@ -303,7 +306,7 @@ export default function CreateArticleForm() {
} }
const saveArticleToDise = async ( const saveArticleToDise = async (
values: z.infer<typeof createArticleSchema> values: z.infer<typeof createArticleSchema>,
) => { ) => {
if (useAi) { if (useAi) {
const request = { const request = {
@ -576,7 +579,7 @@ export default function CreateArticleForm() {
const handleFileChange = ( const handleFileChange = (
event: React.ChangeEvent<HTMLInputElement>, event: React.ChangeEvent<HTMLInputElement>,
type: string type: string,
) => { ) => {
const selectedFiles = event.target.files; const selectedFiles = event.target.files;
if (selectedFiles) { if (selectedFiles) {
@ -611,6 +614,28 @@ export default function CreateArticleForm() {
// setValue("tags", uniqueArray as [string, ...string[]]); // 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 ( return (
<form <form
className="flex flex-col lg:flex-row gap-8 text-black" className="flex flex-col lg:flex-row gap-8 text-black"
@ -710,7 +735,7 @@ export default function CreateArticleForm() {
setDiseData(data); setDiseData(data);
setValue( setValue(
"description", "description",
data?.articleBody ? data?.articleBody : "" data?.articleBody ? data?.articleBody : "",
); );
}} }}
/> />
@ -720,7 +745,7 @@ export default function CreateArticleForm() {
setDiseData(data); setDiseData(data);
setValue( setValue(
"description", "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", "!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
}} }}
classNamePrefix="select" classNamePrefix="select"
onChange={onChange} onChange={(selectedOptions) => {
const fixed = ensureParentSelected(
(selectedOptions as any[]) ?? [],
listCategory,
);
console.log("fixed", fixed);
onChange(fixed);
}}
closeMenuOnSelect={false} closeMenuOnSelect={false}
components={animatedComponents} components={animatedComponents}
isClearable={true} isClearable={true}
@ -926,6 +960,7 @@ export default function CreateArticleForm() {
placeholder="Kategori..." placeholder="Kategori..."
name="sub-module" name="sub-module"
options={listCategory} options={listCategory}
value={value}
/> />
)} )}
/> />
@ -956,7 +991,7 @@ export default function CreateArticleForm() {
className="" className=""
onClose={() => { onClose={() => {
const filteredTags = value.filter( const filteredTags = value.filter(
(tag) => tag !== item (tag) => tag !== item,
); );
if (filteredTags.length === 0) { if (filteredTags.length === 0) {
setError("tags", { setError("tags", {
@ -967,7 +1002,7 @@ export default function CreateArticleForm() {
clearErrors("tags"); clearErrors("tags");
setValue( setValue(
"tags", "tags",
filteredTags as [string, ...string[]] filteredTags as [string, ...string[]],
); );
} }
}} }}

View File

@ -64,13 +64,13 @@ const ViewEditor = dynamic(
() => { () => {
return import("@/components/editor/view-editor"); return import("@/components/editor/view-editor");
}, },
{ ssr: false } { ssr: false },
); );
const CustomEditor = dynamic( const CustomEditor = dynamic(
() => { () => {
return import("@/components/editor/custom-editor"); return import("@/components/editor/custom-editor");
}, },
{ ssr: false } { ssr: false },
); );
interface FileWithPreview extends File { interface FileWithPreview extends File {
@ -81,11 +81,13 @@ interface CategoryType {
id: number; id: number;
label: string; label: string;
value: number; value: number;
parentId: number;
} }
const categorySchema = z.object({ const categorySchema = z.object({
id: z.number(), id: z.number(),
label: z.string(), label: z.string(),
value: z.number(), value: z.number(),
parentId: z.number(),
}); });
const createArticleSchema = z.object({ const createArticleSchema = z.object({
@ -153,7 +155,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
const [diseId, setDiseId] = useState(0); const [diseId, setDiseId] = useState(0);
const [thumbnailImg, setThumbnailImg] = useState<File[]>([]); const [thumbnailImg, setThumbnailImg] = useState<File[]>([]);
const [selectedMainImage, setSelectedMainImage] = useState<number | null>( const [selectedMainImage, setSelectedMainImage] = useState<number | null>(
null null,
); );
const [thumbnailValidation, setThumbnailValidation] = useState(""); const [thumbnailValidation, setThumbnailValidation] = useState("");
const { isOpen, onOpen, onOpenChange } = useDisclosure(); const { isOpen, onOpen, onOpenChange } = useDisclosure();
@ -271,6 +273,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
id: element.id, id: element.id,
label: element.title, label: element.title,
value: element.id, value: element.id,
parentId: element.parentId,
}); });
} }
setListCategory(temp); setListCategory(temp);
@ -601,6 +604,28 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
router.push("/admin/article"); 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 ( return (
<form <form
className="flex flex-col lg:flex-row gap-8 text-black" className="flex flex-col lg:flex-row gap-8 text-black"
@ -792,7 +817,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
{Math.round(file?.size / 100) / 10 > 1000 ? ( {Math.round(file?.size / 100) / 10 > 1000 ? (
<> <>
{(Math.round(file?.size / 100) / 10000).toFixed( {(Math.round(file?.size / 100) / 10000).toFixed(
1 1,
)} )}
</> </>
) : ( ) : (
@ -1007,7 +1032,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
}} }}
classNamePrefix="select" classNamePrefix="select"
value={value} value={value}
onChange={onChange} onChange={(selectedOptions) => {
const fixed = ensureParentSelected(
(selectedOptions as any[]) ?? [],
listCategory,
);
onChange(fixed);
}}
closeMenuOnSelect={false} closeMenuOnSelect={false}
components={animatedComponents} components={animatedComponents}
isClearable={true} isClearable={true}
@ -1048,7 +1079,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
className="" className=""
onClose={() => { onClose={() => {
const filteredTags = value.filter( const filteredTags = value.filter(
(tag) => tag !== item (tag) => tag !== item,
); );
if (filteredTags.length === 0) { if (filteredTags.length === 0) {
setError("tags", { setError("tags", {
@ -1059,7 +1090,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
clearErrors("tags"); clearErrors("tags");
setValue( setValue(
"tags", "tags",
filteredTags as [string, ...string[]] filteredTags as [string, ...string[]],
); );
} }
}} }}

View File

@ -320,7 +320,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
return cellValue; return cellValue;
} }
}, },
[listCategory] [listCategory],
); );
let typingTimer: NodeJS.Timeout; let typingTimer: NodeJS.Timeout;
@ -397,7 +397,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
aria-label="Search" aria-label="Search"
classNames={{ classNames={{
inputWrapper: "bg-default-100", inputWrapper: "bg-default-100",
input: "text-sm", input: "text-sm outline-none",
}} }}
labelPlacement="outside" labelPlacement="outside"
startContent={ startContent={
@ -511,6 +511,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
"border-1 rounded-lg", "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",
], ],
input: "outline-none",
}} }}
variant="bordered" variant="bordered"
/> />
@ -543,6 +544,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
"border-1 rounded-lg", "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",
], ],
input: "outline-none",
}} }}
variant="bordered" variant="bordered"
/> />
@ -600,7 +602,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
className="" className=""
onClose={() => { onClose={() => {
const filteredTags = value.filter( const filteredTags = value.filter(
(tag) => tag !== item (tag) => tag !== item,
); );
if (filteredTags.length === 0) { if (filteredTags.length === 0) {
setError("tags", { setError("tags", {
@ -611,7 +613,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
clearErrors("tags"); clearErrors("tags");
setValue( setValue(
"tags", "tags",
filteredTags as [string, ...string[]] filteredTags as [string, ...string[]],
); );
} }
}} }}
@ -637,6 +639,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
"border-1 rounded-lg", "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",
], ],
input: "outline-none",
}} }}
variant="bordered" variant="bordered"
/> />