feat:add kostum form contest, fix status table contest,add content rewrite 3 id,generate article
This commit is contained in:
parent
0fdfa4b8ba
commit
65ec901d9a
|
|
@ -108,12 +108,8 @@ const columns: ColumnDef<any>[] = [
|
||||||
diterima: "bg-green-100 text-green-600",
|
diterima: "bg-green-100 text-green-600",
|
||||||
"menunggu review": "bg-orange-100 text-orange-600",
|
"menunggu review": "bg-orange-100 text-orange-600",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mengambil `statusName` dari data API
|
|
||||||
const status = row.getValue("statusName") as string;
|
const status = row.getValue("statusName") as string;
|
||||||
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
|
const statusName = status?.toLocaleLowerCase();
|
||||||
|
|
||||||
// Gunakan `statusName` untuk pencocokan
|
|
||||||
const statusStyles =
|
const statusStyles =
|
||||||
statusColors[statusName] || "bg-gray-100 text-gray-600";
|
statusColors[statusName] || "bg-gray-100 text-gray-600";
|
||||||
|
|
||||||
|
|
@ -124,7 +120,7 @@ const columns: ColumnDef<any>[] = [
|
||||||
statusStyles
|
statusStyles
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{status} {/* Tetap tampilkan nilai asli */}
|
{status}
|
||||||
</Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ const columns: ColumnDef<any>[] = [
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isActive ? (
|
{isActive ? (
|
||||||
<b className="text-info">Terkirim</b>
|
<b className="text-blue-500">Terkirim</b>
|
||||||
) : (
|
) : (
|
||||||
<b className="text-danger">Belum Terkirim</b>
|
<b className="text-danger">Belum Terkirim</b>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ const columns: ColumnDef<any>[] = [
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isActive ? (
|
{isActive ? (
|
||||||
<b className="text-info">Terkirim</b>
|
<b className="text-blue-500">Terkirim</b>
|
||||||
) : (
|
) : (
|
||||||
<b className="text-danger">Belum Terkirim</b>
|
<b className="text-danger">Belum Terkirim</b>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,17 @@ const columns: ColumnDef<any>[] = [
|
||||||
accessorKey: "isPublishForAll",
|
accessorKey: "isPublishForAll",
|
||||||
header: "Status",
|
header: "Status",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
|
const isPublishForAll = row.getValue("isPublishForAll");
|
||||||
return (
|
return (
|
||||||
<span className="whitespace-nowrap text-blue-600">
|
<Badge
|
||||||
{row.getValue("isPublishForAll")}
|
className={`whitespace-nowrap px-2 py-1 rounded-full ${
|
||||||
</span>
|
isPublishForAll
|
||||||
|
? "bg-green-100 text-green-600" // Warna hijau untuk status "Publish"
|
||||||
|
: "bg-orange-100 text-orange-600" // Warna kuning untuk status "Pending"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isPublishForAll ? "Publish" : "Pending"}
|
||||||
|
</Badge>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ import { loading } from "@/config/swal";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { error } from "@/lib/swal";
|
import { error } from "@/lib/swal";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -96,6 +97,13 @@ type Detail = {
|
||||||
uploadedById: number;
|
uploadedById: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ViewEditor = dynamic(
|
||||||
|
() => {
|
||||||
|
return import("@/components/editor/view-editor");
|
||||||
|
},
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
export default function FormAudioDetail() {
|
export default function FormAudioDetail() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -180,7 +188,7 @@ export default function FormAudioDetail() {
|
||||||
const getCategories = async () => {
|
const getCategories = async () => {
|
||||||
try {
|
try {
|
||||||
const category = await listEnableCategory(fileTypeId);
|
const category = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = category.data.data.content;
|
const resCategory: Category[] = category?.data.data.content;
|
||||||
|
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
console.log("data category", resCategory);
|
console.log("data category", resCategory);
|
||||||
|
|
@ -206,7 +214,7 @@ export default function FormAudioDetail() {
|
||||||
async function initState() {
|
async function initState() {
|
||||||
if (id) {
|
if (id) {
|
||||||
const response = await detailMedia(id);
|
const response = await detailMedia(id);
|
||||||
const details = response.data?.data;
|
const details = response?.data?.data;
|
||||||
console.log("detail", details);
|
console.log("detail", details);
|
||||||
setFiles(details?.files);
|
setFiles(details?.files);
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
|
@ -400,12 +408,7 @@ export default function FormAudioDetail() {
|
||||||
control={control}
|
control={control}
|
||||||
name="description"
|
name="description"
|
||||||
render={({ field: { onChange, value } }) => (
|
render={({ field: { onChange, value } }) => (
|
||||||
<JoditEditor
|
<ViewEditor initialData={detail?.htmlDescription} />
|
||||||
ref={editor}
|
|
||||||
value={detail?.description}
|
|
||||||
onChange={onChange}
|
|
||||||
className="dark:text-black"
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{errors.description?.message && (
|
{errors.description?.message && (
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -70,6 +71,13 @@ type Category = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CustomEditor = dynamic(
|
||||||
|
() => {
|
||||||
|
return import("@/components/editor/custom-editor");
|
||||||
|
},
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
export default function FormAudio() {
|
export default function FormAudio() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -281,19 +289,47 @@ export default function FormAudio() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleArticleIdClick = async (id: string) => {
|
const handleArticleIdClick = async (id: string) => {
|
||||||
|
setIsLoading(true); // Tampilkan loading segera setelah ID diklik
|
||||||
|
try {
|
||||||
|
// Panggil API untuk mendapatkan data artikel
|
||||||
const res = await getDetailArticle(id);
|
const res = await getDetailArticle(id);
|
||||||
const articleData = res?.data?.data;
|
const articleData = res?.data?.data;
|
||||||
|
|
||||||
|
// Bersihkan konten articleBody dari elemen gambar
|
||||||
const cleanArticleBody = articleData?.articleBody?.replace(
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
||||||
/<img[^>]*>/g,
|
/<img[^>]*>/g,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Pisahkan URL gambar menjadi array
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
|
|
||||||
|
// Tunggu hingga `articleBody` tidak null atau kosong
|
||||||
|
const waitForGeneratedBody = async () => {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (cleanArticleBody) {
|
||||||
|
clearInterval(interval); // Hentikan polling jika articleBody tersedia
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 500); // Periksa setiap 500ms
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tunggu hingga articleBody selesai di-generate
|
||||||
|
await waitForGeneratedBody();
|
||||||
|
|
||||||
|
// Set data artikel ke state setelah validasi
|
||||||
setArticleBody(cleanArticleBody || "");
|
setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching article details:", error);
|
||||||
|
} finally {
|
||||||
|
// Hilangkan loading setelah semua data selesai di-generate
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
|
@ -861,14 +897,18 @@ export default function FormAudio() {
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="description"
|
name="description"
|
||||||
render={({ field: { onChange, value } }) => (
|
render={({ field: { onChange, value } }) =>
|
||||||
<JoditEditor
|
isLoading ? (
|
||||||
ref={editor}
|
<div className="flex justify-center items-center h-40">
|
||||||
value={articleBody || value}
|
<p className="text-gray-500">Loading...</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className="dark:text-black"
|
initialData={articleBody || value}
|
||||||
/>
|
/>
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{errors.description?.message && (
|
{errors.description?.message && (
|
||||||
<p className="text-red-400 text-sm">
|
<p className="text-red-400 text-sm">
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ export default function FormImage() {
|
||||||
setIsGeneratedArticle(true);
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
setArticleIds((prevIds: string[]) => {
|
setArticleIds((prevIds: string[]) => {
|
||||||
if (prevIds.length < 5) {
|
if (prevIds.length < 3) {
|
||||||
return [...prevIds, newArticleId];
|
return [...prevIds, newArticleId];
|
||||||
} else {
|
} else {
|
||||||
const updatedIds = [...prevIds];
|
const updatedIds = [...prevIds];
|
||||||
|
|
@ -308,19 +308,47 @@ export default function FormImage() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleArticleIdClick = async (id: string) => {
|
const handleArticleIdClick = async (id: string) => {
|
||||||
|
setIsLoading(true); // Tampilkan loading segera setelah ID diklik
|
||||||
|
try {
|
||||||
|
// Panggil API untuk mendapatkan data artikel
|
||||||
const res = await getDetailArticle(id);
|
const res = await getDetailArticle(id);
|
||||||
const articleData = res?.data?.data;
|
const articleData = res?.data?.data;
|
||||||
|
|
||||||
|
// Bersihkan konten articleBody dari elemen gambar
|
||||||
const cleanArticleBody = articleData?.articleBody?.replace(
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
||||||
/<img[^>]*>/g,
|
/<img[^>]*>/g,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Pisahkan URL gambar menjadi array
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
|
|
||||||
|
// Tunggu hingga `articleBody` tidak null atau kosong
|
||||||
|
const waitForGeneratedBody = async () => {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (cleanArticleBody) {
|
||||||
|
clearInterval(interval); // Hentikan polling jika articleBody tersedia
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 500); // Periksa setiap 500ms
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tunggu hingga articleBody selesai di-generate
|
||||||
|
await waitForGeneratedBody();
|
||||||
|
|
||||||
|
// Set data artikel ke state setelah validasi
|
||||||
setArticleBody(cleanArticleBody || "");
|
setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching article details:", error);
|
||||||
|
} finally {
|
||||||
|
// Hilangkan loading setelah semua data selesai di-generate
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
|
@ -862,7 +890,7 @@ export default function FormImage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isGeneratedArticle && (
|
{isGeneratedArticle && (
|
||||||
<div className="mt-3 pb-0 flex flex-row ">
|
<div className="mt-3 pb-0 flex flex-row">
|
||||||
{articleIds.map((id: string, index: number) => (
|
{articleIds.map((id: string, index: number) => (
|
||||||
<p
|
<p
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -915,24 +943,18 @@ export default function FormImage() {
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="description"
|
name="description"
|
||||||
render={({ field: { onChange, value } }) => (
|
render={({ field: { onChange, value } }) =>
|
||||||
// <JoditEditor
|
isLoading ? (
|
||||||
// ref={editor}
|
<div className="flex justify-center items-center h-40">
|
||||||
// value={articleBody || value}
|
<p className="text-gray-500">Loading...</p>
|
||||||
// onChange={onChange}
|
</div>
|
||||||
// className="dark:text-black"
|
) : (
|
||||||
// />
|
|
||||||
<<<<<<< HEAD
|
|
||||||
<CustomEditor
|
|
||||||
onChange={onChange}
|
|
||||||
// value={articleBody || value}
|
|
||||||
=======
|
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
initialData={articleBody || value}
|
initialData={articleBody || value}
|
||||||
>>>>>>> e2193a8c9ac305726ea8f34d9b99e36b010f6841
|
|
||||||
/>
|
/>
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{errors.description?.message && (
|
{errors.description?.message && (
|
||||||
<p className="text-red-400 text-sm">
|
<p className="text-red-400 text-sm">
|
||||||
|
|
|
||||||
|
|
@ -330,11 +330,11 @@ export default function FormConvertSPIT() {
|
||||||
setIsGeneratedArticle(true);
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
setArticleIds((prevIds: string[]) => {
|
setArticleIds((prevIds: string[]) => {
|
||||||
if (prevIds.length < 5) {
|
if (prevIds.length < 3) {
|
||||||
return [...prevIds, newArticleId];
|
return [...prevIds, newArticleId];
|
||||||
} else {
|
} else {
|
||||||
const updatedIds = [...prevIds];
|
const updatedIds = [...prevIds];
|
||||||
updatedIds[4] = newArticleId;
|
updatedIds[2] = newArticleId;
|
||||||
return updatedIds;
|
return updatedIds;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ import { loading } from "@/config/swal";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { error } from "@/lib/swal";
|
import { error } from "@/lib/swal";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -96,6 +97,13 @@ type Detail = {
|
||||||
uploadedById: number;
|
uploadedById: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ViewEditor = dynamic(
|
||||||
|
() => {
|
||||||
|
return import("@/components/editor/view-editor");
|
||||||
|
},
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
export default function FormTeksDetail() {
|
export default function FormTeksDetail() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -402,12 +410,7 @@ export default function FormTeksDetail() {
|
||||||
control={control}
|
control={control}
|
||||||
name="description"
|
name="description"
|
||||||
render={({ field: { onChange, value } }) => (
|
render={({ field: { onChange, value } }) => (
|
||||||
<JoditEditor
|
<ViewEditor initialData={detail?.htmlDescription} />
|
||||||
ref={editor}
|
|
||||||
value={detail?.description}
|
|
||||||
onChange={onChange}
|
|
||||||
className="dark:text-black"
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{errors.description?.message && (
|
{errors.description?.message && (
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -70,6 +71,13 @@ type Category = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CustomEditor = dynamic(
|
||||||
|
() => {
|
||||||
|
return import("@/components/editor/custom-editor");
|
||||||
|
},
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
export default function FormTeks() {
|
export default function FormTeks() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -281,19 +289,47 @@ export default function FormTeks() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleArticleIdClick = async (id: string) => {
|
const handleArticleIdClick = async (id: string) => {
|
||||||
|
setIsLoading(true); // Tampilkan loading segera setelah ID diklik
|
||||||
|
try {
|
||||||
|
// Panggil API untuk mendapatkan data artikel
|
||||||
const res = await getDetailArticle(id);
|
const res = await getDetailArticle(id);
|
||||||
const articleData = res?.data?.data;
|
const articleData = res?.data?.data;
|
||||||
|
|
||||||
|
// Bersihkan konten articleBody dari elemen gambar
|
||||||
const cleanArticleBody = articleData?.articleBody?.replace(
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
||||||
/<img[^>]*>/g,
|
/<img[^>]*>/g,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Pisahkan URL gambar menjadi array
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
|
|
||||||
|
// Tunggu hingga `articleBody` tidak null atau kosong
|
||||||
|
const waitForGeneratedBody = async () => {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (cleanArticleBody) {
|
||||||
|
clearInterval(interval); // Hentikan polling jika articleBody tersedia
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 500); // Periksa setiap 500ms
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tunggu hingga articleBody selesai di-generate
|
||||||
|
await waitForGeneratedBody();
|
||||||
|
|
||||||
|
// Set data artikel ke state setelah validasi
|
||||||
setArticleBody(cleanArticleBody || "");
|
setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching article details:", error);
|
||||||
|
} finally {
|
||||||
|
// Hilangkan loading setelah semua data selesai di-generate
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
|
@ -861,14 +897,18 @@ export default function FormTeks() {
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="description"
|
name="description"
|
||||||
render={({ field: { onChange, value } }) => (
|
render={({ field: { onChange, value } }) =>
|
||||||
<JoditEditor
|
isLoading ? (
|
||||||
ref={editor}
|
<div className="flex justify-center items-center h-40">
|
||||||
value={articleBody || value}
|
<p className="text-gray-500">Loading...</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className="dark:text-black"
|
initialData={articleBody || value}
|
||||||
/>
|
/>
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{errors.description?.message && (
|
{errors.description?.message && (
|
||||||
<p className="text-red-400 text-sm">
|
<p className="text-red-400 text-sm">
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,14 @@ import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
import CustomEditor from "@/components/editor/custom-editor";
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
|
const CustomEditor = dynamic(
|
||||||
|
() => {
|
||||||
|
return import("@/components/editor/custom-editor");
|
||||||
|
},
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -282,19 +289,47 @@ export default function FormVideo() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleArticleIdClick = async (id: string) => {
|
const handleArticleIdClick = async (id: string) => {
|
||||||
|
setIsLoading(true); // Tampilkan loading segera setelah ID diklik
|
||||||
|
try {
|
||||||
|
// Panggil API untuk mendapatkan data artikel
|
||||||
const res = await getDetailArticle(id);
|
const res = await getDetailArticle(id);
|
||||||
const articleData = res?.data?.data;
|
const articleData = res?.data?.data;
|
||||||
|
|
||||||
|
// Bersihkan konten articleBody dari elemen gambar
|
||||||
const cleanArticleBody = articleData?.articleBody?.replace(
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
||||||
/<img[^>]*>/g,
|
/<img[^>]*>/g,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Pisahkan URL gambar menjadi array
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
|
|
||||||
|
// Tunggu hingga `articleBody` tidak null atau kosong
|
||||||
|
const waitForGeneratedBody = async () => {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (cleanArticleBody) {
|
||||||
|
clearInterval(interval); // Hentikan polling jika articleBody tersedia
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 500); // Periksa setiap 500ms
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tunggu hingga articleBody selesai di-generate
|
||||||
|
await waitForGeneratedBody();
|
||||||
|
|
||||||
|
// Set data artikel ke state setelah validasi
|
||||||
setArticleBody(cleanArticleBody || "");
|
setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching article details:", error);
|
||||||
|
} finally {
|
||||||
|
// Hilangkan loading setelah semua data selesai di-generate
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,12 @@ import {
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
import JoditEditor from "jodit-react";
|
import JoditEditor from "jodit-react";
|
||||||
import { createTask, getTask } from "@/service/task";
|
import {
|
||||||
import { getContestById } from "@/service/contest/contest";
|
createTask,
|
||||||
|
getTask,
|
||||||
|
getUserLevelForAssignments,
|
||||||
|
} from "@/service/task";
|
||||||
|
import { getContestById, postCreateContest } from "@/service/contest/contest";
|
||||||
import page from "@/app/[locale]/page";
|
import page from "@/app/[locale]/page";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
|
|
@ -29,10 +33,19 @@ import {
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { CalendarIcon } from "lucide-react";
|
import { CalendarIcon, ChevronDown, ChevronUp } from "lucide-react";
|
||||||
import { format, parseISO } from "date-fns";
|
import { format, parseISO } from "date-fns";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
import { DateRange } from "react-day-picker";
|
import { DateRange } from "react-day-picker";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
const contestSchema = z.object({
|
const contestSchema = z.object({
|
||||||
theme: z.string().min(1, { message: "Judul diperlukan" }),
|
theme: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -40,9 +53,12 @@ const contestSchema = z.object({
|
||||||
description: z.string().min(2, {
|
description: z.string().min(2, {
|
||||||
message: "Narasi Penugasan harus lebih dari 2 karakter.",
|
message: "Narasi Penugasan harus lebih dari 2 karakter.",
|
||||||
}),
|
}),
|
||||||
|
scoringFormula: z.string().min(2, {
|
||||||
|
message: "Narasi Penugasan harus lebih dari 2 karakter.",
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type taskDetail = {
|
export type contestDetail = {
|
||||||
id: number;
|
id: number;
|
||||||
theme: string;
|
theme: string;
|
||||||
hastagCode: string;
|
hastagCode: string;
|
||||||
|
|
@ -56,12 +72,22 @@ export type taskDetail = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
platformType: string | null;
|
||||||
|
assignmentTypeId: string;
|
||||||
targetOutput: string;
|
targetOutput: string;
|
||||||
targetParticipantTopLevel: string;
|
targetParticipantTopLevel: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
fileTypeOutput: any;
|
||||||
is_active: string;
|
is_active: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CustomEditor = dynamic(
|
||||||
|
() => {
|
||||||
|
return import("@/components/editor/custom-editor");
|
||||||
|
},
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
export default function FormContestDetail() {
|
export default function FormContestDetail() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -69,8 +95,19 @@ export default function FormContestDetail() {
|
||||||
type ContestSchema = z.infer<typeof contestSchema>;
|
type ContestSchema = z.infer<typeof contestSchema>;
|
||||||
const { id } = useParams() as { id: string };
|
const { id } = useParams() as { id: string };
|
||||||
console.log(id);
|
console.log(id);
|
||||||
|
const [mainType, setMainType] = useState<string>("1");
|
||||||
|
const [broadcastType, setBroadcastType] = useState<string>(""); // untuk Tipe Penugasan
|
||||||
|
const [selectedTarget, setSelectedTarget] = useState("all");
|
||||||
|
const [detail, setDetail] = useState<any>();
|
||||||
|
const [refresh] = useState(false);
|
||||||
|
const [date, setDate] = useState<DateRange | undefined>();
|
||||||
|
const [listDest, setListDest] = useState([]);
|
||||||
|
const [checkedLevels, setCheckedLevels] = useState(new Set());
|
||||||
|
const [expandedPolda, setExpandedPolda] = useState([{}]);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
|
||||||
|
|
||||||
// State for various form fields
|
|
||||||
const [taskOutput, setTaskOutput] = useState({
|
const [taskOutput, setTaskOutput] = useState({
|
||||||
all: false,
|
all: false,
|
||||||
video: false,
|
video: false,
|
||||||
|
|
@ -79,18 +116,6 @@ export default function FormContestDetail() {
|
||||||
text: false,
|
text: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// const [assignmentType, setAssignmentType] = useState("mediahub");
|
|
||||||
// const [assignmentCategory, setAssignmentCategory] = useState("publication");
|
|
||||||
const [mainType, setMainType] = useState<string>("1");
|
|
||||||
const [taskType, setTaskType] = useState<string>("atensi-khusus");
|
|
||||||
const [broadcastType, setBroadcastType] = useState<string>(""); // untuk Tipe Penugasan
|
|
||||||
const [type, setType] = useState<string>("1");
|
|
||||||
const [selectedTarget, setSelectedTarget] = useState("all");
|
|
||||||
const [detail, setDetail] = useState<taskDetail>();
|
|
||||||
const [refresh] = useState(false);
|
|
||||||
const [date, setDate] = useState<DateRange | undefined>();
|
|
||||||
|
|
||||||
const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
|
|
||||||
const [unitSelection, setUnitSelection] = useState({
|
const [unitSelection, setUnitSelection] = useState({
|
||||||
allUnit: false,
|
allUnit: false,
|
||||||
mabes: false,
|
mabes: false,
|
||||||
|
|
@ -113,6 +138,30 @@ export default function FormContestDetail() {
|
||||||
// setPlatformTypeVisible(selectedValue === 2);
|
// setPlatformTypeVisible(selectedValue === 2);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchPoldaPolres() {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await getUserLevelForAssignments();
|
||||||
|
setListDest(response?.data?.data.list);
|
||||||
|
const initialExpandedState = response?.data?.data.list.reduce(
|
||||||
|
(acc: any, polda: any) => {
|
||||||
|
acc[polda.id] = false;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
setExpandedPolda(initialExpandedState);
|
||||||
|
console.log("polres", initialExpandedState);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching Polda/Polres data:", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchPoldaPolres();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function initState() {
|
async function initState() {
|
||||||
if (id) {
|
if (id) {
|
||||||
|
|
@ -142,19 +191,42 @@ export default function FormContestDetail() {
|
||||||
}
|
}
|
||||||
}, [detail?.targetOutput]);
|
}, [detail?.targetOutput]);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (detail?.targetParticipantTopLevel) {
|
// if (detail?.targetParticipantTopLevel) {
|
||||||
const outputSet = new Set(
|
// const outputSet = new Set(
|
||||||
detail.targetParticipantTopLevel.split(",").map(Number)
|
// detail.targetParticipantTopLevel.split(",").map(Number)
|
||||||
);
|
// );
|
||||||
setUnitSelection({
|
// setUnitSelection({
|
||||||
allUnit: outputSet.has(0),
|
// allUnit: outputSet.has(0),
|
||||||
mabes: outputSet.has(1),
|
// mabes: outputSet.has(1),
|
||||||
polda: outputSet.has(2),
|
// polda: outputSet.has(2),
|
||||||
polres: outputSet.has(3),
|
// polres: outputSet.has(3),
|
||||||
});
|
// });
|
||||||
|
// }
|
||||||
|
// }, [detail?.targetParticipantTopLevel]);
|
||||||
|
|
||||||
|
const handleCheckboxChange = (levelId: number) => {
|
||||||
|
setCheckedLevels((prev) => {
|
||||||
|
const updatedLevels = new Set(prev);
|
||||||
|
if (updatedLevels.has(levelId)) {
|
||||||
|
updatedLevels.delete(levelId);
|
||||||
|
} else {
|
||||||
|
updatedLevels.add(levelId);
|
||||||
}
|
}
|
||||||
}, [detail?.targetParticipantTopLevel]);
|
return updatedLevels;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePoldaPolresChange = () => {
|
||||||
|
return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleExpand = (poldaId: any) => {
|
||||||
|
setExpandedPolda((prev: any) => ({
|
||||||
|
...prev,
|
||||||
|
[poldaId]: !prev[poldaId],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const save = async (data: ContestSchema) => {
|
const save = async (data: ContestSchema) => {
|
||||||
const fileTypeMapping = {
|
const fileTypeMapping = {
|
||||||
|
|
@ -165,34 +237,53 @@ export default function FormContestDetail() {
|
||||||
text: "5",
|
text: "5",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unitMapping = {
|
||||||
|
allUnit: "0",
|
||||||
|
mabes: "1",
|
||||||
|
polda: "2",
|
||||||
|
polres: "3",
|
||||||
|
};
|
||||||
|
|
||||||
|
const assignmentPurposeString = Object.keys(unitSelection)
|
||||||
|
.filter((key) => unitSelection[key as keyof typeof unitSelection])
|
||||||
|
.map((key) => unitMapping[key as keyof typeof unitMapping])
|
||||||
|
.join(",");
|
||||||
|
|
||||||
const selectedOutputs = Object.keys(taskOutput)
|
const selectedOutputs = Object.keys(taskOutput)
|
||||||
.filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true`
|
.filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true`
|
||||||
.map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string
|
.map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string
|
||||||
.join(",");
|
.join(",");
|
||||||
|
|
||||||
const requestData = {
|
const requestData: {
|
||||||
|
id?: any;
|
||||||
|
theme: string;
|
||||||
|
assignedToLevel: any;
|
||||||
|
assignmentPurpose: any;
|
||||||
|
hastagCode: string;
|
||||||
|
description: string;
|
||||||
|
assignmentMainTypeId: any;
|
||||||
|
scoringFormula: string;
|
||||||
|
fileTypeOutput: any;
|
||||||
|
} = {
|
||||||
...data,
|
...data,
|
||||||
// assignmentType,
|
hastagCode: data.hastagCode,
|
||||||
// assignmentCategory,
|
|
||||||
target: selectedTarget,
|
|
||||||
unitSelection,
|
|
||||||
assignedToRole: "3",
|
|
||||||
taskType: taskType,
|
|
||||||
broadcastType: broadcastType,
|
|
||||||
assignmentMainTypeId: mainType,
|
|
||||||
assignmentPurpose: "1",
|
|
||||||
assignmentTypeId: type,
|
|
||||||
fileTypeOutput: selectedOutputs,
|
|
||||||
id: null,
|
|
||||||
description: data.description,
|
|
||||||
platformType: "",
|
|
||||||
theme: data.theme,
|
theme: data.theme,
|
||||||
|
description: data.description,
|
||||||
|
scoringFormula: data.scoringFormula,
|
||||||
|
assignmentMainTypeId: mainType,
|
||||||
|
assignedToLevel: handlePoldaPolresChange(),
|
||||||
|
assignmentPurpose: assignmentPurposeString,
|
||||||
|
fileTypeOutput: selectedOutputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
// const response = await createTask(requestData);
|
if (id != undefined) {
|
||||||
|
requestData.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await postCreateContest(requestData);
|
||||||
|
|
||||||
console.log("Form Data Submitted:", requestData);
|
console.log("Form Data Submitted:", requestData);
|
||||||
// console.log("response", response);
|
console.log("response", response);
|
||||||
|
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
title: "Sukses",
|
title: "Sukses",
|
||||||
|
|
@ -225,7 +316,6 @@ export default function FormContestDetail() {
|
||||||
<Card>
|
<Card>
|
||||||
<div className="px-6 py-6">
|
<div className="px-6 py-6">
|
||||||
<p className="text-lg font-semibold mb-3">Form Contest</p>
|
<p className="text-lg font-semibold mb-3">Form Contest</p>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|
@ -233,12 +323,12 @@ export default function FormContestDetail() {
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="hastagCode"
|
name="hastagCode"
|
||||||
render={({ field }) => (
|
render={({ field: { onChange, value } }) => (
|
||||||
<Input
|
<Input
|
||||||
size="md"
|
size="md"
|
||||||
type="text"
|
type="text"
|
||||||
value={field.value}
|
value={detail?.hastagCode || value}
|
||||||
onChange={field.onChange}
|
onChange={onChange}
|
||||||
placeholder="Enter hastagCode"
|
placeholder="Enter hastagCode"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -255,12 +345,12 @@ export default function FormContestDetail() {
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="theme"
|
name="theme"
|
||||||
render={({ field }) => (
|
render={({ field: { onChange, value } }) => (
|
||||||
<Input
|
<Input
|
||||||
size="md"
|
size="md"
|
||||||
type="text"
|
type="text"
|
||||||
value={field.value}
|
value={detail?.theme || value}
|
||||||
onChange={field.onChange}
|
onChange={onChange}
|
||||||
placeholder="Enter theme"
|
placeholder="Enter theme"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -345,19 +435,101 @@ export default function FormContestDetail() {
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<div className=" pl-1">
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="soft" size="sm" color="primary">
|
||||||
|
[Kustom]
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>
|
||||||
|
Daftar Wilayah Polda dan Polres
|
||||||
|
</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>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mt-7">
|
<div className="mt-7">
|
||||||
<Label>Narasi Penugasan</Label>
|
<Label>Narasi Penugasan</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="description"
|
name="description"
|
||||||
render={({ field: { onChange, value } }) => (
|
render={({ field: { onChange, value } }) => (
|
||||||
<JoditEditor
|
<CustomEditor
|
||||||
ref={editor}
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className="dark:text-black"
|
initialData={detail?.description || value}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
@ -367,6 +539,24 @@ export default function FormContestDetail() {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mt-7">
|
||||||
|
<Label>Rumus Penilaian</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="scoringFormula"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={detail?.scoringFormula || value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.scoringFormula?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.scoringFormula.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ export default function FormTask() {
|
||||||
const [isVideoUploadFinish, setIsVideoUploadFinish] = useState(false);
|
const [isVideoUploadFinish, setIsVideoUploadFinish] = useState(false);
|
||||||
const [isTextUploadFinish, setIsTextUploadFinish] = useState(false);
|
const [isTextUploadFinish, setIsTextUploadFinish] = useState(false);
|
||||||
const [isAudioUploadFinish, setIsAudioUploadFinish] = useState(false);
|
const [isAudioUploadFinish, setIsAudioUploadFinish] = useState(false);
|
||||||
|
const [voiceNoteLink, setVoiceNoteLink] = useState("");
|
||||||
|
|
||||||
const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
|
const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
|
||||||
const [unitSelection, setUnitSelection] = useState({
|
const [unitSelection, setUnitSelection] = useState({
|
||||||
|
|
@ -244,52 +245,28 @@ export default function FormTask() {
|
||||||
setIsImageUploadFinish(true);
|
setIsImageUploadFinish(true);
|
||||||
}
|
}
|
||||||
imageFiles?.map(async (item: any, index: number) => {
|
imageFiles?.map(async (item: any, index: number) => {
|
||||||
await uploadResumableFile(
|
await uploadResumableFile(index, String(id), item, "1", "0");
|
||||||
index,
|
|
||||||
String(id),
|
|
||||||
item,
|
|
||||||
"1",
|
|
||||||
"0"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (videoFiles?.length == 0) {
|
if (videoFiles?.length == 0) {
|
||||||
setIsVideoUploadFinish(true);
|
setIsVideoUploadFinish(true);
|
||||||
}
|
}
|
||||||
videoFiles?.map(async (item: any, index: number) => {
|
videoFiles?.map(async (item: any, index: number) => {
|
||||||
await uploadResumableFile(
|
await uploadResumableFile(index, String(id), item, "2", "0");
|
||||||
index,
|
|
||||||
String(id),
|
|
||||||
item,
|
|
||||||
"2",
|
|
||||||
"0"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (textFiles?.length == 0) {
|
if (textFiles?.length == 0) {
|
||||||
setIsTextUploadFinish(true);
|
setIsTextUploadFinish(true);
|
||||||
}
|
}
|
||||||
textFiles?.map(async (item: any, index: number) => {
|
textFiles?.map(async (item: any, index: number) => {
|
||||||
await uploadResumableFile(
|
await uploadResumableFile(index, String(id), item, "3", "0");
|
||||||
index,
|
|
||||||
String(id),
|
|
||||||
item,
|
|
||||||
"3",
|
|
||||||
"0"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (audioFiles?.length == 0) {
|
if (audioFiles?.length == 0) {
|
||||||
setIsAudioUploadFinish(true);
|
setIsAudioUploadFinish(true);
|
||||||
}
|
}
|
||||||
audioFiles?.map(async (item: any, index: number) => {
|
audioFiles?.map(async (item: any, index: number) => {
|
||||||
await uploadResumableFile(
|
await uploadResumableFile(index, String(id), item, "4", "0");
|
||||||
index,
|
|
||||||
String(id),
|
|
||||||
item,
|
|
||||||
"4",
|
|
||||||
"0"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// MySwal.fire({
|
// MySwal.fire({
|
||||||
|
|
@ -417,13 +394,15 @@ export default function FormTask() {
|
||||||
// counterUpdateProgress++;
|
// counterUpdateProgress++;
|
||||||
// setCounterProgress(counterUpdateProgress);
|
// setCounterProgress(counterUpdateProgress);
|
||||||
successTodo();
|
successTodo();
|
||||||
if (fileTypeId == '1'){
|
if (fileTypeId == "1") {
|
||||||
setIsImageUploadFinish(true);
|
setIsImageUploadFinish(true);
|
||||||
} else if (fileTypeId == '2'){
|
} else if (fileTypeId == "2") {
|
||||||
setIsVideoUploadFinish(true);
|
setIsVideoUploadFinish(true);
|
||||||
} if (fileTypeId == '3'){
|
}
|
||||||
|
if (fileTypeId == "3") {
|
||||||
setIsTextUploadFinish(true);
|
setIsTextUploadFinish(true);
|
||||||
} if (fileTypeId == '4'){
|
}
|
||||||
|
if (fileTypeId == "4") {
|
||||||
setIsAudioUploadFinish(true);
|
setIsAudioUploadFinish(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -434,10 +413,20 @@ export default function FormTask() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
successTodo();
|
successTodo();
|
||||||
}, [isImageUploadFinish, isVideoUploadFinish, isAudioUploadFinish, isTextUploadFinish])
|
}, [
|
||||||
|
isImageUploadFinish,
|
||||||
|
isVideoUploadFinish,
|
||||||
|
isAudioUploadFinish,
|
||||||
|
isTextUploadFinish,
|
||||||
|
]);
|
||||||
|
|
||||||
function successTodo() {
|
function successTodo() {
|
||||||
if (isImageUploadFinish && isVideoUploadFinish && isAudioUploadFinish && isTextUploadFinish) {
|
if (
|
||||||
|
isImageUploadFinish &&
|
||||||
|
isVideoUploadFinish &&
|
||||||
|
isAudioUploadFinish &&
|
||||||
|
isTextUploadFinish
|
||||||
|
) {
|
||||||
successSubmit("/in/contributor/agenda-setting");
|
successSubmit("/in/contributor/agenda-setting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -454,7 +443,6 @@ export default function FormTask() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<div className="px-6 py-6">
|
<div className="px-6 py-6">
|
||||||
|
|
@ -776,10 +764,18 @@ export default function FormTask() {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isRecording && (
|
{isRecording && <p>Recording... {timer} seconds remaining</p>}{" "}
|
||||||
<p>Recording... {timer} seconds remaining</p>
|
|
||||||
)}{" "}
|
|
||||||
{/* Display remaining time */}
|
{/* Display remaining time */}
|
||||||
|
<div className="mt-4">
|
||||||
|
<Label htmlFor="voiceNoteLink">Link Berita</Label>
|
||||||
|
<Input
|
||||||
|
id="voiceNoteLink"
|
||||||
|
type="url"
|
||||||
|
placeholder="Masukkan link voice note"
|
||||||
|
value={voiceNoteLink}
|
||||||
|
onChange={(e) => setVoiceNoteLink(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ export async function listDataAll(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
export async function listDataImage(
|
export async function listDataImage(
|
||||||
limit: any,
|
limit: any,
|
||||||
page: any,
|
page: any,
|
||||||
|
|
@ -59,15 +58,11 @@ export async function listDataImage(
|
||||||
endDate: any,
|
endDate: any,
|
||||||
title: string = ""
|
title: string = ""
|
||||||
) {
|
) {
|
||||||
=======
|
|
||||||
export async function listDataImage(limit: any, page: any, isForSelf: any, isApproval: any, categoryFilter: any, statusFilter: any, needApprovalFromLevel: any, creator: any, source: any, startDate: any, endDate: any, title: string = "") {
|
|
||||||
>>>>>>> e2193a8c9ac305726ea8f34d9b99e36b010f6841
|
|
||||||
return await httpGetInterceptor(
|
return await httpGetInterceptor(
|
||||||
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
export async function listDataVideo(
|
export async function listDataVideo(
|
||||||
limit: any,
|
limit: any,
|
||||||
page: any,
|
page: any,
|
||||||
|
|
@ -82,15 +77,11 @@ export async function listDataVideo(
|
||||||
endDate: any,
|
endDate: any,
|
||||||
title: string = ""
|
title: string = ""
|
||||||
) {
|
) {
|
||||||
=======
|
|
||||||
export async function listDataVideo(limit: any, page: any, isForSelf: any, isApproval: any, categoryFilter: any, statusFilter: any, needApprovalFromLevel: any, creator: any, source: any, startDate: any, endDate: any, title: string = "") {
|
|
||||||
>>>>>>> e2193a8c9ac305726ea8f34d9b99e36b010f6841
|
|
||||||
return await httpGetInterceptor(
|
return await httpGetInterceptor(
|
||||||
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=2&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=2&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
export async function listDataTeks(
|
export async function listDataTeks(
|
||||||
limit: any,
|
limit: any,
|
||||||
page: any,
|
page: any,
|
||||||
|
|
@ -105,18 +96,14 @@ export async function listDataTeks(
|
||||||
endDate: any,
|
endDate: any,
|
||||||
title: string = ""
|
title: string = ""
|
||||||
) {
|
) {
|
||||||
=======
|
|
||||||
export async function listDataTeks(limit: any, page: any, isForSelf: any, isApproval: any, categoryFilter: any, statusFilter: any, needApprovalFromLevel: any, creator: any, source: any, startDate: any, endDate: any, title: string = "") {
|
|
||||||
>>>>>>> e2193a8c9ac305726ea8f34d9b99e36b010f6841
|
|
||||||
return await httpGetInterceptor(
|
return await httpGetInterceptor(
|
||||||
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=3&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=3&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
export async function listDataAudio(
|
export async function listDataAudio(
|
||||||
page: any,
|
|
||||||
limit: any,
|
limit: any,
|
||||||
|
page: any,
|
||||||
isForSelf: any,
|
isForSelf: any,
|
||||||
isApproval: any,
|
isApproval: any,
|
||||||
categoryFilter: any,
|
categoryFilter: any,
|
||||||
|
|
@ -128,9 +115,6 @@ export async function listDataAudio(
|
||||||
endDate: any,
|
endDate: any,
|
||||||
title: string = ""
|
title: string = ""
|
||||||
) {
|
) {
|
||||||
=======
|
|
||||||
export async function listDataAudio(page: any, limit: any, isForSelf: any, isApproval: any, categoryFilter: any, statusFilter: any, needApprovalFromLevel: any, creator: any, source: any, startDate: any, endDate: any, title: string = "") {
|
|
||||||
>>>>>>> e2193a8c9ac305726ea8f34d9b99e36b010f6841
|
|
||||||
return await httpGetInterceptor(
|
return await httpGetInterceptor(
|
||||||
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=4&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
`media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=4&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}`
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,8 @@ export async function getContestById(id: any, pages = 0) {
|
||||||
const url = `contest?id=${id}&page=${pages}`;
|
const url = `contest?id=${id}&page=${pages}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function postCreateContest(data: any) {
|
||||||
|
const url = "contest";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue