feat:update tambah Ta,Spit,fix routing

This commit is contained in:
Anang Yusman 2025-06-06 00:11:10 +08:00
parent f574d97523
commit d5f697ddfa
4 changed files with 497 additions and 449 deletions

View File

@ -230,11 +230,13 @@ export default function AddExpertForm() {
};
const handleAddRow = () => {
setPlacementRows((prevRows: any) => [
if (placementRows.length < 2) {
setPlacementRows((prevRows) => [
...prevRows,
{ index: incrementId, roleId: "", userLevelId: 0 },
]);
setIncrementId((prevId) => prevId + 1);
}
};
return (
@ -424,7 +426,7 @@ export default function AddExpertForm() {
))}
</SelectContent>
</Select>
<Select
{/* <Select
onValueChange={(e) =>
handleSelectionChange(row.index, "userLevelId", e)
}
@ -441,6 +443,20 @@ export default function AddExpertForm() {
</SelectItem>
))}
</SelectContent>
</Select> */}
<Select
onValueChange={(e) =>
handleSelectionChange(row.index, "userLevelId", e)
}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Pilih User Level" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="216">MABES POLRI</SelectItem>
</SelectContent>
</Select>
{placementRows.length > 1 && (
<Button
@ -454,7 +470,12 @@ export default function AddExpertForm() {
)}
</div>
))}
<Button type="button" size="md" onClick={() => handleAddRow()}>
<Button
type="button"
size="md"
onClick={handleAddRow}
disabled={placementRows.length >= 2} // optional: disable button if already 1 row added
>
Tambah
</Button>
</div>

View File

@ -55,6 +55,7 @@ import dynamic from "next/dynamic";
import { error } from "@/lib/swal";
import { useTranslations } from "next-intl";
import { contextType } from "cleave.js/react";
import { Form } from "@/components/ui/form";
const imageSchema = z.object({
contentTitle: z.string().min(1, { message: "Judul diperlukan" }),
@ -182,13 +183,31 @@ export default function FormConvertSPIT() {
let fileTypeId = "1";
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<ImageSchema>({
// const {
// control,
// handleSubmit,
// setValue,
// formState: { errors },
// } = useForm<ImageSchema>({
// resolver: zodResolver(imageSchema),
// defaultValues: {
// contentTitle: detail?.contentTitle || "",
// contentDescription: detail?.contentDescription || "",
// contentCreator: detail?.contentCreator || "",
// contentRewriteDescription: detail?.contentRewriteDescription || "",
// // dll
// },
// });
const form = useForm<z.infer<typeof imageSchema>>({
resolver: zodResolver(imageSchema),
defaultValues: {
contentTitle: detail?.contentTitle || "",
contentDescription: detail?.contentDescription || "",
contentCreator: detail?.contentCreator || "",
contentRewriteDescription: detail?.contentRewriteDescription || "",
// dll
},
});
const handleRemoveTag = (index: any) => {
@ -207,11 +226,10 @@ export default function FormConvertSPIT() {
setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index));
};
// const handleCheckboxChange = (id: number) => {
// setSelectedPublishers((prev) =>
// prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
// );
// };
const handleDirectSave = () => {
const values = form.getValues(); // ambil semua nilai tanpa validasi
onSubmit(values); // langsung submit
};
useEffect(() => {
async function initState() {
@ -318,6 +336,13 @@ export default function FormConvertSPIT() {
setDetail(details);
setFiles(details?.contentList);
setupPlacementCheck(details?.contentList?.length);
form.setValue("contentTitle", details?.contentTitle || "");
form.setValue("contentDescription", details?.contentDescription || "");
form.setValue("contentCreator", details?.contentCreator || "");
form.setValue(
"contentRewriteDescription",
details?.contentRewriteDescription || ""
);
const filesData = details.contentList || [];
const fileUrls = filesData.map((file: { contentFile: string }) =>
@ -337,7 +362,7 @@ export default function FormConvertSPIT() {
}
}
initState();
}, [refresh, setValue]);
}, [refresh]);
const [tempFile, setTempFile] = useState(
detailThumb.map((data: any) => ({
@ -472,7 +497,13 @@ export default function FormConvertSPIT() {
});
};
const onSubmit = (data: ImageSchema) => {
const onSubmit = async (data: z.infer<typeof imageSchema>) => {
if (form.getValues("contentTitle") == "") {
form.setError("contentTitle", {
type: "manual",
message: "Required",
});
} else {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
@ -486,6 +517,7 @@ export default function FormConvertSPIT() {
save(data);
}
});
}
};
const [showRewriteEditor, setShowRewriteEditor] = useState(false);
@ -561,6 +593,7 @@ export default function FormConvertSPIT() {
setArticleBody(cleanArticleBody || "");
setDetailData(articleData);
setSelectedArticleId(id);
// setArticleImages(articleImagesData || []);
} catch (error) {
console.error("Error fetching article details:", error);
@ -613,7 +646,9 @@ export default function FormConvertSPIT() {
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
{detail !== undefined ? (
<div className="flex flex-col lg:flex-row gap-10">
<Card className="w-full lg:w-8/12">
@ -624,23 +659,18 @@ export default function FormConvertSPIT() {
<div className="space-y-2 py-3">
<Label>{t("title")}</Label>
<Controller
control={control}
control={form.control}
name="contentTitle"
render={({ field }) => (
<Input
size="md"
type="text"
defaultValue={detail?.contentTitle}
value={field.value}
onChange={field.onChange}
placeholder="Enter contentTitle"
/>
)}
/>
{errors.contentTitle?.message && (
<p className="text-red-400 text-sm">
{errors.contentTitle.message}
</p>
)}
</div>
<div className="flex items-center">
<div className="py-3 w-full space-y-2">
@ -683,7 +713,7 @@ export default function FormConvertSPIT() {
<div className="py-3 space-y-2">
<Label>{t("description")}</Label>
<Controller
control={control}
control={form.control}
name="contentDescription"
render={({ field: { onChange, value } }) => (
// <JoditEditor
@ -698,13 +728,9 @@ export default function FormConvertSPIT() {
/>
)}
/>
{errors.contentDescription?.message && (
<p className="text-red-400 text-sm">
{errors.contentDescription.message}
</p>
)}
</div>
<div className="space-y-2 py-3 w-4/12">
<p className="text-sm font-semibold">Content Rewrite</p>
<div className="space-y-2 pb-3 w-4/12">
<Label>{t("writing-style")}</Label>
<Select
value={selectedWritingStyle}
@ -729,6 +755,7 @@ export default function FormConvertSPIT() {
<div className="my-2">
<Button
size="sm"
type="button"
onClick={handleRewriteClick}
className="bg-blue-500 text-white py-2 px-4 rounded"
>
@ -740,22 +767,26 @@ export default function FormConvertSPIT() {
{isGeneratedArticle && (
<div className="mt-3 pb-0 flex flex-row ">
{articleIds.map((id: string, index: number) => (
<button
<Button
type="button"
key={index}
className={`mr-3 px-3 py-2 rounded-md ${
selectedArticleId === id
? "bg-green-500 text-white"
: "border-2 border-green-500 text-green-500"
: "border-2 border-green-500 bg-white text-green-500 hover:bg-green-500 hover:text-white hover:border-green-500"
}`}
onClick={() => handleArticleIdClick(id)}
>
{"Narasi " + (index + 1)}
</button>
</Button>
))}
</div>
)}
<div className="flex items-center space-x-2 mt-3">
<RadioGroupItem value="rewrite" id="rewrite-file" />
<RadioGroupItem
value="rewrite"
id="rewrite-file"
/>
<Label htmlFor="rewrite-file">
Select File Rewrite
</Label>
@ -763,7 +794,7 @@ export default function FormConvertSPIT() {
<div className="py-3 space-y-2">
<Label>{t("file-rewrite")}</Label>
<Controller
control={control}
control={form.control}
name="contentRewriteDescription"
render={({ field: { onChange, value } }) =>
isLoadingData ? (
@ -780,11 +811,6 @@ export default function FormConvertSPIT() {
)
}
/>
{errors.contentRewriteDescription?.message && (
<p className="text-red-400 text-sm">
{errors.contentRewriteDescription.message}
</p>
)}
</div>
</div>
)}
@ -929,7 +955,9 @@ export default function FormConvertSPIT() {
<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={filePlacements[index]?.includes("mabes")}
checked={filePlacements[index]?.includes(
"mabes"
)}
onCheckedChange={(e) =>
setupPlacement(index, "mabes", Boolean(e))
}
@ -944,7 +972,9 @@ export default function FormConvertSPIT() {
<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={filePlacements[index]?.includes("polda")}
checked={filePlacements[index]?.includes(
"polda"
)}
onCheckedChange={(e) =>
setupPlacement(index, "polda", Boolean(e))
}
@ -964,7 +994,11 @@ export default function FormConvertSPIT() {
"international"
)}
onCheckedChange={(e) =>
setupPlacement(index, "international", Boolean(e))
setupPlacement(
index,
"international",
Boolean(e)
)
}
/>
<label
@ -987,7 +1021,7 @@ export default function FormConvertSPIT() {
<div className="space-y-2">
<Label>{t("creator")}</Label>
<Controller
control={control}
control={form.control}
name="contentCreator"
render={({ field }) => (
<Input
@ -999,11 +1033,6 @@ export default function FormConvertSPIT() {
/>
)}
/>
{errors.contentCreator?.message && (
<p className="text-red-400 text-sm">
{errors.contentCreator.message}
</p>
)}
</div>
</div>
<div className="mt-3 px-3">
@ -1037,7 +1066,10 @@ export default function FormConvertSPIT() {
<div className="flex flex-col gap-3 space-y-2">
<Label>{t("publish-target")}</Label>
{options.map((option) => (
<div key={option.id} className="flex gap-2 items-center">
<div
key={option.id}
className="flex gap-2 items-center"
>
<Checkbox
id={option.id}
checked={
@ -1047,21 +1079,15 @@ export default function FormConvertSPIT() {
.length
: publishedFor.includes(option.id)
}
onCheckedChange={() => handleCheckboxChange(option.id)}
onCheckedChange={() =>
handleCheckboxChange(option.id)
}
/>
<Label htmlFor={option.id}>{option.label}</Label>
</div>
))}
</div>
</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")} (0)</p>
</div>
<div className="px-3 py-3">
<p>{t("information")}:</p>
{/* <p>{detail?.status}</p> */}
</div>
</Card>
<div className="flex flex-row justify-end gap-3">
<div className="mt-4">
@ -1085,5 +1111,7 @@ export default function FormConvertSPIT() {
""
)}
</form>
</Form>
</>
);
}

View File

@ -25,7 +25,6 @@ import DatePicker from "react-datepicker";
import { id } from "date-fns/locale";
import "react-datepicker/dist/react-datepicker.css";
import { zodResolver } from "@hookform/resolvers/zod";
import router from "next/router";
import { Controller, useForm } from "react-hook-form";
import { date, z } from "zod";
import { error, loading } from "@/lib/swal";
@ -51,6 +50,7 @@ import Image from "next/image";
import FileUploader from "../shared/file-uploader";
import { getCsrfToken } from "@/service/auth";
import { Upload } from "tus-js-client";
import { useRouter } from "next/navigation";
const calendarSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@ -68,6 +68,7 @@ interface FileUploaded {
export function CalendarPolriAdd() {
const MySwal = withReactContent(Swal);
const router = useRouter();
const [open, setOpen] = React.useState(false);
const t = useTranslations("Schedule");
type CalendarSchema = z.infer<typeof calendarSchema>;
@ -212,9 +213,7 @@ export function CalendarPolriAdd() {
return false;
}
Cookies.set("scheduleId", response?.data?.data.id, {
expires: 1,
});
const id = response?.data?.data?.id;
loading();
if (imageFiles?.length === 0) {
@ -242,7 +241,7 @@ export function CalendarPolriAdd() {
};
const upload = new Upload(file, {
endpoint: `${process.env.NEXT_PUBLIC_API}/agenda-settings/file/upload`,
endpoint: `${process.env.NEXT_PUBLIC_API}/calendars/file/upload`,
headers: headers,
retryDelays: [0, 3000, 6000, 12_000, 24_000],
chunkSize: 20_000,

View File

@ -134,7 +134,7 @@ export function TambahIklanModal() {
};
const handlePoldaPolresChange = () => {
return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
return Array.from(checkedLevels).join(",");
};
const handleUnitChange = (