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();
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"
/>

View File

@ -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<File[]>([]);
const [documentFiles, setDocumentFiles] = useState<File[]>([]);
const [selectedMainImage, setSelectedMainImage] = useState<number | null>(
null
null,
);
const [thumbnailValidation, setThumbnailValidation] = useState("");
const [thumbnailDocumentValidation, setThumbnailDocumentValidation] =
@ -160,7 +162,7 @@ export default function CreateArticleForm() {
const [diseData, setDiseData] = useState<DiseData>();
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<typeof createArticleSchema>
values: z.infer<typeof createArticleSchema>,
) => {
if (useAi) {
const request = {
@ -576,7 +579,7 @@ export default function CreateArticleForm() {
const handleFileChange = (
event: React.ChangeEvent<HTMLInputElement>,
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 (
<form
className="flex flex-col lg:flex-row gap-8 text-black"
@ -710,7 +735,7 @@ export default function CreateArticleForm() {
setDiseData(data);
setValue(
"description",
data?.articleBody ? data?.articleBody : ""
data?.articleBody ? data?.articleBody : "",
);
}}
/>
@ -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[]],
);
}
}}

View File

@ -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<File[]>([]);
const [selectedMainImage, setSelectedMainImage] = useState<number | null>(
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 (
<form
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) / 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[]],
);
}
}}

View File

@ -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"
/>