feat:update create,edit,detail task ta, download report
This commit is contained in:
parent
df90fc0906
commit
4e71b4525e
|
|
@ -25,8 +25,13 @@ import withReactContent from "sweetalert2-react-content";
|
|||
import { deleteBlog } from "@/service/blog/blog";
|
||||
import { error, loading } from "@/lib/swal";
|
||||
import { useTranslations } from "next-intl";
|
||||
import axios from "axios";
|
||||
|
||||
const useTableColumns = () => {
|
||||
const useTableColumns = ({
|
||||
handlePreview,
|
||||
}: {
|
||||
handlePreview: (id: string) => void;
|
||||
}) => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
|
|
@ -112,6 +117,33 @@ const useTableColumns = () => {
|
|||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDownload = async (id: string) => {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`https://netidhub.com/api/media/report/download?id=${id}`,
|
||||
{
|
||||
responseType: "blob",
|
||||
}
|
||||
);
|
||||
|
||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.setAttribute("download", `report-${id}.pdf`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
} catch (error) {
|
||||
console.error("Download failed", error);
|
||||
MySwal.fire({
|
||||
title: "Gagal",
|
||||
text: "Terjadi kesalahan saat mengunduh file.",
|
||||
icon: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
|
|
@ -124,18 +156,22 @@ const useTableColumns = () => {
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<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">
|
||||
<DropdownMenuItem
|
||||
onClick={() => handlePreview(row.original.id)}
|
||||
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" />
|
||||
Preview
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
<Link href={`/contributor/blog/update/${row.original.id}`}>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
|
||||
<DropdownMenuItem
|
||||
onClick={() => handleDownload(row.original.id)}
|
||||
className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"
|
||||
>
|
||||
<Upload className="w-4 h-4 me-1.5" />
|
||||
Download
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
|
||||
<DropdownMenuItem
|
||||
onClick={() => handleDeleteBlog(row.original.id)}
|
||||
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
||||
|
|
|
|||
|
|
@ -43,14 +43,40 @@ import {
|
|||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import Swal from "sweetalert2";
|
||||
import { listEnableCategory } from "@/service/content/content";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import useTableColumns from "./columns";
|
||||
import {
|
||||
getPreviewById,
|
||||
paginationReport,
|
||||
saveReport,
|
||||
} from "@/service/report/report";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { format } from "date-fns";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
|
||||
type PreviewApiResponse = {
|
||||
error: boolean;
|
||||
message: string;
|
||||
data: {
|
||||
id: number;
|
||||
title: string;
|
||||
filePath: string;
|
||||
version: number;
|
||||
} | null;
|
||||
};
|
||||
|
||||
const ReportTable = () => {
|
||||
const router = useRouter();
|
||||
const MySwal = withReactContent(Swal);
|
||||
const searchParams = useSearchParams();
|
||||
const t = useTranslations("Report");
|
||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||
|
|
@ -78,7 +104,16 @@ const ReportTable = () => {
|
|||
const [categoryFilter, setCategoryFilter] = React.useState<string>("");
|
||||
const [dateFilter, setDateFilter] = React.useState("");
|
||||
const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
|
||||
const columns = useTableColumns();
|
||||
const [openPreview, setOpenPreview] = React.useState(false);
|
||||
const [previewData, setPreviewData] = React.useState<any>(null);
|
||||
|
||||
const handlePreview = (id: string) => {
|
||||
const url = `https://netidhub.com/api/media/report/view?id=${id}`;
|
||||
setPreviewData({ url });
|
||||
setOpenPreview(true);
|
||||
};
|
||||
|
||||
const columns = useTableColumns({ handlePreview });
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
@ -114,7 +149,7 @@ const ReportTable = () => {
|
|||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const res = await paginationBlog(
|
||||
const res = await paginationReport(
|
||||
showData,
|
||||
page - 1,
|
||||
search,
|
||||
|
|
@ -144,11 +179,10 @@ const ReportTable = () => {
|
|||
}
|
||||
|
||||
const handleCheckboxChange = (categoryId: number) => {
|
||||
setSelectedCategories(
|
||||
(prev: any) =>
|
||||
setSelectedCategories((prev: any) =>
|
||||
prev.includes(categoryId)
|
||||
? prev.filter((id: any) => id !== categoryId) // Hapus jika sudah dipilih
|
||||
: [...prev, categoryId] // Tambahkan jika belum dipilih
|
||||
? prev.filter((id: any) => id !== categoryId)
|
||||
: [...prev, categoryId]
|
||||
);
|
||||
|
||||
// Perbarui filter kategori
|
||||
|
|
@ -176,8 +210,61 @@ const ReportTable = () => {
|
|||
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
|
||||
};
|
||||
|
||||
const handleGenerateReport = async () => {
|
||||
const today = new Date();
|
||||
const formattedDate = format(today, "dd-MM-yyyy"); // Hasil: 22-04-2025
|
||||
const title = `Report ${formattedDate}`;
|
||||
|
||||
const requestData = {
|
||||
title,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await saveReport(requestData);
|
||||
|
||||
if (response?.error) {
|
||||
MySwal.fire(
|
||||
"Error",
|
||||
response?.message || "Gagal menyimpan laporan",
|
||||
"error"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
MySwal.fire({
|
||||
title: "Sukses",
|
||||
text: "Laporan berhasil dibuat.",
|
||||
icon: "success",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "OK",
|
||||
}).then(() => {
|
||||
fetchData(); // Refresh tabel setelah generate
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Generate report error:", error);
|
||||
MySwal.fire("Error", "Terjadi kesalahan saat membuat laporan", "error");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog open={openPreview} onOpenChange={setOpenPreview}>
|
||||
<DialogContent className="min-w-max h-[500px] p-0 overflow-hidden">
|
||||
<DialogHeader className="p-4 border-b">
|
||||
<DialogTitle>Preview Laporan</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="h-full w-[1000px] overflow-auto">
|
||||
{previewData ? (
|
||||
<iframe
|
||||
src={previewData.url}
|
||||
className="w-full h-[calc(100vh-100px)]"
|
||||
/>
|
||||
) : (
|
||||
<div className="p-4">Loading preview...</div>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<CardHeader className="border-b border-solid border-default-200 mb-6">
|
||||
<CardTitle>
|
||||
<div className="flex items-center">
|
||||
|
|
@ -185,17 +272,14 @@ const ReportTable = () => {
|
|||
{t("table")} {t("report")}
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Link href={"#"}>
|
||||
<Button fullWidth color="primary">
|
||||
<Button fullWidth color="primary" onClick={handleGenerateReport}>
|
||||
<Plus size={18} className=" me-1.5" />
|
||||
{t("generate-report")}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex flex-col md:flex-row lg:flex-row md:justify-between lg:justify-between items-center md:px-5 lg:px-5">
|
||||
<div className="w-full md:w-[200px] lg:w-[200px] px-2">
|
||||
|
|
|
|||
|
|
@ -158,13 +158,13 @@ const useTableColumns = () => {
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<Link href={`/contributor/task/detail/${row.original.id}`}>
|
||||
<Link href={`/contributor/task-ta/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/task/update/${row.original.id}`}>
|
||||
<Link href={`/contributor/task-ta/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
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ import { Badge } from "@/components/ui/badge";
|
|||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import TablePagination from "@/components/table/table-pagination";
|
||||
import columns from "./columns";
|
||||
import { listTask } from "@/service/task";
|
||||
import { listTask, listTaskTa } from "@/service/task";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { format } from "date-fns";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
|
@ -133,7 +133,7 @@ const TaskTaTable = () => {
|
|||
? format(new Date(dateFilter), "yyyy-MM-dd")
|
||||
: "";
|
||||
try {
|
||||
const res = await listTask(
|
||||
const res = await listTaskTa(
|
||||
page - 1,
|
||||
search,
|
||||
showData,
|
||||
|
|
|
|||
|
|
@ -2,13 +2,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";
|
||||
import FormTaskTaDetail from "@/components/form/task-ta/task-ta-detail-form";
|
||||
|
||||
const TaskTaDetailPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<FormTaskDetail />
|
||||
<FormTaskTaDetail />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ import SiteBreadcrumb from "@/components/site-breadcrumb";
|
|||
import FormTask from "@/components/form/task/task-form";
|
||||
import FormTaskDetail from "@/components/form/task/task-detail-form";
|
||||
import FormTaskEdit from "@/components/form/task/task-edit-form";
|
||||
import FormTaskTaEdit from "@/components/form/task-ta/task-ta-edit-form";
|
||||
|
||||
const TaskTaDetailPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<FormTaskEdit />
|
||||
<FormTaskTaEdit />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import {
|
|||
getAssignmentResponseList,
|
||||
getMediaUpload,
|
||||
getTask,
|
||||
getTaskTa,
|
||||
getUserLevelForAssignments,
|
||||
} from "@/service/task";
|
||||
import {
|
||||
|
|
@ -82,11 +83,11 @@ export type taskDetail = {
|
|||
title: string;
|
||||
fileTypeOutput: string;
|
||||
assignedToRole: string;
|
||||
assignedToTopLevel: string;
|
||||
assignmentType: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
assignedToUsers: string;
|
||||
// assignmentType: {
|
||||
// id: number;
|
||||
// name: string;
|
||||
// };
|
||||
assignmentMainType: {
|
||||
id: number;
|
||||
name: string;
|
||||
|
|
@ -106,7 +107,8 @@ export type taskDetail = {
|
|||
userGroupId: number;
|
||||
};
|
||||
};
|
||||
taskType: string;
|
||||
assignmentType: string;
|
||||
expertCompetencies: string;
|
||||
broadcastType: string;
|
||||
narration: string;
|
||||
is_active: string;
|
||||
|
|
@ -198,6 +200,22 @@ export default function FormTaskTaDetail() {
|
|||
const userId = getCookiesDecrypt("uie");
|
||||
const userLevelId = "";
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
// State for various form fields
|
||||
const [taskOutput, setTaskOutput] = useState({
|
||||
all: false,
|
||||
|
|
@ -307,6 +325,62 @@ export default function FormTaskTaDetail() {
|
|||
// setPlatformTypeVisible(selectedValue === 2);
|
||||
// };
|
||||
|
||||
const handleExpertiseOutputChange = (
|
||||
key: keyof typeof expertise,
|
||||
value: boolean
|
||||
) => {
|
||||
if (key === "semua") {
|
||||
const newState = {
|
||||
semua: value,
|
||||
komunikasi: value,
|
||||
hukum: value,
|
||||
bahasa: value,
|
||||
ekonomi: value,
|
||||
politik: value,
|
||||
sosiologi: value,
|
||||
ilmuadministrasipemerintah: value,
|
||||
ti: value,
|
||||
};
|
||||
setExpertiseOutput(newState);
|
||||
} else {
|
||||
const updated = {
|
||||
...expertise,
|
||||
[key]: value,
|
||||
};
|
||||
|
||||
const allChecked = ["video", "audio", "image", "text"].every(
|
||||
(k) => updated[k as keyof typeof expertise]
|
||||
);
|
||||
|
||||
updated.semua = allChecked;
|
||||
setExpertiseOutput(updated);
|
||||
}
|
||||
};
|
||||
|
||||
const handleExpertOutputChange = (
|
||||
key: keyof typeof expert,
|
||||
value: boolean
|
||||
) => {
|
||||
if (key === "semua") {
|
||||
const newState = {
|
||||
semua: value,
|
||||
};
|
||||
setExpertOutput(newState);
|
||||
} else {
|
||||
const updated = {
|
||||
...expert,
|
||||
[key]: value,
|
||||
};
|
||||
|
||||
const allChecked = ["video", "audio", "image", "text"].every(
|
||||
(k) => updated[k as keyof typeof expert]
|
||||
);
|
||||
|
||||
updated.semua = allChecked;
|
||||
setExpertOutput(updated);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchPoldaPolres() {
|
||||
setIsLoading(true);
|
||||
|
|
@ -358,7 +432,7 @@ export default function FormTaskTaDetail() {
|
|||
useEffect(() => {
|
||||
async function initState() {
|
||||
if (id) {
|
||||
const response = await getTask(id);
|
||||
const response = await getTaskTa(id);
|
||||
const details = response?.data?.data;
|
||||
|
||||
setDetail(details);
|
||||
|
|
@ -427,19 +501,36 @@ export default function FormTaskTaDetail() {
|
|||
}, [detail?.fileTypeOutput]);
|
||||
|
||||
useEffect(() => {
|
||||
if (detail?.assignedToTopLevel) {
|
||||
if (detail?.expertCompetencies) {
|
||||
const outputSet = new Set(
|
||||
detail.assignedToTopLevel.split(",").map(Number)
|
||||
detail.expertCompetencies.split(",").map(String)
|
||||
);
|
||||
setUnitSelection({
|
||||
allUnit: outputSet.has(0),
|
||||
mabes: outputSet.has(1),
|
||||
polda: outputSet.has(2),
|
||||
polres: outputSet.has(3),
|
||||
satker: outputSet.has(4),
|
||||
setExpertiseOutput({
|
||||
semua: outputSet.has("0"),
|
||||
komunikasi: outputSet.has("1"),
|
||||
hukum: outputSet.has("2"),
|
||||
bahasa: outputSet.has("3"),
|
||||
ekonomi: outputSet.has("4"),
|
||||
politik: outputSet.has("5"),
|
||||
sosiologi: outputSet.has("6"),
|
||||
ilmuadministrasipemerintah: outputSet.has("7"),
|
||||
ti: outputSet.has("8"),
|
||||
});
|
||||
}
|
||||
}, [detail?.fileTypeOutput]);
|
||||
}, [detail?.expertCompetencies]);
|
||||
|
||||
useEffect(() => {
|
||||
if (detail?.assignedToUsers) {
|
||||
const outputSet = new Set(detail.assignedToUsers.split(",").map(String));
|
||||
setUnitSelection({
|
||||
allUnit: outputSet.has("0"),
|
||||
mabes: outputSet.has("1"),
|
||||
polda: outputSet.has("2"),
|
||||
polres: outputSet.has("3"),
|
||||
satker: outputSet.has("4"),
|
||||
});
|
||||
}
|
||||
}, [detail?.assignedToUsers]);
|
||||
|
||||
const successConfirm = () => {
|
||||
MySwal.fire({
|
||||
|
|
@ -1022,7 +1113,7 @@ export default function FormTaskTaDetail() {
|
|||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 space-y-2">
|
||||
{/* <div className="mt-6 space-y-2">
|
||||
<Label>{t("type-task")}</Label>
|
||||
<RadioGroup
|
||||
value={detail.assignmentMainType.id.toString()}
|
||||
|
|
@ -1036,11 +1127,11 @@ export default function FormTaskTaDetail() {
|
|||
<RadioGroupItem value="2" id="medsos-mediahub" />
|
||||
<Label htmlFor="medsos-mediahub">Medsos Mediahub</Label>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="mt-6 space-y-2">
|
||||
<Label>{t("assigment-type")} </Label>
|
||||
<RadioGroup
|
||||
value={detail.taskType.toString()}
|
||||
value={detail?.assignmentType}
|
||||
onValueChange={(value) => setTaskType(String(value))}
|
||||
className="flex flex-wrap gap-3"
|
||||
>
|
||||
|
|
@ -1050,40 +1141,21 @@ export default function FormTaskTaDetail() {
|
|||
<Label htmlFor="tugas-harian">Tugas Harian</Label>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
{/* RadioGroup Assignment Category */}
|
||||
<div className="mt-6 space-y-2">
|
||||
<Label>{t("type-of-task")}</Label>
|
||||
<RadioGroup
|
||||
value={detail.assignmentType.id.toString()}
|
||||
onValueChange={(value) => setType(value)}
|
||||
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-6 space-y-2">
|
||||
<Label>{t("output-task")}</Label>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{Object.keys(taskOutput).map((key) => (
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("areas-expertise")}</Label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{Object.keys(expertise).map((key) => (
|
||||
<div className="flex items-center gap-2" key={key}>
|
||||
<Checkbox
|
||||
id={key}
|
||||
disabled
|
||||
checked={taskOutput[key as keyof typeof taskOutput]}
|
||||
checked={expertise[key as keyof typeof expertise]}
|
||||
onCheckedChange={(value) =>
|
||||
setTaskOutput({ ...taskOutput, [key]: value })
|
||||
handleExpertiseOutputChange(
|
||||
key as keyof typeof expertise,
|
||||
value as boolean
|
||||
)
|
||||
}
|
||||
disabled
|
||||
/>
|
||||
<Label htmlFor={key}>
|
||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
||||
|
|
@ -1093,6 +1165,28 @@ export default function FormTaskTaDetail() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("choose-expert")}</Label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{Object.keys(expert).map((key) => (
|
||||
<div className="flex items-center gap-2" key={key}>
|
||||
<Checkbox
|
||||
id={key}
|
||||
checked={expert[key as keyof typeof expert]}
|
||||
onCheckedChange={(value) =>
|
||||
handleExpertOutputChange(
|
||||
key as keyof typeof expert,
|
||||
value as boolean
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Label htmlFor={key}>
|
||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 space-y-2">
|
||||
<Label>{t("description")}</Label>
|
||||
<Controller
|
||||
|
|
@ -22,7 +22,9 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|||
import JoditEditor from "jodit-react";
|
||||
import {
|
||||
createTask,
|
||||
createTaskTa,
|
||||
getTask,
|
||||
getTaskTa,
|
||||
getUserLevelForAssignments,
|
||||
} from "@/service/task";
|
||||
import {
|
||||
|
|
@ -65,16 +67,13 @@ export type taskDetail = {
|
|||
title: string;
|
||||
fileTypeOutput: string;
|
||||
assignedToRole: string;
|
||||
assignedToTopLevel: string;
|
||||
assignmentType: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
assignedToUsers: string;
|
||||
assignmentMainType: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
taskType: string;
|
||||
assignmentType: string;
|
||||
expertCompetencies: string;
|
||||
broadcastType: string;
|
||||
narration: string;
|
||||
attachmentUrl: string;
|
||||
|
|
@ -110,7 +109,22 @@ export default function FormTaskTaEdit() {
|
|||
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 [taskOutput, setTaskOutput] = useState({
|
||||
all: false,
|
||||
video: false,
|
||||
|
|
@ -177,12 +191,61 @@ export default function FormTaskTaEdit() {
|
|||
resolver: zodResolver(taskSchema),
|
||||
});
|
||||
|
||||
// const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// const selectedValue = Number(event.target.value);
|
||||
// setMainType(selectedValue);
|
||||
const handleExpertiseOutputChange = (
|
||||
key: keyof typeof expertise,
|
||||
value: boolean
|
||||
) => {
|
||||
if (key === "semua") {
|
||||
const newState = {
|
||||
semua: value,
|
||||
komunikasi: value,
|
||||
hukum: value,
|
||||
bahasa: value,
|
||||
ekonomi: value,
|
||||
politik: value,
|
||||
sosiologi: value,
|
||||
ilmuadministrasipemerintah: value,
|
||||
ti: value,
|
||||
};
|
||||
setExpertiseOutput(newState);
|
||||
} else {
|
||||
const updated = {
|
||||
...expertise,
|
||||
[key]: value,
|
||||
};
|
||||
|
||||
// setPlatformTypeVisible(selectedValue === 2);
|
||||
// };
|
||||
const allChecked = ["video", "audio", "image", "text"].every(
|
||||
(k) => updated[k as keyof typeof expertise]
|
||||
);
|
||||
|
||||
updated.semua = allChecked;
|
||||
setExpertiseOutput(updated);
|
||||
}
|
||||
};
|
||||
|
||||
const handleExpertOutputChange = (
|
||||
key: keyof typeof expert,
|
||||
value: boolean
|
||||
) => {
|
||||
if (key === "semua") {
|
||||
const newState = {
|
||||
semua: value,
|
||||
};
|
||||
setExpertOutput(newState);
|
||||
} else {
|
||||
const updated = {
|
||||
...expert,
|
||||
[key]: value,
|
||||
};
|
||||
|
||||
const allChecked = ["video", "audio", "image", "text"].every(
|
||||
(k) => updated[k as keyof typeof expert]
|
||||
);
|
||||
|
||||
updated.semua = allChecked;
|
||||
setExpertOutput(updated);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchPoldaPolres() {
|
||||
|
|
@ -211,7 +274,7 @@ export default function FormTaskTaEdit() {
|
|||
useEffect(() => {
|
||||
async function initState() {
|
||||
if (id) {
|
||||
const response = await getTask(id);
|
||||
const response = await getTaskTa(id);
|
||||
const details = response?.data?.data;
|
||||
|
||||
setDetail(details);
|
||||
|
|
@ -274,19 +337,49 @@ export default function FormTaskTaEdit() {
|
|||
}, [detail?.fileTypeOutput]);
|
||||
|
||||
useEffect(() => {
|
||||
if (detail?.assignedToTopLevel) {
|
||||
if (detail?.expertCompetencies) {
|
||||
const outputSet = new Set(
|
||||
detail.assignedToTopLevel.split(",").map(Number)
|
||||
detail.expertCompetencies.split(",").map(String)
|
||||
);
|
||||
setUnitSelection({
|
||||
allUnit: outputSet.has(0),
|
||||
mabes: outputSet.has(1),
|
||||
polda: outputSet.has(2),
|
||||
polres: outputSet.has(3),
|
||||
satker: outputSet.has(4),
|
||||
setExpertiseOutput({
|
||||
semua: outputSet.has("0"),
|
||||
komunikasi: outputSet.has("1"),
|
||||
hukum: outputSet.has("2"),
|
||||
bahasa: outputSet.has("3"),
|
||||
ekonomi: outputSet.has("4"),
|
||||
politik: outputSet.has("5"),
|
||||
sosiologi: outputSet.has("6"),
|
||||
ilmuadministrasipemerintah: outputSet.has("7"),
|
||||
ti: outputSet.has("8"),
|
||||
});
|
||||
}
|
||||
}, [detail?.fileTypeOutput]);
|
||||
}, [detail?.expertCompetencies]);
|
||||
|
||||
useEffect(() => {
|
||||
if (detail?.assignedToUsers) {
|
||||
const outputSet = new Set(detail.assignedToUsers.split(",").map(String));
|
||||
setUnitSelection({
|
||||
allUnit: outputSet.has("0"),
|
||||
mabes: outputSet.has("1"),
|
||||
polda: outputSet.has("2"),
|
||||
polres: outputSet.has("3"),
|
||||
satker: outputSet.has("4"),
|
||||
});
|
||||
}
|
||||
}, [detail?.assignedToUsers]);
|
||||
|
||||
const successConfirm = () => {
|
||||
MySwal.fire({
|
||||
title: "Sukses",
|
||||
icon: "success",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "OK",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
router.push("/en/contributor/task");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleCheckboxChange = (levelId: number) => {
|
||||
setCheckedLevels((prev) => {
|
||||
|
|
@ -391,15 +484,16 @@ export default function FormTaskTaEdit() {
|
|||
id?: any;
|
||||
title: string;
|
||||
assignedToLevel: any;
|
||||
assignmentPurpose: any;
|
||||
assignedToUsers: any;
|
||||
assignmentTypeId: string;
|
||||
fileTypeOutput: string;
|
||||
narration: string;
|
||||
platformType: string | null;
|
||||
assignmentMainTypeId: any;
|
||||
taskType: string;
|
||||
assignmentType: string;
|
||||
assignedToRole: string;
|
||||
broadcastType: string;
|
||||
expertCompetencies: string;
|
||||
attachmentUrl: string[];
|
||||
} = {
|
||||
...data,
|
||||
|
|
@ -407,20 +501,21 @@ export default function FormTaskTaEdit() {
|
|||
// assignmentCategory,
|
||||
id: detail?.id || null,
|
||||
assignedToLevel: handlePoldaPolresChange(),
|
||||
assignmentPurpose: assignmentPurposeString,
|
||||
assignedToUsers: assignmentPurposeString,
|
||||
assignedToRole: selectedTarget,
|
||||
taskType: taskType,
|
||||
assignmentType: taskType,
|
||||
broadcastType: broadcastType,
|
||||
assignmentMainTypeId: mainType,
|
||||
assignmentTypeId: type,
|
||||
fileTypeOutput: selectedOutputs,
|
||||
narration: data.naration,
|
||||
platformType: "",
|
||||
expertCompetencies: "1,2,3",
|
||||
title: data.title,
|
||||
attachmentUrl: links,
|
||||
};
|
||||
|
||||
const response = await createTask(requestData);
|
||||
const response = await createTaskTa(requestData);
|
||||
|
||||
console.log("Form Data Submitted:", requestData);
|
||||
console.log("response", response);
|
||||
|
|
@ -832,25 +927,10 @@ export default function FormTaskTaEdit() {
|
|||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("type-task")}</Label>
|
||||
<RadioGroup
|
||||
defaultValue={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 space-y-2">
|
||||
<div className="mt-6 space-y-2">
|
||||
<Label>{t("assigment-type")} </Label>
|
||||
<RadioGroup
|
||||
defaultValue={detail.taskType.toString()}
|
||||
defaultValue={detail?.assignmentType}
|
||||
onValueChange={(value) => setTaskType(String(value))}
|
||||
className="flex flex-wrap gap-3"
|
||||
>
|
||||
|
|
@ -860,39 +940,17 @@ export default function FormTaskTaEdit() {
|
|||
<Label htmlFor="tugas-harian">Tugas Harian</Label>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
{/* RadioGroup Assignment Category */}
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("type-of-task")}</Label>
|
||||
<RadioGroup
|
||||
defaultValue={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 space-y-2">
|
||||
<Label>{t("output-task")}</Label>
|
||||
<Label>{t("areas-expertise")}</Label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{Object.keys(taskOutput).map((key) => (
|
||||
{Object.keys(expertise).map((key) => (
|
||||
<div className="flex items-center gap-2" key={key}>
|
||||
<Checkbox
|
||||
id={key}
|
||||
checked={taskOutput[key as keyof typeof taskOutput]}
|
||||
checked={expertise[key as keyof typeof expertise]}
|
||||
onCheckedChange={(value) =>
|
||||
handleTaskOutputChange(
|
||||
key as keyof typeof taskOutput,
|
||||
handleExpertiseOutputChange(
|
||||
key as keyof typeof expertise,
|
||||
value as boolean
|
||||
)
|
||||
}
|
||||
|
|
@ -904,6 +962,30 @@ export default function FormTaskTaEdit() {
|
|||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("choose-expert")}</Label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{Object.keys(expert).map((key) => (
|
||||
<div className="flex items-center gap-2" key={key}>
|
||||
<Checkbox
|
||||
id={key}
|
||||
checked={expert[key as keyof typeof expert]}
|
||||
onCheckedChange={(value) =>
|
||||
handleExpertOutputChange(
|
||||
key as keyof typeof expert,
|
||||
value as boolean
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Label htmlFor={key}>
|
||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("description")}</Label>
|
||||
<Controller
|
||||
|
|
@ -22,6 +22,7 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|||
import JoditEditor from "jodit-react";
|
||||
import {
|
||||
createTask,
|
||||
createTaskTa,
|
||||
getTask,
|
||||
getUserLevelForAssignments,
|
||||
} from "@/service/task";
|
||||
|
|
@ -318,35 +319,37 @@ export default function FormTaskTa() {
|
|||
id?: number;
|
||||
title: string;
|
||||
assignedToLevel: any;
|
||||
assignmentPurpose: any;
|
||||
assignedToUsers: any;
|
||||
assignmentTypeId: string;
|
||||
fileTypeOutput: string;
|
||||
narration: string;
|
||||
platformType: string | null;
|
||||
assignmentMainTypeId: any;
|
||||
taskType: string;
|
||||
assignmentType: string;
|
||||
assignedToRole: string;
|
||||
broadcastType: string;
|
||||
expertCompetencies: string;
|
||||
attachmentUrl: string[];
|
||||
} = {
|
||||
...data,
|
||||
// assignmentType,
|
||||
// assignmentCategory,
|
||||
assignedToLevel: handlePoldaPolresChange(),
|
||||
assignmentPurpose: assignmentPurposeString,
|
||||
assignedToUsers: assignmentPurposeString,
|
||||
assignedToRole: selectedTarget,
|
||||
taskType: taskType,
|
||||
assignmentType: taskType,
|
||||
broadcastType: broadcastType,
|
||||
assignmentMainTypeId: mainType,
|
||||
assignmentTypeId: type,
|
||||
fileTypeOutput: selectedOutputs,
|
||||
narration: data.naration,
|
||||
platformType: "",
|
||||
expertCompetencies: "1,2,3",
|
||||
title: data.title,
|
||||
attachmentUrl: links,
|
||||
};
|
||||
|
||||
const response = await createTask(requestData);
|
||||
const response = await createTaskTa(requestData);
|
||||
|
||||
console.log("Form Data Submitted:", requestData);
|
||||
console.log("response", response);
|
||||
|
|
@ -719,7 +722,19 @@ export default function FormTaskTa() {
|
|||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("assigment-type")} </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>
|
||||
<div className="mt-5 space-y-2">
|
||||
<Label>{t("areas-expertise")}</Label>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import {
|
||||
httpGetInterceptor,
|
||||
httpPostInterceptor,
|
||||
} from "../http-config/http-interceptor-service";
|
||||
|
||||
export async function paginationReport(
|
||||
size: any,
|
||||
page: number,
|
||||
title: string = "",
|
||||
categoryFilter: any,
|
||||
statusFilter: any
|
||||
) {
|
||||
return await httpGetInterceptor(
|
||||
`/media/report/list?enablePage=1&page=${page}&size=${size}&title=${title}&categoryId=${categoryFilter}&statusId=${statusFilter}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function getPreviewById(id: any) {
|
||||
return await httpGetInterceptor(`/media/report/view?id=${id}`);
|
||||
}
|
||||
|
||||
export async function saveReport(data: any) {
|
||||
const url = "/media/report";
|
||||
return httpPostInterceptor(url, data);
|
||||
}
|
||||
|
|
@ -112,3 +112,35 @@ export async function finishTask(id: any) {
|
|||
const url = `assignment/finish?id=${id}`;
|
||||
return httpPostInterceptor(url);
|
||||
}
|
||||
|
||||
export async function listTaskTa(
|
||||
page: any,
|
||||
title: string = "",
|
||||
size: any,
|
||||
code: any,
|
||||
createdAt: any,
|
||||
taskType: string,
|
||||
status: number[]
|
||||
) {
|
||||
let statusQuery = "";
|
||||
|
||||
if (status.includes(1)) {
|
||||
statusQuery = "&isDone=true";
|
||||
} else if (status.includes(2)) {
|
||||
statusQuery = "&isDone=false";
|
||||
}
|
||||
|
||||
return httpGetInterceptor(
|
||||
`assignment-expert/pagination?enablePage=1&size=${size}&page=${page}&title=${title}&taskType=${taskType}&uniqueCode=${code}&createdAt=${createdAt}${statusQuery}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function createTaskTa(data: any) {
|
||||
const pathUrl = "assignment-expert";
|
||||
return httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getTaskTa(id: any) {
|
||||
const url = `/assignment-expert?id=${id}`;
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue