This commit is contained in:
hanif salafi 2024-12-19 10:13:21 +07:00
commit fecc753abb
29 changed files with 3606 additions and 350 deletions

View File

@ -12,6 +12,7 @@ import {
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -95,18 +96,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<Link href={`/contributor/blog/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
{/*
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuItem> */}
</DropdownMenuContent>
</DropdownMenu>
);

View File

@ -0,0 +1,15 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormBlogDetail from "@/components/form/blog/blog--detail-form";
const BlogDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormBlogDetail />
</div>
</div>
);
};
export default BlogDetailPage;

View File

@ -11,6 +11,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
),
},
{
accessorKey: "startTime",
accessorKey: "time",
header: "Time",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
},
},
{
accessorKey: "speakerName",
accessorKey: "speaker",
header: "Disampaikan oleh",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<Link
href={`/contributor/schedule/event/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/event/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -0,0 +1,22 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormEventDetail from "@/components/form/schedule/event-detail-form";
const EventDetailPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormEventDetail />
</div>
</div>
);
};
export default EventDetailPage;

View File

@ -0,0 +1,23 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form";
import FormEventUpdate from "@/components/form/schedule/event-update-form";
const EventUpdatePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormEventUpdate />
</div>
</div>
);
};
export default EventUpdatePage;

View File

@ -106,11 +106,17 @@ const columns: ColumnDef<any>[] = [
},
},
{
accessorKey: "speakerName",
accessorKey: "speaker",
header: "Disampaikan oleh",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
@ -138,16 +144,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Link href={`/contributor/schedule/press-conference/detail/${row.id}`}>
<Link
href={`/contributor/schedule/press-conference/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
Detail
</Link>
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/press-conference/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -8,13 +8,11 @@ import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
const PressConDetailPage = () => {
const params = useParams();
const id = params?.id;
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormDetailPressConference id={id} />
<FormDetailPressConference />
</div>
</div>
);

View File

@ -0,0 +1,22 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form";
const PressConUpdatePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormUpdatePressConference />
</div>
</div>
);
};
export default PressConUpdatePage;

View File

@ -11,6 +11,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
),
},
{
accessorKey: "startTime",
accessorKey: "time",
header: "Time",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
},
},
{
accessorKey: "speakerName",
accessorKey: "speaker",
header: "Disampaikan oleh",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<Link
href={`/contributor/schedule/press-release/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/press-release/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -0,0 +1,17 @@
"use client";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import FormDetailPressRillis from "@/components/form/schedule/pers-release--detail-form";
const PressRilisDetailPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormDetailPressRillis />
</div>
</div>
);
};
export default PressRilisDetailPage;

View File

@ -0,0 +1,23 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form";
import FormUpdatePressRelease from "@/components/form/schedule/pers-release--update-form";
const PressRilisUpdatePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormUpdatePressRelease />
</div>
</div>
);
};
export default PressRilisUpdatePage;

View File

@ -1,13 +1,14 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormTaskDetail from "@/components/form/task/task-detail-form";
const TaskDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormTask />
<FormTaskDetail />
</div>
</div>
);

View File

