fix:select polres category autoselect polda
This commit is contained in:
parent
962b9708bf
commit
45350a7132
|
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -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[]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -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[]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue