Merge branch 'dev-sabda-v2' of https://gitlab.com/hanifsalafi/mediahub_redesign
This commit is contained in:
commit
803960cf62
|
|
@ -74,7 +74,7 @@ const TaskTable = () => {
|
|||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [showData, setShowData] = React.useState("50");
|
||||
const [showData, setShowData] = React.useState("10");
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: Number(showData),
|
||||
|
|
@ -206,7 +206,7 @@ const TaskTable = () => {
|
|||
<span
|
||||
className={` ${
|
||||
isSpecificAttention
|
||||
? "bg-default-900 text-white"
|
||||
? "bg-default-900 text-white dark:text-black"
|
||||
: "dark:text-default-700 border-2"
|
||||
}
|
||||
px-[18px] py-1 transition duration-100 rounded`}
|
||||
|
|
@ -217,7 +217,7 @@ const TaskTable = () => {
|
|||
className={`
|
||||
${
|
||||
!isSpecificAttention
|
||||
? "bg-default-900 text-white"
|
||||
? "bg-default-900 text-white dark:text-black"
|
||||
: " dark:text-default-700 border-2"
|
||||
}
|
||||
px-[18px] py-1 transition duration-100 rounded
|
||||
|
|
|
|||
|
|
@ -106,12 +106,10 @@ interface FileWithPreview extends File {
|
|||
export default function FormImageUpdate() {
|
||||
const MySwal = withReactContent(Swal);
|
||||
const router = useRouter();
|
||||
|
||||
const { id } = useParams() as { id: string };
|
||||
console.log(id);
|
||||
const editor = useRef(null);
|
||||
type ImageSchema = z.infer<typeof imageSchema>;
|
||||
|
||||
let progressInfo: any = [];
|
||||
let counterUpdateProgress = 0;
|
||||
const [progressList, setProgressList] = useState<any>([]);
|
||||
|
|
@ -123,7 +121,6 @@ export default function FormImageUpdate() {
|
|||
const taskId = Cookies.get("taskId");
|
||||
const scheduleId = Cookies.get("scheduleId");
|
||||
const scheduleType = Cookies.get("scheduleType");
|
||||
|
||||
const [categories, setCategories] = useState<Category[]>([]);
|
||||
const [selectedCategory, setSelectedCategory] = useState<any>();
|
||||
const [tags, setTags] = useState<any[]>([]);
|
||||
|
|
@ -134,11 +131,19 @@ export default function FormImageUpdate() {
|
|||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||
const [filesTemp, setFilesTemp] = useState<File[]>([]);
|
||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||
const [thumbnailFile, setThumbnailFile] = useState<File | null>(null);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [selectedOptions, setSelectedOptions] = useState<{
|
||||
[fileId: number]: string[];
|
||||
}>({});
|
||||
|
||||
const handleThumbnailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (file) {
|
||||
setThumbnailFile(file);
|
||||
}
|
||||
};
|
||||
|
||||
const options: Option[] = [
|
||||
{ id: "all", name: "SEMUA" },
|
||||
{ id: "5", name: "UMUM" },
|
||||
|
|
@ -177,35 +182,6 @@ export default function FormImageUpdate() {
|
|||
resolver: zodResolver(imageSchema),
|
||||
});
|
||||
|
||||
// const handleKeyDown = (e: any) => {
|
||||
// const newTag = e.target.value.trim(); // Ambil nilai input
|
||||
// if (e.key === "Enter" && newTag) {
|
||||
// e.preventDefault(); // Hentikan submit form
|
||||
// if (!tags.includes(newTag)) {
|
||||
// setTags((prevTags) => [...prevTags, newTag]); // Tambah tag baru
|
||||
// setValue("tags", ""); // Kosongkan input
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
const handleImageChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.files) {
|
||||
const files = Array.from(event.target.files);
|
||||
setSelectedFiles((prevImages: any) => [...prevImages, ...files]);
|
||||
console.log("DATAFILE::", selectedFiles);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveImage = (index: number) => {
|
||||
setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index));
|
||||
};
|
||||
|
||||
// const handleCheckboxChange = (id: number) => {
|
||||
// setSelectedPublishers((prev) =>
|
||||
// prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
|
||||
// );
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
async function initState() {
|
||||
getCategories();
|
||||
|
|
@ -219,9 +195,9 @@ export default function FormImageUpdate() {
|
|||
e.preventDefault();
|
||||
const newTag = e.currentTarget.value.trim();
|
||||
if (!tags.includes(newTag)) {
|
||||
setTags((prevTags) => [...prevTags, newTag]); // Tambahkan tag baru
|
||||
setTags((prevTags) => [...prevTags, newTag]);
|
||||
if (inputRef.current) {
|
||||
inputRef.current.value = ""; // Kosongkan input
|
||||
inputRef.current.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -252,7 +228,7 @@ export default function FormImageUpdate() {
|
|||
|
||||
if (findCategory) {
|
||||
// setValue("categoryId", findCategory.id);
|
||||
setSelectedCategory(findCategory.id); // Set the selected category
|
||||
setSelectedCategory(findCategory.id);
|
||||
const response = await getTagsBySubCategoryId(findCategory.id);
|
||||
setTags(response?.data?.data);
|
||||
}
|
||||
|
|
@ -269,16 +245,13 @@ export default function FormImageUpdate() {
|
|||
const details = response?.data?.data;
|
||||
|
||||
setDetail(details);
|
||||
|
||||
// Set the selected target to the category ID from details
|
||||
|
||||
setSelectedTarget(String(details.category.id));
|
||||
|
||||
// Set form values immediately and then again after a delay to ensure editor is ready
|
||||
setValue("title", details.title);
|
||||
setValue("description", details.htmlDescription);
|
||||
setValue("creatorName", details.creatorName);
|
||||
|
||||
// Set again after delay to ensure editor has loaded
|
||||
setTimeout(() => {
|
||||
setValue("title", details.title);
|
||||
setValue("description", details.htmlDescription);
|
||||
|
|
@ -308,7 +281,7 @@ export default function FormImageUpdate() {
|
|||
}
|
||||
}
|
||||
initState();
|
||||
}, [id, setValue]); // Remove refresh dependency and add id
|
||||
}, [id, setValue]);
|
||||
|
||||
const mapPlacementsToOptions = (placements: string): string[] => {
|
||||
const mapping: Record<string, string> = {
|
||||
|
|
@ -318,7 +291,6 @@ export default function FormImageUpdate() {
|
|||
polres: "internasional",
|
||||
};
|
||||
|
||||
// Jika placements hanya "all", langsung aktifkan semua checkbox
|
||||
if (placements.trim() === "all") {
|
||||
return ["all", "nasional", "wilayah", "internasional"];
|
||||
}
|
||||
|
|
@ -337,7 +309,6 @@ export default function FormImageUpdate() {
|
|||
|
||||
const handleCheckboxChange = (id: string) => {
|
||||
if (id === "all") {
|
||||
// Select all options except "all"
|
||||
const allOptions = options
|
||||
.filter((opt) => opt.id !== "all")
|
||||
.map((opt) => opt.id);
|
||||
|
|
@ -345,7 +316,6 @@ export default function FormImageUpdate() {
|
|||
publishedFor.length === allOptions.length ? [] : allOptions
|
||||
);
|
||||
} else {
|
||||
// Toggle individual option
|
||||
setPublishedFor((prev) =>
|
||||
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
|
||||
);
|
||||
|
|
@ -381,9 +351,11 @@ export default function FormImageUpdate() {
|
|||
}
|
||||
|
||||
const formMedia = new FormData();
|
||||
const thumbnail = files[0];
|
||||
const thumbnail = thumbnailFile || files[0];
|
||||
formMedia.append("file", thumbnail);
|
||||
|
||||
const responseThumbnail = await uploadThumbnail(id, formMedia);
|
||||
|
||||
if (responseThumbnail?.error == true) {
|
||||
error(responseThumbnail?.message);
|
||||
return false;
|
||||
|
|
@ -449,7 +421,7 @@ export default function FormImageUpdate() {
|
|||
filename: file.name,
|
||||
filetype: file.type,
|
||||
duration,
|
||||
isWatermark: "true", // hardcode
|
||||
isWatermark: "true",
|
||||
},
|
||||
onBeforeRequest: function (req) {
|
||||
var xhr = req.getUnderlyingObject();
|
||||
|
|
@ -555,7 +527,7 @@ export default function FormImageUpdate() {
|
|||
|
||||
const fileList = files.map((file: any) => (
|
||||
<div
|
||||
key={file.id} // Gunakan ID file sebagai key
|
||||
key={file.id}
|
||||
className="flex justify-between border px-3.5 py-3 my-6 rounded-md"
|
||||
>
|
||||
<div className="flex gap-3 items-center">
|
||||
|
|
@ -580,7 +552,7 @@ export default function FormImageUpdate() {
|
|||
color="destructive"
|
||||
variant="outline"
|
||||
className="border-none rounded-full"
|
||||
onClick={() => handleDeleteFile(file.id)} // Kirim ID spesifik
|
||||
onClick={() => handleDeleteFile(file.id)}
|
||||
>
|
||||
<Icon icon="tabler:x" className="h-5 w-5" />
|
||||
</Button>
|
||||
|
|
@ -591,21 +563,18 @@ export default function FormImageUpdate() {
|
|||
setSelectedOptions((prev: any) => {
|
||||
const currentSelections = prev[fileId] || [];
|
||||
if (value === "all") {
|
||||
// If "all" is clicked, toggle all options
|
||||
if (currentSelections.includes("all")) {
|
||||
return { ...prev, [fileId]: [] }; // Deselect all
|
||||
return { ...prev, [fileId]: [] };
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
[fileId]: ["all", "nasional", "wilayah", "internasional"],
|
||||
}; // Select all
|
||||
};
|
||||
} else {
|
||||
// If any other checkbox is clicked, toggle that checkbox
|
||||
const updatedSelections = currentSelections.includes(value)
|
||||
? currentSelections.filter((option: any) => option !== value)
|
||||
: [...currentSelections, value];
|
||||
|
||||
// If all individual options are selected, include "all" automatically
|
||||
const isAllSelected = ["nasional", "wilayah", "internasional"].every(
|
||||
(opt) => updatedSelections.includes(opt)
|
||||
);
|
||||
|
|
@ -672,7 +641,9 @@ export default function FormImageUpdate() {
|
|||
<div className="flex flex-col lg:flex-row gap-10">
|
||||
<Card className="w-full lg:w-8/12">
|
||||
<div className="px-6 py-6">
|
||||
<p className="text-lg font-semibold mb-3">{t("form-image", { defaultValue: "Form Image" })}</p>
|
||||
<p className="text-lg font-semibold mb-3">
|
||||
{t("form-image", { defaultValue: "Form Image" })}
|
||||
</p>
|
||||
<div className="gap-5 mb-5">
|
||||
{/* Input Title */}
|
||||
<div className="space-y-2 py-3">
|
||||
|
|
@ -711,14 +682,18 @@ export default function FormImageUpdate() {
|
|||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{/* Show the category from details if it doesn't exist in categories list */}
|
||||
{detail && !categories.find(cat => String(cat.id) === String(detail.category.id)) && (
|
||||
<SelectItem
|
||||
key={String(detail.category.id)}
|
||||
value={String(detail.category.id)}
|
||||
>
|
||||
{detail.category.name}
|
||||
</SelectItem>
|
||||
)}
|
||||
{detail &&
|
||||
!categories.find(
|
||||
(cat) =>
|
||||
String(cat.id) === String(detail.category.id)
|
||||
) && (
|
||||
<SelectItem
|
||||
key={String(detail.category.id)}
|
||||
value={String(detail.category.id)}
|
||||
>
|
||||
{detail.category.name}
|
||||
</SelectItem>
|
||||
)}
|
||||
{categories.map((category) => (
|
||||
<SelectItem
|
||||
key={String(category.id)}
|
||||
|
|
@ -733,12 +708,17 @@ export default function FormImageUpdate() {
|
|||
</div>
|
||||
|
||||
<div className="py-3 space-y-2">
|
||||
<Label>{t("description", { defaultValue: "Description" })}</Label>
|
||||
<Label>
|
||||
{t("description", { defaultValue: "Description" })}
|
||||
</Label>
|
||||
<Controller
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field }) => (
|
||||
<CustomEditor onChange={field.onChange} initialData={field.value} />
|
||||
<CustomEditor
|
||||
onChange={field.onChange}
|
||||
initialData={field.value}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.description?.message && (
|
||||
|
|
@ -748,7 +728,9 @@ export default function FormImageUpdate() {
|
|||
)}
|
||||
</div>
|
||||
<div className="py-3 space-y-2">
|
||||
<Label>{t("select-file", { defaultValue: "Select File" })}</Label>
|
||||
<Label>
|
||||
{t("select-file", { defaultValue: "Select File" })}
|
||||
</Label>
|
||||
{/* <Input
|
||||
id="fileInput"
|
||||
type="file"
|
||||
|
|
@ -764,7 +746,9 @@ export default function FormImageUpdate() {
|
|||
{t("drag-file", { defaultValue: "Drag File" })}
|
||||
</h4>
|
||||
<div className=" text-xs text-muted-foreground">
|
||||
{t("upload-file-max", { defaultValue: "Upload File Max" })}
|
||||
{t("upload-file-max", {
|
||||
defaultValue: "Upload File Max",
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -773,7 +757,9 @@ export default function FormImageUpdate() {
|
|||
<div>{fileList}</div>
|
||||
<div className=" flex justify-between gap-2">
|
||||
<div className="flex flex-row items-center gap-3 py-3">
|
||||
<Label>{t("watermark", { defaultValue: "Watermark" })}</Label>
|
||||
<Label>
|
||||
{t("watermark", { defaultValue: "Watermark" })}
|
||||
</Label>
|
||||
<div className="flex items-center gap-3">
|
||||
<Switch defaultChecked color="primary" id="c2" />
|
||||
</div>
|
||||
|
|
@ -813,7 +799,9 @@ export default function FormImageUpdate() {
|
|||
rel="noopener noreferrer"
|
||||
className="text-blue-500 text-sm"
|
||||
>
|
||||
{t("view-file", { defaultValue: "View File" })}
|
||||
{t("view-file", {
|
||||
defaultValue: "View File",
|
||||
})}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -831,7 +819,9 @@ export default function FormImageUpdate() {
|
|||
}
|
||||
className="form-checkbox"
|
||||
/>
|
||||
<span>{t("all", { defaultValue: "All" })}</span>
|
||||
<span>
|
||||
{t("all", { defaultValue: "All" })}
|
||||
</span>
|
||||
</Label>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -900,7 +890,7 @@ export default function FormImageUpdate() {
|
|||
</div>
|
||||
</Card>
|
||||
<div className="w-full lg:w-4/12">
|
||||
<Card className="h-[900px] md:h-[1100px] lg:h-[800px]">
|
||||
<Card className="h-[900px] md:h-[1100px] lg:h-fit">
|
||||
<div className="px-3 py-3">
|
||||
<div className="space-y-2">
|
||||
<Label>{t("creator", { defaultValue: "Creator" })}</Label>
|
||||
|
|
@ -924,7 +914,7 @@ export default function FormImageUpdate() {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 px-3 space-y-2">
|
||||
{/* <div className="mt-3 px-3 space-y-2">
|
||||
<Label>{t("preview", { defaultValue: "Preview" })}</Label>
|
||||
<Card className="mt-2">
|
||||
<img
|
||||
|
|
@ -933,7 +923,37 @@ export default function FormImageUpdate() {
|
|||
className="w-full h-auto rounded"
|
||||
/>
|
||||
</Card>
|
||||
</div> */}
|
||||
<div className="mt-3 px-3 space-y-2">
|
||||
<Label>{t("preview", { defaultValue: "Preview" })}</Label>
|
||||
|
||||
<Input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={(e) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (file) {
|
||||
setThumbnailFile(file);
|
||||
}
|
||||
}}
|
||||
className="dark:border dark:border-gray-500 dark:rounded-lg"
|
||||
/>
|
||||
|
||||
<Card className="mt-2">
|
||||
<img
|
||||
src={
|
||||
thumbnailFile
|
||||
? URL.createObjectURL(thumbnailFile)
|
||||
: detail?.thumbnailLink
|
||||
? `${detail.thumbnailLink}?v=${Date.now()}`
|
||||
: ""
|
||||
}
|
||||
alt="Thumbnail Preview"
|
||||
className="w-full h-auto rounded"
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="px-3 py-3">
|
||||
<div className="space-y-2">
|
||||
<Label>{t("tags", { defaultValue: "Tags" })}</Label>
|
||||
|
|
@ -981,7 +1001,9 @@ export default function FormImageUpdate() {
|
|||
</div>
|
||||
<div className="px-3 py-3">
|
||||
<div className="flex flex-col gap-6 space-y-2">
|
||||
<Label>{t("publish-target", { defaultValue: "Publish Target" })}</Label>
|
||||
<Label>
|
||||
{t("publish-target", { defaultValue: "Publish Target" })}
|
||||
</Label>
|
||||
{options.map((option: Option) => (
|
||||
<div key={option.id} className="flex gap-2 items-center">
|
||||
<Checkbox
|
||||
|
|
@ -1001,7 +1023,9 @@ export default function FormImageUpdate() {
|
|||
</div>
|
||||
<div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm">
|
||||
<MailIcon />
|
||||
<p className="">{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)</p>
|
||||
<p className="">
|
||||
{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)
|
||||
</p>
|
||||
</div>
|
||||
<div className="px-3 py-3">
|
||||
<p>{t("information", { defaultValue: "Information" })}:</p>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,17 @@ interface FileUploaded {
|
|||
url: string;
|
||||
}
|
||||
|
||||
interface Destination {
|
||||
id: string;
|
||||
name: string;
|
||||
subDestination?: SubDestination[];
|
||||
}
|
||||
|
||||
interface SubDestination {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
type Url = {
|
||||
id: number;
|
||||
attachmentUrl: string;
|
||||
|
|
@ -137,7 +148,7 @@ export default function FormTaskEdit() {
|
|||
const [detail, setDetail] = useState<taskDetail>();
|
||||
const [urlInputs, setUrlInputs] = useState<Url[]>([]);
|
||||
const [refresh] = useState(false);
|
||||
const [listDest, setListDest] = useState([]);
|
||||
const [listDest, setListDest] = useState<Destination[]>([]);
|
||||
const [checkedLevels, setCheckedLevels] = useState(new Set());
|
||||
const [expandedPolda, setExpandedPolda] = useState([{}]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
|
@ -177,6 +188,12 @@ export default function FormTaskEdit() {
|
|||
resolver: zodResolver(taskSchema),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (detail?.taskType) {
|
||||
setTaskType(detail.taskType.toString());
|
||||
}
|
||||
}, [detail]);
|
||||
|
||||
// const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// const selectedValue = Number(event.target.value);
|
||||
// setMainType(selectedValue);
|
||||
|
|
@ -425,7 +442,7 @@ export default function FormTaskEdit() {
|
|||
console.log("Form Data Submitted:", requestData);
|
||||
console.log("response", response);
|
||||
const id = response?.data?.data.id;
|
||||
loading();
|
||||
// loading();
|
||||
if (imageFiles?.length == 0) {
|
||||
setIsImageUploadFinish(true);
|
||||
}
|
||||
|
|
@ -471,6 +488,26 @@ export default function FormTaskEdit() {
|
|||
// });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const updated = new Set(checkedLevels);
|
||||
|
||||
if (unitSelection.polda) {
|
||||
listDest.forEach((polda) => {
|
||||
updated.add(polda.id); // hanya id polda
|
||||
});
|
||||
}
|
||||
|
||||
if (unitSelection.polres) {
|
||||
listDest.forEach((polda) => {
|
||||
polda?.subDestination?.forEach((polres: any) => {
|
||||
updated.add(polres.id); // hanya id polres
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setCheckedLevels(updated);
|
||||
}, [unitSelection.polda, unitSelection.polres, listDest]);
|
||||
|
||||
const onSubmit = (data: TaskSchema) => {
|
||||
MySwal.fire({
|
||||
title: "Simpan Data",
|
||||
|
|
@ -732,25 +769,29 @@ export default function FormTaskEdit() {
|
|||
</Select>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-3 mt-6 lg:pt-7 lg:ml-3">
|
||||
{Object.keys(unitSelection).map((key) => (
|
||||
<div className="flex items-center gap-2" key={key}>
|
||||
<Checkbox
|
||||
id={key}
|
||||
checked={
|
||||
unitSelection[key as keyof typeof unitSelection]
|
||||
}
|
||||
onCheckedChange={(value) =>
|
||||
handleUnitChange(
|
||||
key as keyof typeof unitSelection,
|
||||
value as boolean
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Label htmlFor={key}>
|
||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
{Object.keys(unitSelection).map((key) => {
|
||||
const isDisabled = key === "polres" && !unitSelection.polda;
|
||||
return (
|
||||
<div className="flex items-center gap-2" key={key}>
|
||||
<Checkbox
|
||||
id={key}
|
||||
checked={
|
||||
unitSelection[key as keyof typeof unitSelection]
|
||||
}
|
||||
disabled={isDisabled}
|
||||
onCheckedChange={(value) =>
|
||||
handleUnitChange(
|
||||
key as keyof typeof unitSelection,
|
||||
value as boolean
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Label htmlFor={key}>
|
||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
||||
</Label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mt-6 lg:pt-6 lg:pl-3">
|
||||
<Dialog>
|
||||
|
|
@ -766,71 +807,67 @@ export default function FormTaskEdit() {
|
|||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
|
||||
{listDest.map((polda: any) => (
|
||||
<div key={polda.id} className="border p-2">
|
||||
<Label className="flex items-center">
|
||||
<Checkbox
|
||||
checked={checkedLevels.has(polda.id)}
|
||||
onCheckedChange={() =>
|
||||
handleCheckboxChange(polda.id)
|
||||
}
|
||||
className="mr-3"
|
||||
/>
|
||||
{polda.name}
|
||||
<button
|
||||
onClick={() => toggleExpand(polda.id)}
|
||||
className="ml-2 focus:outline-none"
|
||||
>
|
||||
{expandedPolda[polda.id] ? (
|
||||
<ChevronUp size={16} />
|
||||
) : (
|
||||
<ChevronDown size={16} />
|
||||
)}
|
||||
</button>
|
||||
</Label>
|
||||
{expandedPolda[polda.id] && (
|
||||
<div className="ml-6 mt-2">
|
||||
<Label className="block">
|
||||
<Checkbox
|
||||
checked={polda?.subDestination?.every(
|
||||
(polres: any) =>
|
||||
checkedLevels.has(polres.id)
|
||||
)}
|
||||
onCheckedChange={(isChecked) => {
|
||||
const updatedLevels = new Set(
|
||||
checkedLevels
|
||||
);
|
||||
polda?.subDestination?.forEach(
|
||||
(polres: any) => {
|
||||
if (isChecked) {
|
||||
updatedLevels.add(polres.id);
|
||||
} else {
|
||||
updatedLevels.delete(polres.id);
|
||||
}
|
||||
}
|
||||
);
|
||||
setCheckedLevels(updatedLevels);
|
||||
}}
|
||||
className="mr-2"
|
||||
/>
|
||||
Pilih Semua Polres
|
||||
</Label>
|
||||
{polda?.subDestination?.map((polres: any) => (
|
||||
<Label key={polres.id} className="block mt-1">
|
||||
<Checkbox
|
||||
checked={checkedLevels.has(polres.id)}
|
||||
onCheckedChange={() =>
|
||||
handleCheckboxChange(polres.id)
|
||||
}
|
||||
className="mr-2"
|
||||
/>
|
||||
{polres.name}
|
||||
</Label>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{listDest.map((polda: any) => {
|
||||
const poldaChecked = unitSelection.polda; // kontrol polda luar
|
||||
const polresChecked = unitSelection.polres; // kontrol polres luar
|
||||
|
||||
const isPoldaDisabled = poldaChecked; // lock checkbox polda dialog jika polda luar dicentang
|
||||
const isPolresDisabled = polresChecked; // lock checkbox polres dialog jika polres luar dicentang
|
||||
|
||||
return (
|
||||
<div key={polda.id} className="border p-2">
|
||||
<Label className="flex items-center">
|
||||
<Checkbox
|
||||
checked={
|
||||
poldaChecked || checkedLevels.has(polda.id)
|
||||
} // auto-centang jika polda luar dicentang
|
||||
disabled={isPoldaDisabled}
|
||||
onCheckedChange={() => {
|
||||
if (isPoldaDisabled) return;
|
||||
handleCheckboxChange(polda.id);
|
||||
}}
|
||||
className="mr-3"
|
||||
/>
|
||||
{polda.name}
|
||||
<button
|
||||
onClick={() => toggleExpand(polda.id)}
|
||||
className="ml-2 focus:outline-none"
|
||||
>
|
||||
{expandedPolda[polda.id] ? (
|
||||
<ChevronUp size={16} />
|
||||
) : (
|
||||
<ChevronDown size={16} />
|
||||
)}
|
||||
</button>
|
||||
</Label>
|
||||
|
||||
{expandedPolda[polda.id] && (
|
||||
<div className="ml-6 mt-2">
|
||||
{polda?.subDestination?.map((polres: any) => (
|
||||
<Label
|
||||
key={polres.id}
|
||||
className="block mt-1"
|
||||
>
|
||||
<Checkbox
|
||||
checked={
|
||||
polresChecked ||
|
||||
checkedLevels.has(polres.id)
|
||||
} // auto-centang jika polres luar dicentang
|
||||
disabled={isPolresDisabled}
|
||||
onCheckedChange={() => {
|
||||
if (isPolresDisabled) return;
|
||||
handleCheckboxChange(polres.id);
|
||||
}}
|
||||
className="mr-2"
|
||||
/>
|
||||
{polres.name}
|
||||
</Label>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
|
@ -856,14 +893,15 @@ export default function FormTaskEdit() {
|
|||
{t("assigment-type", { defaultValue: "Assigment Type" })}{" "}
|
||||
</Label>
|
||||
<RadioGroup
|
||||
defaultValue={detail.taskType.toString()}
|
||||
onValueChange={(value) => setTaskType(String(value))}
|
||||
value={taskType} // ✅ controlled
|
||||
onValueChange={(value) => setTaskType(value)}
|
||||
className="flex flex-wrap gap-3"
|
||||
>
|
||||
<RadioGroupItem value="atensi-khusus" id="khusus" />
|
||||
<Label htmlFor="atensi-khusus">Atensi Khusus</Label>
|
||||
<Label htmlFor="khusus">Atensi Khusus</Label>
|
||||
|
||||
<RadioGroupItem value="tugas-harian" id="harian" />
|
||||
<Label htmlFor="tugas-harian">Tugas Harian</Label>
|
||||
<Label htmlFor="harian">Tugas Harian</Label>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
{/* RadioGroup Assignment Category */}
|
||||
|
|
|
|||
Loading…
Reference in New Issue