@ -12,6 +12,7 @@ import {
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -108,18 +109,20 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Link href={`/shared/contest/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
{/* <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuItem> */}
</DropdownMenuContent>
</DropdownMenu>
);

View File

@ -0,0 +1,17 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormContestDetail from "@/components/form/contest/contest-detail-form";
const ContestDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormContestDetail />
</div>
</div>
);
};
export default ContestDetailPage;

View File

@ -0,0 +1,443 @@
"use client";
import React, { ChangeEvent, useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import JoditEditor from "jodit-react";
import { register } from "module";
import { Switch } from "@/components/ui/switch";
import Cookies from "js-cookie";
import { createTask } from "@/config/api";
import {
createMedia,
getTagsBySubCategoryId,
listEnableCategory,
} from "@/service/content/content";
import { getBlog, postBlog } from "@/service/blog/blog";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
slug: z.string().min(1, { message: "Judul diperlukan" }),
meta: z.string().min(1, { message: "Judul diperlukan" }),
description: z
.string()
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
categoryName: z.string().min(1, { message: "Kategori diperlukan" }),
});
type Category = {
id: string;
categoryName: string;
};
type Detail = {
id: string;
title: string;
description: string;
slug: string;
metadata: string;
categoryName: string;
thumbnailLink: string;
};
const initialCategories: Category[] = [
{
id: "1",
categoryName: "Giat Polri",
},
{
id: "2",
categoryName: "Giat Pimpinan",
},
{
id: "3",
categoryName: "Liputan Kegiatan",
},
{
id: "4",
categoryName: "Seputar Prestasi",
},
];
export default function FormBlogDetail() {
const MySwal = withReactContent(Swal);
const router = useRouter();
const { id } = useParams() as { id: string };
console.log(id);
const editor = useRef(null);
type TaskSchema = z.infer<typeof taskSchema>;
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
const taskId = Cookies.get("taskId");
const scheduleId = Cookies.get("scheduleId");
const scheduleType = Cookies.get("scheduleType");
const [categories] = useState<Category[]>(initialCategories);
const [selectedTarget, setSelectedTarget] = useState<string>("");
const [selectedCategory, setSelectedCategory] = useState<any>();
const [tags, setTags] = useState<any[]>([]);
const [isDraft, setIsDraft] = useState(false);
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const [unitSelection, setUnitSelection] = useState({
allUnit: false,
mabes: false,
polda: false,
polres: false,
});
let fileTypeId = "1";
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
});
// 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 handleRemoveTag = (index: any) => {
setTags((prevTags) => prevTags.filter((_, i) => i !== index));
};
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));
};
useEffect(() => {
async function initState() {
if (id) {
const response = await getBlog(id);
const details = response.data?.data;
setDetail(details);
// Set categoryId dari API ke form dan Select
setValue("categoryName", details.categoryName);
setSelectedTarget(details.categoryId); // Untuk dropdown
}
}
initState();
}, [refresh, setValue]);
const save = async (data: TaskSchema) => {
const requestData = {
...data,
title: data.title,
description: data.description,
categoryId: selectedTarget,
slug: data.slug,
metadata: data.meta,
// tags: data.tags,
isDraft,
};
const response = await postBlog(requestData);
console.log("Form Data Submitted:", requestData);
console.log("response", response);
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/blog");
});
};
const onSubmit = (data: TaskSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
const handlePublish = () => {
setIsDraft(false);
};
const handleSave = () => {
setIsDraft(true);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{detail !== undefined ? (
<div className="flex 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">Detail Indeks</p>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2 py-3">
<Label>Judul</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.title}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
<div className="py-3">
<Label>Deskripsi</Label>
<Controller
control={control}
name="description"
render={({ field: { onChange, value } }) => (
<JoditEditor
ref={editor}
value={detail.description}
onChange={onChange}
className="dark:text-black"
/>
)}
/>
{errors.description?.message && (
<p className="text-red-400 text-sm">
{errors.description.message}
</p>
)}
</div>
<div className=" py-3">
<div className="space-y-2">
<Label>Slug</Label>
<Controller
control={control}
name="slug"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.slug}
onChange={field.onChange}
placeholder="Enter Slug"
/>
)}
/>
{errors.slug?.message && (
<p className="text-red-400 text-sm">
{errors.slug.message}
</p>
)}
</div>
</div>
<div className=" py-3">
<div className="space-y-2">
<Label>Meta</Label>
<Controller
control={control}
name="meta"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.metadata}
onChange={field.onChange}
placeholder="Enter Meta"
/>
)}
/>
{errors.meta?.message && (
<p className="text-red-400 text-sm">
{errors.meta.message}
</p>
)}
</div>
</div>
</div>
</div>
</Card>
<div className="w-4/12">
<Card className=" h-[600px]">
<div className="px-3 py-3">
<Label htmlFor="fileInput">Gambar Utama</Label>
<Input
id="fileInput"
type="file"
// onChange={(e) => {
// const file = e.target.files[0];
// if (file) {
// console.log("Selected File:", file);
// // Tambahkan logika jika diperlukan, misalnya upload file ke server
// }
// }}
className=""
/>
</div>
<div className="mt-3 px-3">
<Label>Pratinjau Gambar Utama</Label>
<Card className="mt-2">
<img
src={detail.thumbnailLink}
alt="Thumbnail Gambar Utama"
className="w-full h-auto rounded"
/>
</Card>
</div>
<div className="px-3 py-3">
<label
htmlFor="kategori"
className="block text-sm font-medium text-gray-700"
>
Kategori
</label>
<Controller
name="categoryName"
control={control}
render={({ field }) => (
<Select
value={detail?.categoryName}
onValueChange={(value) => {
setSelectedTarget(value);
field.onChange(value); // Sinkronisasi dengan react-hook-form
}}
>
<SelectTrigger size="md">
<SelectValue placeholder="Pilih" />
</SelectTrigger>
<SelectContent>
{categories.map((category) => (
<SelectItem
key={category.id}
value={category.categoryName}
>
{category.categoryName}
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
</div>
<div className="px-3 py-3">
<Label>Tags</Label>
{/* <Controller
control={control}
name="tags"
render={({ field }) => (
<Input
size="md"
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Enter Title"
onKeyDown={handleKeyDown}
/>
)}
/> */}
<div className="text-sm text-red-500">
{tags.length === 0 && "Please add at least one tag."}
</div>
<div className="flex flex-wrap gap-2 border border-gray-300 mt-2 rounded-md p-2 items-center">
{tags.map((tag, index) => (
<div
key={index}
className="flex items-center gap-1 bg-blue-100 text-blue-800 rounded-full px-3 py-1 text-sm font-medium"
>
<span>{tag}</span>
<button
className="text-blue-600 hover:text-blue-800 focus:outline-none"
onClick={() => handleRemoveTag(index)}
>
×
</button>
</div>
))}
</div>
</div>
</Card>
{/* <div className="flex flex-row justify-end gap-3">
<div className="mt-4">
<Button
type="submit"
color="success"
onClick={() => handlePublish()}
>
Publish
</Button>
</div>
<div className="mt-4">
<Button
type="submit"
color="primary"
onClick={() => handleSave()}
>
Submit
</Button>
</div>
<div className="mt-4">
<Button type="submit" color="primary" variant="outline">
Cancel
</Button>
</div>
</div> */}
</div>
</div>
) : (
""
)}
</form>
);
}

View File

@ -0,0 +1,391 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import JoditEditor from "jodit-react";
import { createTask, getTask } from "@/service/task";
import { getContestById } from "@/service/contest/contest";
import page from "@/app/[locale]/page";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { format, parseISO } from "date-fns";
import { Calendar } from "@/components/ui/calendar";
import { DateRange } from "react-day-picker";
const contestSchema = z.object({
theme: z.string().min(1, { message: "Judul diperlukan" }),
hastagCode: z.string().min(1, { message: "Judul diperlukan" }),
description: z.string().min(2, {
message: "Narasi Penugasan harus lebih dari 2 karakter.",
}),
});
export type taskDetail = {
id: number;
theme: string;
hastagCode: string;
assignedToTopLevel: string;
assignmentType: {
id: number;
name: string;
};
assignmentMainType: {
id: number;
name: string;
};
targetOutput: string;
targetParticipantTopLevel: string;
description: string;
is_active: string;
};
export default function FormContestDetail() {
const MySwal = withReactContent(Swal);
const router = useRouter();
const editor = useRef(null);
type ContestSchema = z.infer<typeof contestSchema>;
const { id } = useParams() as { id: string };
console.log(id);
// State for various form fields
const [taskOutput, setTaskOutput] = useState({
all: false,
video: false,
audio: false,
image: 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({
allUnit: false,
mabes: false,
polda: false,
polres: false,
});
const {
control,
handleSubmit,
formState: { errors },
} = useForm<ContestSchema>({
resolver: zodResolver(contestSchema),
});
// const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
// const selectedValue = Number(event.target.value);
// setMainType(selectedValue);
// setPlatformTypeVisible(selectedValue === 2);
// };
useEffect(() => {
async function initState() {
if (id) {
const response = await getContestById(id);
const details = response.data?.data;
setDetail(details);
// if (details?.createdAt) {
// // Memisahkan string duration menjadi start dan end date
// const [startDate, endDate] = details.createdAt.split(" - ");
// setDate({
// from: parseISO(startDate),
// to: parseISO(endDate),
// });
// }
}
}
initState();
}, [id, refresh]);
useEffect(() => {
if (detail?.targetOutput) {
const outputSet = new Set(detail.targetOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor
setTaskOutput({
all: outputSet.has(0),
video: outputSet.has(2),
audio: outputSet.has(4),
image: outputSet.has(1),
text: outputSet.has(3),
});
}
}, [detail?.targetOutput]);
useEffect(() => {
if (detail?.targetParticipantTopLevel) {
const outputSet = new Set(
detail.targetParticipantTopLevel.split(",").map(Number)
);
setUnitSelection({
allUnit: outputSet.has(0),
mabes: outputSet.has(1),
polda: outputSet.has(2),
polres: outputSet.has(3),
});
}
}, [detail?.targetParticipantTopLevel]);
const save = async (data: ContestSchema) => {
const fileTypeMapping = {
all: "1",
video: "2",
audio: "3",
image: "4",
text: "5",
};
const selectedOutputs = Object.keys(taskOutput)
.filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true`
.map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string
.join(",");
const requestData = {
...data,
// assignmentType,
// 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,
};
const response = await createTask(requestData);
console.log("Form Data Submitted:", requestData);
console.log("response", response);
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/task");
});
};
const onSubmit = (data: ContestSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
return (
<Card>
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Contest</p>
{detail !== undefined ? (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5">
<div className="space-y-2">
<Label>Kode Lomba</Label>
<Controller
control={control}
name="hastagCode"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.hastagCode}
onChange={field.onChange}
placeholder="Enter hastagCode"
/>
)}
/>
{errors.hastagCode?.message && (
<p className="text-red-400 text-sm">
{errors.hastagCode.message}
</p>
)}
</div>
{/* Input Title */}
<div className="space-y-2 mt-5">
<Label>Judul Lomba</Label>
<Controller
control={control}
name="theme"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.theme}
onChange={field.onChange}
placeholder="Enter theme"
/>
)}
/>
{errors.theme?.message && (
<p className="text-red-400 text-sm">{errors.theme.message}</p>
)}
</div>
<div className="flex flex-col mt-5">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={1}
/>
</PopoverContent>
</Popover>
</div>
<div className="mt-5">
<Label>Output Lomba</Label>
<div className="flex flex-wrap gap-3 mt-2">
{Object.keys(taskOutput).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={taskOutput[key as keyof typeof taskOutput]}
onCheckedChange={(value) =>
setTaskOutput({ ...taskOutput, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="flex flex-col mt-5">
<Label>Pelaksana Tugas</Label>
<div className="flex flex-row mt-2 gap-2">
{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) =>
setUnitSelection({ ...unitSelection, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Narasi Penugasan</Label>
<Controller
control={control}
name="description"
render={({ field: { onChange, value } }) => (
<JoditEditor
ref={editor}
value={detail?.description}
onChange={onChange}
className="dark:text-black"
/>
)}
/>
{errors.description?.message && (
<p className="text-red-400 text-sm">
{errors.description.message}
</p>
)}
</div>
</div>
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
) : (
""
)}
</div>
</Card>
);
}

View File

@ -0,0 +1,320 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import { Switch } from "@/components/ui/switch";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, parseISO, setDate } from "date-fns";
import { DateRange } from "react-day-picker";
import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
import "react-clock/dist/Clock.css";
import MapHome from "@/components/maps/MapHome";
import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
level: z.string().min(1, { message: "Judul diperlukan" }),
name: z.string().min(1, { message: "Judul diperlukan" }),
location: z.string().min(1, { message: "Judul diperlukan" }),
});
interface Detail {
id: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
addressLat: number;
addressLong: number;
}
export default function FormEventDetail() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
useEffect(() => {
async function initState() {
if (id) {
const response = await detailSchedule(id);
const details = response.data?.data;
setDetail(details);
if (details) {
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
});
}
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
}
}
}
initState();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Event</p>
{detail !== undefined ? (
<div className=" gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul Kegiatan</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
type="text"
value={detail?.title}
onChange={field.onChange}
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Live Streaming</Label>
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
color="primary"
id="c2"
onCheckedChange={(checked) =>
setIsLiveStreamingEnabled(checked)
}
/>
</div>
</div>
</div>
{isLiveStreamingEnabled && (
<div className="mt-1">
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Masukan ID youtube"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between">
<div className="flex flex-col">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={1}
/>
</PopoverContent>
</Popover>
</div>
<div>
<Label htmlFor="title">Rentang Waktu</Label>
<div>
<div className="flex flex-row items-center">
<div className="col-6">
<Input
value={startTime}
type="time"
onChange={handleStartTime}
/>
</div>
<div className="col-6">
<Input
value={endTime}
type="time"
onChange={handleEndTime}
/>
</div>
</div>
</div>
</div>
</div>
<div>
{/* Kirim setValue ke MapHome */}
<MapHome
draggable
setLocation={(location) => setValue("location", location)}
/>
</div>
<div>
<Controller
control={control}
name="location"
render={({ field }) => (
<Textarea
rows={3}
value={detail?.address}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
)}
/>
<div className="invalid-feedback">
{errors.location?.message}
</div>
</div>
<p className="text-sm my-2 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col ">
<div className="mt-1">
<Label>Nama Pangkat</Label>
<Controller
control={control}
name="level"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={detail?.speakerTitle}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
)}
/>
{errors.level?.message && (
<p className="text-red-400 text-sm">
{errors.level.message}
</p>
)}
</div>
</div>
<div className="flex flex-col my-3">
<div className="mt-1">
<Label>Nama Lengkap</Label>
<Controller
control={control}
name="name"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={detail?.speakerName}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>
)}
/>
{errors.name?.message && (
<p className="text-red-400 text-sm">
{errors.name.message}
</p>
)}
</div>
</div>
</div>
) : (
""
)}
{/* Submit Button
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div> */}
</div>
</Card>
<Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</div>
);
}

View File

@ -0,0 +1,400 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import { Switch } from "@/components/ui/switch";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, parseISO, setDate } from "date-fns";
import { DateRange } from "react-day-picker";
import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
import "react-clock/dist/Clock.css";
import MapHome from "@/components/maps/MapHome";
import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
level: z.string().min(1, { message: "Judul diperlukan" }),
name: z.string().min(1, { message: "Judul diperlukan" }),
location: z.string().min(1, { message: "Judul diperlukan" }),
});
interface Detail {
id: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
addressLat: number;
addressLong: number;
}
export default function FormEventUpdate() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const MySwal = withReactContent(Swal);
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
useEffect(() => {
async function initState() {
if (id) {
const response = await detailSchedule(id);
const details = response.data?.data;
setDetail(details);
if (details) {
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
});
}
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
}
}
}
initState();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
const save = async (data: TaskSchema) => {
const requestData: {
id?: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
startTime: string;
endTime: string;
addressLat: string;
addressLong: string;
startDate: string | null;
endDate: string | null;
isYoutube: boolean;
scheduleTypeId: number;
} = {
title: data.title,
address: data.location,
speakerTitle: data.level,
speakerName: data.name,
startTime, // Start time from state
endTime, // End time from state
addressLat: "0.0", // Replace with actual latitude
addressLong: "0.0", // Replace with actual longitude
startDate: date?.from ? format(date.from, "yyyy-MM-dd") : null,
endDate: date?.to ? format(date.to, "yyyy-MM-dd") : null,
isYoutube: isLiveStreamingEnabled,
scheduleTypeId: 2,
};
// Add id property if it exists
if (id) {
requestData.id = parseInt(id, 10); // Ensure id is a number
}
console.log("Form Data Submitted:", requestData);
const response = await postSchedule(requestData);
if (response.error) {
error(response.message);
return false;
}
Cookies.set("scheduleId", response.data.data.id, {
expires: 1,
});
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/schedule/event");
});
};
const onSubmit = (data: TaskSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Event</p>
<form onSubmit={handleSubmit(onSubmit)}>
{detail !== undefined ? (
<div className=" gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul Kegiatan</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
type="text"
defaultValue={detail?.title}
onChange={field.onChange}
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Live Streaming</Label>
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
color="primary"
id="c2"
onCheckedChange={(checked) =>
setIsLiveStreamingEnabled(checked)
}
/>
</div>
</div>
</div>
{isLiveStreamingEnabled && (
<div className="mt-1">
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Masukan ID youtube"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between">
<div className="flex flex-col">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={1}
/>
</PopoverContent>
</Popover>
</div>
<div>
<Label htmlFor="title">Rentang Waktu</Label>
<div>
<div className="flex flex-row items-center">
<div className="col-6">
<Input
value={startTime}
type="time"
onChange={handleStartTime}
/>
</div>
<div className="col-6">
<Input
value={endTime}
type="time"
onChange={handleEndTime}
/>
</div>
</div>
</div>
</div>
</div>
<div>
{/* Kirim setValue ke MapHome */}
<MapHome
draggable
setLocation={(location) => setValue("location", location)}
/>
</div>
<div>
<Controller
control={control}
name="location"
render={({ field }) => (
<Textarea
rows={3}
defaultValue={detail?.address}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
)}
/>
<div className="invalid-feedback">
{errors.location?.message}
</div>
</div>
<p className="text-sm my-2 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col ">
<div className="mt-1">
<Label>Nama Pangkat</Label>
<Controller
control={control}
name="level"
render={({ field }) => (
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerTitle}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
)}
/>
{errors.level?.message && (
<p className="text-red-400 text-sm">
{errors.level.message}
</p>
)}
</div>
</div>
<div className="flex flex-col my-3">
<div className="mt-1">
<Label>Nama Lengkap</Label>
<Controller
control={control}
name="name"
render={({ field }) => (
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerName}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>
)}
/>
{errors.name?.message && (
<p className="text-red-400 text-sm">
{errors.name.message}
</p>
)}
</div>
</div>
</div>
) : (
""
)}
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
</div>
</Card>
<Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</div>
);
}

