Merge branch 'dev-anang' of https://gitlab.com/hanifsalafi/mediahub_redesign
This commit is contained in:
commit
fecc753abb
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
import { Link } from "@/components/navigation";
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -95,18 +96,22 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<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/blog/detail/${row.original.id}`}>
|
||||||
<Eye className="w-4 h-4 me-1.5" />
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
View
|
<Eye className="w-4 h-4 me-1.5" />
|
||||||
</DropdownMenuItem>
|
View
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</Link>
|
||||||
|
{/*
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
<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" />
|
<SquarePen className="w-4 h-4 me-1.5" />
|
||||||
Edit
|
Edit
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|
||||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
<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" />
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
Delete
|
Delete
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem> */}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Link } from "@/components/navigation";
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "startTime",
|
accessorKey: "time",
|
||||||
header: "Time",
|
header: "Time",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }: { row: { original: any } }) => {
|
||||||
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
|
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",
|
accessorKey: "address",
|
||||||
|
|
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "speakerName",
|
accessorKey: "speaker",
|
||||||
header: "Disampaikan oleh",
|
header: "Disampaikan oleh",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }: { row: { original: any } }) => {
|
||||||
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
|
console.log("Row Original Data:", row.original);
|
||||||
),
|
const { speakerTitle, speakerName } = row.original;
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{speakerTitle || ""} {speakerName || ""}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "uploaderName",
|
accessorKey: "uploaderName",
|
||||||
|
|
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<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
|
||||||
<Eye className="w-4 h-4 me-1.5" />
|
href={`/contributor/schedule/event/detail/${row.original.id}`}
|
||||||
View
|
>
|
||||||
</DropdownMenuItem>
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
<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" />
|
||||||
<SquarePen className="w-4 h-4 me-1.5" />
|
View
|
||||||
Edit
|
</DropdownMenuItem>
|
||||||
</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">
|
<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" />
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
Delete
|
Delete
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -106,11 +106,17 @@ const columns: ColumnDef<any>[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "speakerName",
|
accessorKey: "speaker",
|
||||||
header: "Disampaikan oleh",
|
header: "Disampaikan oleh",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }: { row: { original: any } }) => {
|
||||||
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
|
console.log("Row Original Data:", row.original);
|
||||||
),
|
const { speakerTitle, speakerName } = row.original;
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{speakerTitle || ""} {speakerName || ""}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "uploaderName",
|
accessorKey: "uploaderName",
|
||||||
|
|
@ -138,16 +144,22 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<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
|
||||||
<Link href={`/contributor/schedule/press-conference/detail/${row.id}`}>
|
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" />
|
<Eye className="w-4 h-4 me-1.5" />
|
||||||
Detail
|
Detail
|
||||||
</Link>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuItem>
|
</Link>
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
<Link
|
||||||
<SquarePen className="w-4 h-4 me-1.5" />
|
href={`/contributor/schedule/press-conference/update/${row.original.id}`}
|
||||||
Edit
|
>
|
||||||
</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>
|
||||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
<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" />
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
Delete
|
Delete
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,11 @@ import { useParams } from "next/navigation";
|
||||||
import { id } from "date-fns/locale";
|
import { id } from "date-fns/locale";
|
||||||
|
|
||||||
const PressConDetailPage = () => {
|
const PressConDetailPage = () => {
|
||||||
const params = useParams();
|
|
||||||
const id = params?.id;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<FormDetailPressConference id={id} />
|
<FormDetailPressConference />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Link } from "@/components/navigation";
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "startTime",
|
accessorKey: "time",
|
||||||
header: "Time",
|
header: "Time",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }: { row: { original: any } }) => {
|
||||||
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
|
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",
|
accessorKey: "address",
|
||||||
|
|
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "speakerName",
|
accessorKey: "speaker",
|
||||||
header: "Disampaikan oleh",
|
header: "Disampaikan oleh",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }: { row: { original: any } }) => {
|
||||||
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
|
console.log("Row Original Data:", row.original);
|
||||||
),
|
const { speakerTitle, speakerName } = row.original;
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{speakerTitle || ""} {speakerName || ""}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "uploaderName",
|
accessorKey: "uploaderName",
|
||||||
|
|
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<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
|
||||||
<Eye className="w-4 h-4 me-1.5" />
|
href={`/contributor/schedule/press-release/detail/${row.original.id}`}
|
||||||
View
|
>
|
||||||
</DropdownMenuItem>
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
<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" />
|
||||||
<SquarePen className="w-4 h-4 me-1.5" />
|
View
|
||||||
Edit
|
</DropdownMenuItem>
|
||||||
</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">
|
<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" />
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
Delete
|
Delete
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
import FormTask from "@/components/form/task/task-form";
|
import FormTask from "@/components/form/task/task-form";
|
||||||
|
import FormTaskDetail from "@/components/form/task/task-detail-form";
|
||||||
|
|
||||||
const TaskDetailPage = async () => {
|
const TaskDetailPage = async () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<FormTask />
|
<FormTaskDetail />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
import { Link } from "@/components/navigation";
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -108,18 +109,20 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<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={`/shared/contest/detail/${row.original.id}`}>
|
||||||
<Eye className="w-4 h-4 me-1.5" />
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
View
|
<Eye className="w-4 h-4 me-1.5" />
|
||||||
</DropdownMenuItem>
|
View
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
</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" />
|
<SquarePen className="w-4 h-4 me-1.5" />
|
||||||
Edit
|
Edit
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
<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" />
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
Delete
|
Delete
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem> */}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -129,7 +129,7 @@ export default function FormPressRelease() {
|
||||||
confirmButtonColor: "#3085d6",
|
confirmButtonColor: "#3085d6",
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
router.push("/contributor/schedule/press-release");
|
router.push("/en/contributor/schedule/press-release");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,6 @@ import * as z from "zod";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
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 { Switch } from "@/components/ui/switch";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
|
|
@ -29,7 +19,7 @@ import {
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { CalendarIcon } from "lucide-react";
|
import { CalendarIcon } from "lucide-react";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
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 { DateRange } from "react-day-picker";
|
||||||
import TimePicker from "react-time-picker";
|
import TimePicker from "react-time-picker";
|
||||||
import "react-time-picker/dist/TimePicker.css";
|
import "react-time-picker/dist/TimePicker.css";
|
||||||
|
|
@ -39,7 +29,6 @@ import { Textarea } from "@/components/ui/textarea";
|
||||||
import { error, loading } from "@/lib/swal";
|
import { error, loading } from "@/lib/swal";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
|
import { detailSchedule, postSchedule } from "@/service/schedule/schedule";
|
||||||
import { id } from "date-fns/locale";
|
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -49,6 +38,7 @@ const taskSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Detail {
|
interface Detail {
|
||||||
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
address: string;
|
address: string;
|
||||||
speakerTitle: string;
|
speakerTitle: string;
|
||||||
|
|
@ -57,27 +47,17 @@ interface Detail {
|
||||||
addressLong: number;
|
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 router = useRouter();
|
||||||
const id = props.id;
|
|
||||||
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
|
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
|
||||||
type TaskSchema = z.infer<typeof taskSchema>;
|
type TaskSchema = z.infer<typeof taskSchema>;
|
||||||
const [startTime, setStartTime] = useState("08:00");
|
const [startTime, setStartTime] = useState("08:00");
|
||||||
const [endTime, setEndTime] = useState("09:00");
|
const [endTime, setEndTime] = useState("09:00");
|
||||||
|
const [date, setDate] = useState<DateRange | undefined>();
|
||||||
|
|
||||||
const [date, setDate] = React.useState<DateRange | undefined>({
|
const [detail, setDetail] = useState<Detail>();
|
||||||
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 [refresh, setRefresh] = useState(false);
|
const [refresh, setRefresh] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
@ -94,35 +74,34 @@ export default function FormDetailPressConference(props: { id: any }) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function initState() {
|
async function initState() {
|
||||||
try {
|
if (id) {
|
||||||
loading();
|
|
||||||
const response = await detailSchedule(id);
|
const response = await detailSchedule(id);
|
||||||
const details = response.data?.data;
|
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, {
|
setDetail(details);
|
||||||
secure: true,
|
if (details) {
|
||||||
sameSite: "strict",
|
setDate({
|
||||||
});
|
from: parseISO(details.startDate),
|
||||||
Cookies.set("map_long", details.addressLong, {
|
to: parseISO(details.endDate),
|
||||||
secure: true,
|
|
||||||
sameSite: "strict",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Swal.close();
|
if (details) {
|
||||||
} catch (err) {
|
setStartTime(details.startTime);
|
||||||
Swal.fire("Error", "Failed to fetch details", "error");
|
setEndTime(details.endTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initState();
|
initState();
|
||||||
}, [refresh, setValue]);
|
}, [refresh, setValue]);
|
||||||
|
|
||||||
|
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setStartTime(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setEndTime(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col lg:flex-row gap-2">
|
<div className="flex flex-col lg:flex-row gap-2">
|
||||||
<Card className="w-full lg:w-9/12">
|
<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 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>
|
<Label className="mr-3 mb-1">Tanggal</Label>
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
|
|
@ -230,20 +209,20 @@ export default function FormDetailPressConference(props: { id: any }) {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="title">Rentang Waktu</Label>
|
<Label htmlFor="title">Rentang Waktu</Label>
|
||||||
<div className="">
|
<div>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
<Input
|
<Input
|
||||||
defaultValue="08:00"
|
value={startTime}
|
||||||
type="time"
|
type="time"
|
||||||
onChange={(e) => handleStartTime(e)}
|
onChange={handleStartTime}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
<Input
|
<Input
|
||||||
defaultValue="09:00"
|
value={endTime}
|
||||||
type="time"
|
type="time"
|
||||||
onChange={(e) => handleEndTime(e)}
|
onChange={handleEndTime}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -264,7 +243,7 @@ export default function FormDetailPressConference(props: { id: any }) {
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Textarea
|
<Textarea
|
||||||
rows={3}
|
rows={3}
|
||||||
value={field.value}
|
value={detail?.address}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
placeholder="Masukan lokasi"
|
placeholder="Masukan lokasi"
|
||||||
/>
|
/>
|
||||||
|
|
@ -285,7 +264,7 @@ export default function FormDetailPressConference(props: { id: any }) {
|
||||||
<Input
|
<Input
|
||||||
size={"md"}
|
size={"md"}
|
||||||
type="text"
|
type="text"
|
||||||
value={field.value}
|
value={detail?.speakerTitle}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
placeholder="Masukan Nama Pangkat"
|
placeholder="Masukan Nama Pangkat"
|
||||||
/>
|
/>
|
||||||
|
|
@ -308,7 +287,7 @@ export default function FormDetailPressConference(props: { id: any }) {
|
||||||
<Input
|
<Input
|
||||||
size={"md"}
|
size={"md"}
|
||||||
type="text"
|
type="text"
|
||||||
value={field.value}
|
value={detail?.speakerName}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
placeholder="Masukan Nama Lengkap"
|
placeholder="Masukan Nama Lengkap"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,6 @@ import * as z from "zod";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { useRouter } from "next/navigation";
|
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 { Switch } from "@/components/ui/switch";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -98,51 +98,6 @@ export default function FormTask() {
|
||||||
// setPlatformTypeVisible(selectedValue === 2);
|
// 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 save = async (data: TaskSchema) => {
|
||||||
const fileTypeMapping = {
|
const fileTypeMapping = {
|
||||||
all: "1",
|
all: "1",
|
||||||
|
|
@ -212,184 +167,179 @@ export default function FormTask() {
|
||||||
<Card>
|
<Card>
|
||||||
<div className="px-6 py-6">
|
<div className="px-6 py-6">
|
||||||
<p className="text-lg font-semibold mb-3">Form Penugasan</p>
|
<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 */}
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="mt-4">
|
<div className="gap-5 mb-5">
|
||||||
<Button type="submit" color="primary">
|
{/* Input Title */}
|
||||||
Submit
|
<div className="space-y-2">
|
||||||
</Button>
|
<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>
|
||||||
</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>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { title } from "process";
|
import { title } from "process";
|
||||||
import { httpGetInterceptor } from "../http-config/http-interceptor-service";
|
import { httpGetInterceptor } from "../http-config/http-interceptor-service";
|
||||||
import { postAPIInterceptor } from "@/config/api";
|
import { getAPIInterceptor, postAPIInterceptor } from "@/config/api";
|
||||||
|
|
||||||
export async function paginationBlog(
|
export async function paginationBlog(
|
||||||
size: number,
|
size: number,
|
||||||
|
|
@ -16,3 +16,8 @@ export async function postBlog(data: any) {
|
||||||
const url = "blog";
|
const url = "blog";
|
||||||
return postAPIInterceptor(url, data);
|
return postAPIInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getBlog(id: any) {
|
||||||
|
const url = `blog/${id}`;
|
||||||
|
return getAPIInterceptor(url);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { getAPIInterceptor } from "@/config/api";
|
||||||
import {
|
import {
|
||||||
httpGetInterceptor,
|
httpGetInterceptor,
|
||||||
httpPostInterceptor,
|
httpPostInterceptor,
|
||||||
|
|
@ -17,3 +18,8 @@ export async function createTask(data: any) {
|
||||||
const url = "assignment";
|
const url = "assignment";
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getContestById(id: any, pages = 0) {
|
||||||
|
const url = `contest?id=${id}&page=${pages}`;
|
||||||
|
return getAPIInterceptor(url);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,15 @@ import { httpGetInterceptor } from "../http-config/http-interceptor-service";
|
||||||
import { type } from "os";
|
import { type } from "os";
|
||||||
import { getAPI, getAPIInterceptor, postAPIInterceptor } from "@/config/api";
|
import { getAPI, getAPIInterceptor, postAPIInterceptor } from "@/config/api";
|
||||||
|
|
||||||
export async function paginationSchedule(size: number, page: number, type: any, title: string = "") {
|
export async function paginationSchedule(
|
||||||
return await httpGetInterceptor(`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`);
|
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) {
|
export async function postSchedule(data: any) {
|
||||||
|
|
@ -14,7 +21,7 @@ export async function postSchedule(data: any) {
|
||||||
|
|
||||||
export async function detailSchedule(id: any) {
|
export async function detailSchedule(id: any) {
|
||||||
const url = `public/schedule?id=${id}`;
|
const url = `public/schedule?id=${id}`;
|
||||||
return getAPIInterceptor({ url });
|
return getAPIInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listScheduleTodayPublic(group = null) {
|
export async function listScheduleTodayPublic(group = null) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue