diff --git a/app/[locale]/(protected)/admin/settings/category/component/table.tsx b/app/[locale]/(protected)/admin/settings/category/component/table.tsx index ffcfd2dd..19fe6628 100644 --- a/app/[locale]/(protected)/admin/settings/category/component/table.tsx +++ b/app/[locale]/(protected)/admin/settings/category/component/table.tsx @@ -45,6 +45,11 @@ import { } from "@/components/ui/dialog"; import CreateCategoryModal from "./create"; import { useTranslations } from "next-intl"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; const AdminCategoryTable = () => { const router = useRouter(); @@ -55,6 +60,9 @@ const AdminCategoryTable = () => { const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); const [sorting, setSorting] = React.useState([]); + const [region, setRegion] = React.useState(); + const [regionFilter, setRegionFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] ); @@ -89,6 +97,14 @@ const AdminCategoryTable = () => { }, }); + const manualRegions = [ + { id: "semua", label: "Semua" }, + { id: "mabes", label: "Mabes" }, + { id: "polda", label: "Polda" }, + { id: "satker", label: "Satker" }, + { id: "internasional", label: "Internasional" }, + ]; + React.useEffect(() => { if (dataChange) { router.push("/admin/settings/category"); @@ -105,14 +121,28 @@ const AdminCategoryTable = () => { React.useEffect(() => { fetchData(); - }, [page]); + }, [page, regionFilter]); async function fetchData() { try { loading(); - const response = await getCategories(page - 1); + + const regionQuery = regionFilter.length + ? `&publishedLocation=${regionFilter.join(",")}` + : ""; + + const statusQuery = statusFilter.length + ? `&isPublish=${statusFilter.join(",")}` + : ""; + + const response = await getCategories( + page - 1, + `${regionQuery}${statusQuery}` + ); + const data = response?.data?.data; const contentData = data?.content; + contentData.forEach((item: any, index: number) => { item.no = (page - 1) * 10 + index + 1; }); @@ -122,17 +152,124 @@ const AdminCategoryTable = () => { setTotalPage(data?.totalPages); close(); } catch (error) { - console.error("Error fetching tasks:", error); + console.error("Error fetching categories:", error); } } + const handleChange = (type: string, id: string, checked: boolean) => { + if (type === "region") { + if (id === "semua") { + if (checked) { + // Pilih semua (kecuali 'semua' itu sendiri) + setRegionFilter(["mabes", "polda", "satker", "internasional"]); + } else { + setRegionFilter([]); + } + } else { + let updated = checked + ? [...regionFilter, id] + : regionFilter.filter((val) => val !== id); + + // Jika semua sudah tercentang, maka otomatis centang "semua" + const allIds = ["mabes", "polda", "satker", "internasional"]; + const allSelected = allIds.every((val) => updated.includes(val)); + + setRegionFilter(allSelected ? allIds : updated); + } + } else { + if (checked) { + setStatusFilter([...statusFilter, id]); + } else { + setStatusFilter(statusFilter.filter((val: any) => val !== id)); + } + } + }; + return (

{t("category")}

- +
+ + + + + +
+ +
+

Wilayah

+ {manualRegions.map((region) => ( +
+ regionFilter.includes(val) + ) + : regionFilter.includes(region.id) + } + onCheckedChange={(e) => + handleChange("region", region.id, Boolean(e)) + } + /> + +
+ ))} +

Status

+
+ + handleChange("status", "true", Boolean(e)) + } + /> + +
+
+ + handleChange("status", "false", Boolean(e)) + } + /> + +
+
+
+
+
+
{table.getHeaderGroups().map((headerGroup) => ( diff --git a/app/[locale]/(protected)/supervisor/communications/account-report/components/column.tsx b/app/[locale]/(protected)/supervisor/communications/account-report/components/column.tsx index 827a8b7d..dce71a9b 100644 --- a/app/[locale]/(protected)/supervisor/communications/account-report/components/column.tsx +++ b/app/[locale]/(protected)/supervisor/communications/account-report/components/column.tsx @@ -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 "@/i18n/routing"; const columns: ColumnDef[] = [ { @@ -19,14 +20,14 @@ const columns: ColumnDef[] = [ cell: ({ row }) => {row.getValue("no")}, }, { - accessorKey: "report", + accessorKey: "reportedBy", header: "Pelapor", - cell: ({ row }) => {row.getValue("report")}, + cell: ({ row }) => {row?.original?.reportedBy?.fullname}, }, { accessorKey: "reportAccount", header: "Terlapor", - cell: ({ row }) => {row.getValue("reportAccount")}, + cell: ({ row }) => {row?.original?.user?.fullname}, }, { accessorKey: "message", @@ -38,41 +39,37 @@ const columns: ColumnDef[] = [ header: "Status", cell: ({ row }) => {row.getValue("reportAction")}, }, - // { - // id: "actions", - // accessorKey: "action", - // header: "Actions", - // enableHiding: false, - // cell: ({ row }) => { - // return ( - // - // - // - // - // - // - // - // View - // - // - // - // Edit - // - // - // - // Delete - // - // - // - // ); - // }, - // }, + { + id: "actions", + accessorKey: "action", + header: "Actions", + enableHiding: false, + cell: ({ row }) => { + return ( + + + + + + + + + View + + + + + ); + }, + }, ]; export default columns; diff --git a/app/[locale]/(protected)/supervisor/communications/account-report/detail/[id]/page.tsx b/app/[locale]/(protected)/supervisor/communications/account-report/detail/[id]/page.tsx new file mode 100644 index 00000000..3ac46db3 --- /dev/null +++ b/app/[locale]/(protected)/supervisor/communications/account-report/detail/[id]/page.tsx @@ -0,0 +1,17 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormBlogDetail from "@/components/form/blog/blog--detail-form"; +import FormSurveyDetailPage from "@/components/form/survey/survey-detail"; +import FormAccountReport from "@/components/form/account-report/account-report-form"; + +const AccountReportDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default AccountReportDetailPage; diff --git a/components/form/account-report/account-report-form.tsx b/components/form/account-report/account-report-form.tsx new file mode 100644 index 00000000..499be0db --- /dev/null +++ b/components/form/account-report/account-report-form.tsx @@ -0,0 +1,394 @@ +"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, + SelectGroup, + SelectItem, + SelectLabel, + 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, + createTaskTa, + getTask, + getUserLevelForAssignments, +} from "@/service/task"; +import { Upload } from "tus-js-client"; +import { error } from "@/config/swal"; +import { getCsrfToken } from "@/service/auth"; +import { loading } from "@/lib/swal"; +import { useTranslations } from "next-intl"; +import dynamic from "next/dynamic"; +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 { detailMedia } from "@/service/curated-content/curated-content"; +import { Textarea } from "@/components/ui/textarea"; +import { FormLabel } from "@/components/ui/form"; +import { getUserReports, saveUserReportsAction } from "@/service/report/report"; +import { postBlog } from "@/service/blog/blog"; +import { Link } from "@/i18n/routing"; + +const reportSchema = z.object({ + reportedBy: z.string().min(1, { message: "Judul diperlukan" }), + user: z.string().min(1, { message: "Judul diperlukan" }), + message: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), + // url: z.string().min(1, { message: "Judul diperlukan" }), +}); + +interface FileWithPreview extends File { + preview: string; +} + +export type reportDetail = { + id: number; + message: string; + reportedBy: { + id: number; + fullname: string; + }; + user: { + id: number; + fullname: string; + }; +}; + +const CustomEditor = dynamic( + () => { + return import("@/components/editor/custom-editor"); + }, + { ssr: false } +); + +export default function FormAccountReport() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type ReportSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); + + // State for various form fields + const [expertise, setExpertiseOutput] = useState({ + semua: false, + komunikasi: false, + hukum: false, + bahasa: false, + ekonomi: false, + politik: false, + sosiologi: false, + ilmuadministrasipemerintah: false, + ti: false, + }); + const [expert, setExpertOutput] = useState({ + semua: false, + }); + + // const [assignmentType, setAssignmentType] = useState("mediahub"); + // const [assignmentCategory, setAssignmentCategory] = useState("publication"); + const [mainType, setMainType] = useState("1"); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState(""); + const [type, setType] = useState("1"); + const [selectedTarget, setSelectedTarget] = useState("3,4"); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [listDest, setListDest] = useState([]); + const [checkedLevels, setCheckedLevels] = useState(new Set()); + const [expandedPolda, setExpandedPolda] = useState([{}]); + const [isLoading, setIsLoading] = useState(false); + const [audioFile, setAudioFile] = useState(null); + const [isRecording, setIsRecording] = useState(false); + const [timer, setTimer] = useState(120); + + const t = useTranslations("Form"); + const [imageFiles, setImageFiles] = useState([]); + const [videoFiles, setVideoFiles] = useState([]); + const [textFiles, setTextFiles] = useState([]); + const [audioFiles, setAudioFiles] = useState([]); + const [isImageUploadFinish, setIsImageUploadFinish] = useState(false); + const [isVideoUploadFinish, setIsVideoUploadFinish] = useState(false); + const [isTextUploadFinish, setIsTextUploadFinish] = useState(false); + const [isAudioUploadFinish, setIsAudioUploadFinish] = useState(false); + const [voiceNoteLink, setVoiceNoteLink] = useState(""); + const [date, setDate] = React.useState({ + from: new Date(2024, 0, 1), + }); + + const [platformTypeVisible, setPlatformTypeVisible] = useState(false); + const [unitSelection, setUnitSelection] = useState({ + semua: false, + mabes: false, + polda: false, + polres: false, + satker: false, + }); + + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + + const [links, setLinks] = useState([""]); + + const { + register, + control, + setValue, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(reportSchema), + mode: "all", + }); + + // const handleRadioChange = (event: React.ChangeEvent) => { + // const selectedValue = Number(event.target.value); + // setMainType(selectedValue); + + // setPlatformTypeVisible(selectedValue === 2); + + useEffect(() => { + async function fetchPoldaPolres() { + setIsLoading(true); + try { + const response = await getUserLevelForAssignments(); + setListDest(response?.data?.data.list); + console.log("polda", response?.data?.data?.list); + const initialExpandedState = response?.data?.data.list.reduce( + (acc: any, polda: any) => { + acc[polda.id] = false; + return acc; + }, + {} + ); + setExpandedPolda(initialExpandedState); + console.log("polres", initialExpandedState); + } catch (error) { + console.error("Error fetching Polda/Polres data:", error); + } finally { + setIsLoading(false); + } + } + fetchPoldaPolres(); + }, []); + + const handleUnitChange = ( + key: keyof typeof unitSelection, + value: boolean + ) => { + if (key === "semua") { + const newState = { + semua: value, + mabes: value, + polda: value, + polres: value, + satker: value, + }; + setUnitSelection(newState); + } else { + const updatedSelection = { + ...unitSelection, + [key]: value, + }; + + const allChecked = ["mabes", "polda", "polres", "satker"].every( + (k) => updatedSelection[k as keyof typeof unitSelection] + ); + + updatedSelection.semua = allChecked; + + setUnitSelection(updatedSelection); + } + }; + + useEffect(() => { + async function getReportData() { + if (id != undefined) { + const res = await getUserReports(id); + close(); + if (res?.data?.data != undefined) { + const data = res?.data?.data; + console.log("Data :", data); + setDetail(data); + } + } + } + + getReportData(); + }, [id]); + + const save = async (data: ReportSchema) => { + loading(); + const requestData = { + ...data, + id: detail?.id, + action: selectedTarget, + }; + + const response = await saveUserReportsAction(id, requestData); + console.log("Form Data Submitted:", requestData); + console.log("response", response); + + if (response?.error) { + MySwal.fire("Error", response?.message, "error"); + return; + } + close(); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/in/contributor/blog"); + }); + }; + + const onSubmit = (data: ReportSchema) => { + 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 ( + +
+

{t("form-task")}

+ {detail !== undefined ? ( +
+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.reportedBy?.message && ( +

+ {errors.reportedBy.message} +

+ )} +
+
+ + ( + + )} + /> + {errors.user?.message && ( +

{errors.user.message}

+ )} +
+ +
+ + ( +