View File

@ -0,0 +1,345 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import { Switch } from "@/components/ui/switch";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, parseISO, setDate } from "date-fns";
import { DateRange } from "react-day-picker";
import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
import "react-clock/dist/Clock.css";
import MapHome from "@/components/maps/MapHome";
import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
level: z.string().min(1, { message: "Judul diperlukan" }),
name: z.string().min(1, { message: "Judul diperlukan" }),
location: z.string().min(1, { message: "Judul diperlukan" }),
});
interface Detail {
id: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
addressLat: number;
addressLong: number;
}
export default function FormDetailPressRillis() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
const [selectedTarget, setSelectedTarget] = useState("all");
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
useEffect(() => {
async function initState() {
if (id) {
const response = await detailSchedule(id);
const details = response.data?.data;
setDetail(details);
if (details) {
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
});
}
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
}
}
}
initState();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Pers Rilis</p>
{detail !== undefined ? (
<div className=" gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul Kegiatan</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
type="text"
value={detail?.title}
onChange={field.onChange}
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Live Streaming</Label>
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
color="primary"
id="c2"
onCheckedChange={(checked) =>
setIsLiveStreamingEnabled(checked)
}
/>
</div>
</div>
</div>
{isLiveStreamingEnabled && (
<div className="mt-1">
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Masukan ID youtube"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between">
<div className="flex flex-col">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={1}
/>
</PopoverContent>
</Popover>
</div>
<div>
<Label htmlFor="title">Rentang Waktu</Label>
<div>
<div className="flex flex-row items-center">
<div className="col-6">
<Input
value={startTime}
type="time"
onChange={handleStartTime}
/>
</div>
<div className="col-6">
<Input
value={endTime}
type="time"
onChange={handleEndTime}
/>
</div>
</div>
</div>
</div>
</div>
<div>
{/* Kirim setValue ke MapHome */}
<MapHome
draggable
setLocation={(location) => setValue("location", location)}
/>
</div>
<div>
<Controller
control={control}
name="location"
render={({ field }) => (
<Textarea
rows={3}
value={detail?.address}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
)}
/>
<div className="invalid-feedback">
{errors.location?.message}
</div>
</div>
<div className="mt-5">
<Label>Invitation</Label>
<Select onValueChange={setSelectedTarget}>
<SelectTrigger size="md">
<SelectValue placeholder="Pilih" />
</SelectTrigger>
<SelectContent>
<SelectItem value="kompas">
PT. kompas Cyber Media{" "}
</SelectItem>
<SelectItem value="trans">
PT. Trans Digital Media
</SelectItem>
<SelectItem value="mnc">MNC</SelectItem>
</SelectContent>
</Select>
</div>
<p className="text-sm my-2 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col ">
<div className="mt-1">
<Label>Nama Pangkat</Label>
<Controller
control={control}
name="level"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={detail?.speakerTitle}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
)}
/>
{errors.level?.message && (
<p className="text-red-400 text-sm">
{errors.level.message}
</p>
)}
</div>
</div>
<div className="flex flex-col my-3">
<div className="mt-1">
<Label>Nama Lengkap</Label>
<Controller
control={control}
name="name"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={detail?.speakerName}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>
)}
/>
{errors.name?.message && (
<p className="text-red-400 text-sm">
{errors.name.message}
</p>
)}
</div>
</div>
</div>
) : (
""
)}
{/* Submit Button
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div> */}
</div>
</Card>
<Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</div>
);
}

View File

@ -0,0 +1,424 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import { Switch } from "@/components/ui/switch";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, parseISO, setDate } from "date-fns";
import { DateRange } from "react-day-picker";
import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
import "react-clock/dist/Clock.css";
import MapHome from "@/components/maps/MapHome";
import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
level: z.string().min(1, { message: "Judul diperlukan" }),
name: z.string().min(1, { message: "Judul diperlukan" }),
location: z.string().min(1, { message: "Judul diperlukan" }),
});
interface Detail {
id: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
addressLat: number;
addressLong: number;
}
export default function FormUpdatePressRelease() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const MySwal = withReactContent(Swal);
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
const [selectedTarget, setSelectedTarget] = useState("all");
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
useEffect(() => {
async function initState() {
if (id) {
const response = await detailSchedule(id);
const details = response.data?.data;
setDetail(details);
if (details) {
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
});
}
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
}
}
}
initState();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
const save = async (data: TaskSchema) => {
const requestData: {
id?: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
startTime: string;
endTime: string;
addressLat: string;
addressLong: string;
startDate: string | null;
endDate: string | null;
isYoutube: boolean;
scheduleTypeId: number;
} = {
title: data.title,
address: data.location,
speakerTitle: data.level,
speakerName: data.name,
startTime, // Start time from state
endTime, // End time from state
addressLat: "0.0", // Replace with actual latitude
addressLong: "0.0", // Replace with actual longitude
startDate: date?.from ? format(date.from, "yyyy-MM-dd") : null,
endDate: date?.to ? format(date.to, "yyyy-MM-dd") : null,
isYoutube: isLiveStreamingEnabled,
scheduleTypeId: 3,
};
// Add id property if it exists
if (id) {
requestData.id = parseInt(id, 10); // Ensure id is a number
}
console.log("Form Data Submitted:", requestData);
const response = await postSchedule(requestData);
if (response.error) {
error(response.message);
return false;
}
Cookies.set("scheduleId", response.data.data.id, {
expires: 1,
});
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/schedule/press-release");
});
};
const onSubmit = (data: TaskSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Konferensi Pers</p>
<form onSubmit={handleSubmit(onSubmit)}>
{detail !== undefined ? (
<div className=" gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul Kegiatan</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
type="text"
defaultValue={detail?.title}
onChange={field.onChange}
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Live Streaming</Label>
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
color="primary"
id="c2"
onCheckedChange={(checked) =>
setIsLiveStreamingEnabled(checked)
}
/>
</div>
</div>
</div>
{isLiveStreamingEnabled && (
<div className="mt-1">
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Masukan ID youtube"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between">
<div className="flex flex-col">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={1}
/>
</PopoverContent>
</Popover>
</div>
<div>
<Label htmlFor="title">Rentang Waktu</Label>
<div>
<div className="flex flex-row items-center">
<div className="col-6">
<Input
value={startTime}
type="time"
onChange={handleStartTime}
/>
</div>
<div className="col-6">
<Input
value={endTime}
type="time"
onChange={handleEndTime}
/>
</div>
</div>
</div>
</div>
</div>
<div>
{/* Kirim setValue ke MapHome */}
<MapHome
draggable
setLocation={(location) => setValue("location", location)}
/>
</div>
<div>
<Controller
control={control}
name="location"
render={({ field }) => (
<Textarea
rows={3}
defaultValue={detail?.address}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
)}
/>
<div className="invalid-feedback">
{errors.location?.message}
</div>
</div>
<div className="mt-5">
<Label>Invitation</Label>
<Select onValueChange={setSelectedTarget}>
<SelectTrigger size="md">
<SelectValue placeholder="Pilih" />
</SelectTrigger>
<SelectContent>
<SelectItem value="kompas">
PT. kompas Cyber Media{" "}
</SelectItem>
<SelectItem value="trans">
PT. Trans Digital Media
</SelectItem>
<SelectItem value="mnc">MNC</SelectItem>
</SelectContent>
</Select>
</div>
<p className="text-sm my-2 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col ">
<div className="mt-1">
<Label>Nama Pangkat</Label>
<Controller
control={control}
name="level"
render={({ field }) => (
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerTitle}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
)}
/>
{errors.level?.message && (
<p className="text-red-400 text-sm">
{errors.level.message}
</p>
)}
</div>
</div>
<div className="flex flex-col my-3">
<div className="mt-1">
<Label>Nama Lengkap</Label>
<Controller
control={control}
name="name"
render={({ field }) => (
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerName}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>
)}
/>
{errors.name?.message && (
<p className="text-red-400 text-sm">
{errors.name.message}
</p>
)}
</div>
</div>
</div>
) : (
""
)}
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
</div>
</Card>
<Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</div>
);
}

View File

@ -129,7 +129,7 @@ export default function FormPressRelease() {
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/contributor/schedule/press-release");
router.push("/en/contributor/schedule/press-release");
});
};

View File

@ -10,16 +10,6 @@ import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import JoditEditor from "jodit-react";
import { Switch } from "@/components/ui/switch";
import {
Popover,
@ -29,7 +19,7 @@ import {
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, setDate } from "date-fns";
import { addDays, format, parseISO, setDate } from "date-fns";
import { DateRange } from "react-day-picker";
import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
@ -39,7 +29,6 @@ import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
import { id } from "date-fns/locale";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@ -49,6 +38,7 @@ const taskSchema = z.object({
});
interface Detail {
id: number;
title: string;
address: string;
speakerTitle: string;
@ -57,27 +47,17 @@ interface Detail {
addressLong: number;
}
export default function FormDetailPressConference(props: { id: any }) {
export default function FormDetailPressConference() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const id = props.id;
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
const [date, setDate] = React.useState<DateRange | undefined>({
from: new Date(2024, 0, 1),
});
const handleStartTime = (e: any) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: any) => {
setEndTime(e.target.value);
};
const [detail, setDetail] = useState<Detail | null>(null);
const [dataForm, setDataForm] = useState(null);
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
@ -94,35 +74,34 @@ export default function FormDetailPressConference(props: { id: any }) {
useEffect(() => {
async function initState() {
try {
loading();
if (id) {
const response = await detailSchedule(id);
const details = response.data?.data;
console.log("res", id, response?.data?.data);
if (details) {
setDetail(details);
setValue("title", details.title || "");
setValue("location", details.address || "");
setValue("level", details.speakerTitle || "");
setValue("name", details.speakerName || "");
Cookies.set("map_lat", details.addressLat, {
secure: true,
sameSite: "strict",
});
Cookies.set("map_long", details.addressLong, {
secure: true,
sameSite: "strict",
setDetail(details);
if (details) {
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
});
}
Swal.close();
} catch (err) {
Swal.fire("Error", "Failed to fetch details", "error");
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
}
}
}
initState();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
@ -189,7 +168,7 @@ export default function FormDetailPressConference(props: { id: any }) {
)}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between">
<div className="flex flex-col ">
<div className="flex flex-col">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
@ -230,20 +209,20 @@ export default function FormDetailPressConference(props: { id: any }) {
</div>
<div>
<Label htmlFor="title">Rentang Waktu</Label>
<div className="">
<div>
<div className="flex flex-row items-center">
<div className="col-6">
<Input
defaultValue="08:00"
value={startTime}
type="time"
onChange={(e) => handleStartTime(e)}
onChange={handleStartTime}
/>
</div>
<div className="col-6">
<Input
defaultValue="09:00"
value={endTime}
type="time"
onChange={(e) => handleEndTime(e)}
onChange={handleEndTime}
/>
</div>
</div>
@ -264,7 +243,7 @@ export default function FormDetailPressConference(props: { id: any }) {
render={({ field }) => (
<Textarea
rows={3}
value={field.value}
value={detail?.address}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
@ -285,7 +264,7 @@ export default function FormDetailPressConference(props: { id: any }) {
<Input
size={"md"}
type="text"
value={field.value}
value={detail?.speakerTitle}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
@ -308,7 +287,7 @@ export default function FormDetailPressConference(props: { id: any }) {
<Input
size={"md"}
type="text"
value={field.value}
value={detail?.speakerName}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>

View File

@ -10,16 +10,6 @@ import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useRouter } from "next/navigation";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import JoditEditor from "jodit-react";
import { Switch } from "@/components/ui/switch";
import {
Popover,

View File

@ -0,0 +1,400 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import { Switch } from "@/components/ui/switch";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, parseISO, setDate } from "date-fns";
import { DateRange } from "react-day-picker";
import TimePicker from "react-time-picker";
import "react-time-picker/dist/TimePicker.css";
import "react-clock/dist/Clock.css";
import MapHome from "@/components/maps/MapHome";
import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
level: z.string().min(1, { message: "Judul diperlukan" }),
name: z.string().min(1, { message: "Judul diperlukan" }),
location: z.string().min(1, { message: "Judul diperlukan" }),
});
interface Detail {
id: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
addressLat: number;
addressLong: number;
}
export default function FormUpdatePressConference() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const MySwal = withReactContent(Swal);
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
useEffect(() => {
async function initState() {
if (id) {
const response = await detailSchedule(id);
const details = response.data?.data;
setDetail(details);
if (details) {
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
});
}
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
}
}
}
initState();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
const save = async (data: TaskSchema) => {
const requestData: {
id?: number;
title: string;
address: string;
speakerTitle: string;
speakerName: string;
startTime: string;
endTime: string;
addressLat: string;
addressLong: string;
startDate: string | null;
endDate: string | null;
isYoutube: boolean;
scheduleTypeId: number;
} = {
title: data.title,
address: data.location,
speakerTitle: data.level,
speakerName: data.name,
startTime, // Start time from state
endTime, // End time from state
addressLat: "0.0", // Replace with actual latitude
addressLong: "0.0", // Replace with actual longitude
startDate: date?.from ? format(date.from, "yyyy-MM-dd") : null,
endDate: date?.to ? format(date.to, "yyyy-MM-dd") : null,
isYoutube: isLiveStreamingEnabled,
scheduleTypeId: 1,
};
// Add id property if it exists
if (id) {
requestData.id = parseInt(id, 10); // Ensure id is a number
}
console.log("Form Data Submitted:", requestData);
const response = await postSchedule(requestData);
if (response.error) {
error(response.message);
return false;
}
Cookies.set("scheduleId", response.data.data.id, {
expires: 1,
});
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/schedule/press-conference");
});
};
const onSubmit = (data: TaskSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Konferensi Pers</p>
<form onSubmit={handleSubmit(onSubmit)}>
{detail !== undefined ? (
<div className=" gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul Kegiatan</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
type="text"
defaultValue={detail?.title}
onChange={field.onChange}
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Live Streaming</Label>
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
color="primary"
id="c2"
onCheckedChange={(checked) =>
setIsLiveStreamingEnabled(checked)
}
/>
</div>
</div>
</div>
{isLiveStreamingEnabled && (
<div className="mt-1">
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Masukan ID youtube"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between">
<div className="flex flex-col">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={1}
/>
</PopoverContent>
</Popover>
</div>
<div>
<Label htmlFor="title">Rentang Waktu</Label>
<div>
<div className="flex flex-row items-center">
<div className="col-6">
<Input
value={startTime}
type="time"
onChange={handleStartTime}
/>
</div>
<div className="col-6">
<Input
value={endTime}
type="time"
onChange={handleEndTime}
/>
</div>
</div>
</div>
</div>
</div>
<div>
{/* Kirim setValue ke MapHome */}
<MapHome
draggable
setLocation={(location) => setValue("location", location)}
/>
</div>
<div>
<Controller
control={control}
name="location"
render={({ field }) => (
<Textarea
rows={3}
defaultValue={detail?.address}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
)}
/>
<div className="invalid-feedback">
{errors.location?.message}
</div>
</div>
<p className="text-sm my-2 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col ">
<div className="mt-1">
<Label>Nama Pangkat</Label>
<Controller
control={control}
name="level"
render={({ field }) => (
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerTitle}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
)}
/>
{errors.level?.message && (
<p className="text-red-400 text-sm">
{errors.level.message}
</p>
)}
</div>
</div>
<div className="flex flex-col my-3">
<div className="mt-1">
<Label>Nama Lengkap</Label>
<Controller
control={control}
name="name"
render={({ field }) => (
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerName}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>
)}
/>
{errors.name?.message && (
<p className="text-red-400 text-sm">
{errors.name.message}
</p>
)}
</div>
</div>
</div>
) : (
""
)}
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
</div>
</Card>
<Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</div>
);
}

View File

@ -0,0 +1,396 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Card } from "@/components/ui/card";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import JoditEditor from "jodit-react";
import { createTask, getTask } from "@/service/task";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
naration: z.string().min(2, {
message: "Narasi Penugasan harus lebih dari 2 karakter.",
}),
});
export type taskDetail = {
id: number;
title: string;
fileTypeOutput: string;
assignedToTopLevel: string;
assignmentType: {
id: number;
name: string;
};
assignmentMainType: {
id: number;
name: string;
};
taskType: string;
broadcastType: string;
narration: string;
is_active: string;
};
export default function FormTaskDetail() {
const MySwal = withReactContent(Swal);
const router = useRouter();
const editor = useRef(null);
type TaskSchema = z.infer<typeof taskSchema>;
const { id } = useParams() as { id: string };
console.log(id);
// State for various form fields
const [taskOutput, setTaskOutput] = useState({
all: false,
video: false,
audio: false,
image: 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 [platformTypeVisible, setPlatformTypeVisible] = useState(false);
const [unitSelection, setUnitSelection] = useState({
allUnit: false,
mabes: false,
polda: false,
polres: false,
});
const {
control,
handleSubmit,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
});
// const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
// const selectedValue = Number(event.target.value);
// setMainType(selectedValue);
// setPlatformTypeVisible(selectedValue === 2);
// };
useEffect(() => {
async function initState() {
if (id) {
const response = await getTask(id);
const details = response.data?.data;
setDetail(details);
}
}
initState();
}, [id, refresh]);
useEffect(() => {
if (detail?.broadcastType) {
setBroadcastType(detail.broadcastType); // Mengatur nilai broadcastType dari API
}
}, [detail?.broadcastType]);
useEffect(() => {
if (detail?.fileTypeOutput) {
const outputSet = new Set(detail.fileTypeOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor
setTaskOutput({
all: outputSet.has(0),
video: outputSet.has(2),
audio: outputSet.has(4),
image: outputSet.has(1),
text: outputSet.has(3),
});
}
}, [detail?.fileTypeOutput]);
useEffect(() => {
if (detail?.assignedToTopLevel) {
const outputSet = new Set(
detail.assignedToTopLevel.split(",").map(Number)
);
setUnitSelection({
allUnit: outputSet.has(0),
mabes: outputSet.has(1),
polda: outputSet.has(2),
polres: outputSet.has(3),
});
}
}, [detail?.fileTypeOutput]);
const save = async (data: TaskSchema) => {
const fileTypeMapping = {
all: "1",
video: "2",
audio: "3",
image: "4",
text: "5",
};
const selectedOutputs = Object.keys(taskOutput)
.filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true`
.map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string
.join(",");
const requestData = {
...data,
// assignmentType,
// assignmentCategory,
target: selectedTarget,
unitSelection,
assignedToRole: "3",
taskType: taskType,
broadcastType: broadcastType,
assignmentMainTypeId: mainType,
assignmentPurpose: "1",
assignmentTypeId: type,
fileTypeOutput: selectedOutputs,
id: null,
narration: data.naration,
platformType: "",
title: data.title,
};
const response = await createTask(requestData);
console.log("Form Data Submitted:", requestData);
console.log("response", response);
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/task");
});
};
const onSubmit = (data: TaskSchema) => {
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Simpan",
}).then((result) => {
if (result.isConfirmed) {
save(data);
}
});
};
return (
<Card>
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Penugasan</p>
{detail !== undefined ? (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.title}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Tujuan Pemilihan Tugas</Label>
<Select onValueChange={setSelectedTarget}>
<SelectTrigger size="md">
<SelectValue placeholder="Pilih" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Semua Pengguna</SelectItem>
<SelectItem value="contributor">Kontributor</SelectItem>
<SelectItem value="approver">Approver</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex flex-wrap gap-3 mt-5 pt-5 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) =>
setUnitSelection({ ...unitSelection, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Tipe Penugasan</Label>
<RadioGroup
value={detail.assignmentMainType.id.toString()} // State yang dipetakan ke value RadioGroup
onValueChange={(value) => setMainType(value)}
// value={String(mainType)}
// onValueChange={(value) => setMainType(Number(value))}
className="flex flex-wrap gap-3"
>
<RadioGroupItem value="1" id="mediahub" />
<Label htmlFor="mediahub">Mediahub</Label>
<RadioGroupItem value="2" id="medsos-mediahub" />
<Label htmlFor="medsos-mediahub">Medsos Mediahub</Label>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Jenis Tugas </Label>
<RadioGroup
value={detail.taskType.toString()}
onValueChange={(value) => setTaskType(String(value))}
className="flex flex-wrap gap-3"
>
<RadioGroupItem value="atensi-khusus" id="khusus" />
<Label htmlFor="atensi-khusus">Atensi Khusus</Label>
<RadioGroupItem value="tugas-harian" id="harian" />
<Label htmlFor="tugas-harian">Tugas Harian</Label>
</RadioGroup>
</div>
{/* RadioGroup Assignment Category */}
<div className="mt-5">
<Label>Jenis Penugasan</Label>
<RadioGroup
value={detail.assignmentType.id.toString()} // State yang dipetakan ke value RadioGroup
onValueChange={(value) => setType(value)} // Mengubah nilai state ketika pilihan berubah
className="flex flex-wrap gap-3"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="1" id="publication" />
<Label htmlFor="publication">Publikasi</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="2" id="amplification" />
<Label htmlFor="amplification">Amplifikasi</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="3" id="contra" />
<Label htmlFor="contra">Kontra</Label>
</div>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Output Tugas</Label>
<div className="flex flex-wrap gap-3">
{Object.keys(taskOutput).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={taskOutput[key as keyof typeof taskOutput]}
onCheckedChange={(value) =>
setTaskOutput({ ...taskOutput, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Broadcast </Label>
<RadioGroup
value={broadcastType} // Nilai terpilih diambil dari state broadcastType
onValueChange={(value) => setBroadcastType(value)} // Mengatur nilai saat radio berubah
className="flex flex-wrap gap-3"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="all" id="all" />
<Label htmlFor="all">Semua</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="email" id="email" />
<Label htmlFor="email">Email Blast</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="whatsapp" id="whatsapp" />
<Label htmlFor="whatsapp">WhatsApp Blast</Label>
</div>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Narasi Penugasan</Label>
<Controller
control={control}
name="naration"
render={({ field: { onChange, value } }) => (
<JoditEditor
ref={editor}
value={detail?.narration}
onChange={onChange}
className="dark:text-black"
/>
)}
/>
{errors.naration?.message && (
<p className="text-red-400 text-sm">
{errors.naration.message}
</p>
)}
</div>
</div>
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
) : (
""
)}
</div>
</Card>
);
}

View File

@ -98,51 +98,6 @@ export default function FormTask() {
// setPlatformTypeVisible(selectedValue === 2);
// };
useEffect(() => {
async function initState() {
if (id) {
const response = await getTask(id);
const details = response.data?.data;
setDetail(details);
}
}
initState();
}, [id, refresh]);
useEffect(() => {
if (detail?.broadcastType) {
setBroadcastType(detail.broadcastType); // Mengatur nilai broadcastType dari API
}
}, [detail?.broadcastType]);
useEffect(() => {
if (detail?.fileTypeOutput) {
const outputSet = new Set(detail.fileTypeOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor
setTaskOutput({
all: outputSet.has(0),
video: outputSet.has(2),
audio: outputSet.has(4),
image: outputSet.has(1),
text: outputSet.has(3),
});
}
}, [detail?.fileTypeOutput]);
useEffect(() => {
if (detail?.assignedToTopLevel) {
const outputSet = new Set(
detail.assignedToTopLevel.split(",").map(Number)
);
setUnitSelection({
allUnit: outputSet.has(0),
mabes: outputSet.has(1),
polda: outputSet.has(2),
polres: outputSet.has(3),
});
}
}, [detail?.fileTypeOutput]);
const save = async (data: TaskSchema) => {
const fileTypeMapping = {
all: "1",
@ -212,184 +167,179 @@ export default function FormTask() {
<Card>
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Penugasan</p>
{detail !== undefined ? (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.title}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Tujuan Pemilihan Tugas</Label>
<Select onValueChange={setSelectedTarget}>
<SelectTrigger size="md">
<SelectValue placeholder="Pilih" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Semua Pengguna</SelectItem>
<SelectItem value="contributor">Kontributor</SelectItem>
<SelectItem value="approver">Approver</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex flex-wrap gap-3 mt-5 pt-5 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) =>
setUnitSelection({ ...unitSelection, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Tipe Penugasan</Label>
<RadioGroup
value={detail.assignmentMainType.id.toString()} // State yang dipetakan ke value RadioGroup
onValueChange={(value) => setMainType(value)}
// value={String(mainType)}
// onValueChange={(value) => setMainType(Number(value))}
className="flex flex-wrap gap-3"
>
<RadioGroupItem value="1" id="mediahub" />
<Label htmlFor="mediahub">Mediahub</Label>
<RadioGroupItem value="2" id="medsos-mediahub" />
<Label htmlFor="medsos-mediahub">Medsos Mediahub</Label>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Jenis Tugas </Label>
<RadioGroup
value={detail.taskType.toString()}
onValueChange={(value) => setTaskType(String(value))}
className="flex flex-wrap gap-3"
>
<RadioGroupItem value="atensi-khusus" id="khusus" />
<Label htmlFor="atensi-khusus">Atensi Khusus</Label>
<RadioGroupItem value="tugas-harian" id="harian" />
<Label htmlFor="tugas-harian">Tugas Harian</Label>
</RadioGroup>
</div>
{/* RadioGroup Assignment Category */}
<div className="mt-5">
<Label>Jenis Penugasan</Label>
<RadioGroup
value={detail.assignmentType.id.toString()} // State yang dipetakan ke value RadioGroup
onValueChange={(value) => setType(value)} // Mengubah nilai state ketika pilihan berubah
className="flex flex-wrap gap-3"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="1" id="publication" />
<Label htmlFor="publication">Publikasi</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="2" id="amplification" />
<Label htmlFor="amplification">Amplifikasi</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="3" id="contra" />
<Label htmlFor="contra">Kontra</Label>
</div>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Output Tugas</Label>
<div className="flex flex-wrap gap-3">
{Object.keys(taskOutput).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={taskOutput[key as keyof typeof taskOutput]}
onCheckedChange={(value) =>
setTaskOutput({ ...taskOutput, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Broadcast </Label>
<RadioGroup
value={broadcastType} // Nilai terpilih diambil dari state broadcastType
onValueChange={(value) => setBroadcastType(value)} // Mengatur nilai saat radio berubah
className="flex flex-wrap gap-3"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="all" id="all" />
<Label htmlFor="all">Semua</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="email" id="email" />
<Label htmlFor="email">Email Blast</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="whatsapp" id="whatsapp" />
<Label htmlFor="whatsapp">WhatsApp Blast</Label>
</div>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Narasi Penugasan</Label>
<Controller
control={control}
name="naration"
render={({ field: { onChange, value } }) => (
<JoditEditor
ref={editor}
value={detail?.narration}
onChange={onChange}
className="dark:text-black"
/>
)}
/>
{errors.naration?.message && (
<p className="text-red-400 text-sm">
{errors.naration.message}
</p>
)}
</div>
</div>
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
<Label>Judul</Label>
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size="md"
type="text"
value={detail?.title}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
</form>
) : (
""
)}
<div className="flex flex-row items-center">
<div className="mt-5">
<Label>Tujuan Pemilihan Tugas</Label>
<Select onValueChange={setSelectedTarget}>
<SelectTrigger size="md">
<SelectValue placeholder="Pilih" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Semua Pengguna</SelectItem>
<SelectItem value="contributor">Kontributor</SelectItem>
<SelectItem value="approver">Approver</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex flex-wrap gap-3 mt-5 pt-5 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) =>
setUnitSelection({ ...unitSelection, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Tipe Penugasan</Label>
<RadioGroup
value={mainType} // State yang dipetakan ke value RadioGroup
onValueChange={(value) => setMainType(value)}
// value={String(mainType)}
// onValueChange={(value) => setMainType(Number(value))}
className="flex flex-wrap gap-3"
>
<RadioGroupItem value="1" id="mediahub" />
<Label htmlFor="mediahub">Mediahub</Label>
<RadioGroupItem value="2" id="medsos-mediahub" />
<Label htmlFor="medsos-mediahub">Medsos Mediahub</Label>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Jenis Tugas </Label>
<RadioGroup
value={taskType}
onValueChange={(value) => setTaskType(String(value))}
className="flex flex-wrap gap-3"
>
<RadioGroupItem value="atensi-khusus" id="khusus" />
<Label htmlFor="atensi-khusus">Atensi Khusus</Label>
<RadioGroupItem value="tugas-harian" id="harian" />
<Label htmlFor="tugas-harian">Tugas Harian</Label>
</RadioGroup>
</div>
{/* RadioGroup Assignment Category */}
<div className="mt-5">
<Label>Jenis Penugasan</Label>
<RadioGroup
value={type} // State yang dipetakan ke value RadioGroup
onValueChange={(value) => setType(value)} // Mengubah nilai state ketika pilihan berubah
className="flex flex-wrap gap-3"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="1" id="publication" />
<Label htmlFor="publication">Publikasi</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="2" id="amplification" />
<Label htmlFor="amplification">Amplifikasi</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="3" id="contra" />
<Label htmlFor="contra">Kontra</Label>
</div>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Output Tugas</Label>
<div className="flex flex-wrap gap-3">
{Object.keys(taskOutput).map((key) => (
<div className="flex items-center gap-2" key={key}>
<Checkbox
id={key}
checked={taskOutput[key as keyof typeof taskOutput]}
onCheckedChange={(value) =>
setTaskOutput({ ...taskOutput, [key]: value })
}
/>
<Label htmlFor={key}>
{key.charAt(0).toUpperCase() + key.slice(1)}
</Label>
</div>
))}
</div>
</div>
<div className="mt-5">
<Label>Broadcast </Label>
<RadioGroup
value={broadcastType} // Nilai terpilih diambil dari state broadcastType
onValueChange={(value) => setBroadcastType(value)} // Mengatur nilai saat radio berubah
className="flex flex-wrap gap-3"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="all" id="all" />
<Label htmlFor="all">Semua</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="email" id="email" />
<Label htmlFor="email">Email Blast</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="whatsapp" id="whatsapp" />
<Label htmlFor="whatsapp">WhatsApp Blast</Label>
</div>
</RadioGroup>
</div>
<div className="mt-5">
<Label>Narasi Penugasan</Label>
<Controller
control={control}
name="naration"
render={({ field: { onChange, value } }) => (
<JoditEditor
ref={editor}
value={value}
onChange={onChange}
className="dark:text-black"
/>
)}
/>
{errors.naration?.message && (
<p className="text-red-400 text-sm">
{errors.naration.message}
</p>
)}
</div>
</div>
{/* Submit Button */}
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</form>
</div>
</Card>
);

View File

@ -1,6 +1,6 @@
import { title } from "process";
import { httpGetInterceptor } from "../http-config/http-interceptor-service";
import { postAPIInterceptor } from "@/config/api";
import { getAPIInterceptor, postAPIInterceptor } from "@/config/api";
export async function paginationBlog(
size: number,
@ -16,3 +16,8 @@ export async function postBlog(data: any) {
const url = "blog";
return postAPIInterceptor(url, data);
}
export async function getBlog(id: any) {
const url = `blog/${id}`;
return getAPIInterceptor(url);
}

View File

@ -1,3 +1,4 @@
import { getAPIInterceptor } from "@/config/api";
import {
httpGetInterceptor,
httpPostInterceptor,
@ -17,3 +18,8 @@ export async function createTask(data: any) {
const url = "assignment";
return httpPostInterceptor(url, data);
}
export async function getContestById(id: any, pages = 0) {
const url = `contest?id=${id}&page=${pages}`;
return getAPIInterceptor(url);
}

View File

@ -3,8 +3,15 @@ import { httpGetInterceptor } from "../http-config/http-interceptor-service";
import { type } from "os";
import { getAPI, getAPIInterceptor, postAPIInterceptor } from "@/config/api";
export async function paginationSchedule(size: number, page: number, type: any, title: string = "") {
return await httpGetInterceptor(`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`);
export async function paginationSchedule(
size: number,
page: number,
type: any,
title: string = ""
) {
return await httpGetInterceptor(
`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`
);
}
export async function postSchedule(data: any) {
@ -14,7 +21,7 @@ export async function postSchedule(data: any) {
export async function detailSchedule(id: any) {
const url = `public/schedule?id=${id}`;
return getAPIInterceptor({ url });
return getAPIInterceptor(url);
}
export async function listScheduleTodayPublic(group = null) {