[QUDO-154] - fix:create live report form & flow, polda sidebar

This commit is contained in:
Rama Priyanto 2025-06-05 18:16:40 +07:00
parent 9703c25ea2
commit 9231546780
9 changed files with 505 additions and 190 deletions

View File

@ -13,8 +13,12 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
import { deleteSchedule } from "@/service/schedule/schedule";
import { error } from "@/config/swal";
const useTableColumns = () => {
const useTableColumns = (props: { selectedTypeSchedule: string }) => {
const t = useTranslations("Table"); // Panggil di dalam hook
const columns: ColumnDef<any>[] = [
@ -138,6 +142,33 @@ const useTableColumns = () => {
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
async function doDelete(id: any) {
// loading();
const response = await deleteSchedule(id);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
@ -151,7 +182,7 @@ const useTableColumns = () => {
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<Link
href={`/contributor/schedule/press-conference/detail/${row.original.id}`}
href={`/contributor/schedule/live-report/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" />
@ -159,14 +190,17 @@ const useTableColumns = () => {
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/press-conference/update/${row.original.id}`}
href={`/contributor/schedule/live-report/update/${row.original.id}?scheduleType=${props.selectedTypeSchedule}`}
>
<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
onClick={() => doDelete(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>

View File

@ -91,7 +91,7 @@ const LiveReportTable = () => {
const [search, setSearch] = React.useState<string>("");
const [statusFilter, setStatusFilter] = React.useState<number[]>([]);
const [selectedType, setSelectedType] = React.useState<string>("1");
const columns = useTableColumns();
const columns = useTableColumns({ selectedTypeSchedule: selectedType });
const table = useReactTable({
data: dataTable,
columns,
@ -197,11 +197,11 @@ const LiveReportTable = () => {
/>
</InputGroup>
</div>
<div className="flex flex-row items-center gap-3">
<div className="">
<div className="grid grid-cols-2 w-full md:w-fit md:flex lg:flex-row items-center gap-3">
<div className="w-full md:w-fit">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="md" variant="outline">
<Button size="md" variant="outline" className="w-full">
1 - {showData} Data
</Button>
</DropdownMenuTrigger>
@ -226,12 +226,12 @@ const LiveReportTable = () => {
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="border border-black rounded-md">
<div className="border border-black rounded-md w-full md:w-fit">
<Select
value={selectedType}
onValueChange={(value) => setSelectedType(value)}
>
<SelectTrigger className="w-[150px] text-black">
<SelectTrigger className="w-full md:w-[150px] text-black">
<SelectValue placeholder="Tipe" />
</SelectTrigger>
<SelectContent>
@ -244,10 +244,14 @@ const LiveReportTable = () => {
</SelectContent>
</Select>
</div>
<div className="">
<div className="w-full md:w-fit">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto" size="md">
<Button
variant="outline"
className="w-full md:ml-auto"
size="md"
>
Filter <ChevronDown />
</Button>
</DropdownMenuTrigger>
@ -287,10 +291,14 @@ const LiveReportTable = () => {
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="flex items-center">
<div className="flex items-center w-full md:w-fit">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto" size="md">
<Button
variant="outline"
className="md:ml-auto w-full"
size="md"
>
Columns <ChevronDown />
</Button>
</DropdownMenuTrigger>

View File

@ -1,11 +1,5 @@
"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 FormDetailLiveReport from "@/components/form/schedule/live-report-detail-form";
const LiveReportDetailPage = () => {

View File

@ -1,12 +1,5 @@
"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 FormUpdateLiveReport from "@/components/form/schedule/live-report-update-form";
const LiveReportUpdatePage = () => {

View File

@ -16,7 +16,7 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { cn, getCookiesDecrypt } from "@/lib/utils";
import { CalendarIcon, Clock1, Locate, MapPin, User2 } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { addDays, format, parseISO, setDate } from "date-fns";
@ -32,6 +32,7 @@ import {
detailSchedule,
listScheduleNext,
listScheduleToday,
postApprovalSchedule,
postSchedule,
} from "@/service/schedule/schedule";
import {
@ -42,6 +43,18 @@ import {
} from "@/components/ui/accordion";
import { formatDateToIndonesian } from "@/utils/globals";
import { formatDate } from "@fullcalendar/core/index.js";
import { Icon } from "@iconify/react/dist/iconify.js";
import { useTranslations } from "next-intl";
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Badge } from "@/components/ui/badge";
import { close } from "@/config/swal";
import { Checkbox } from "@/components/ui/checkbox";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@ -58,14 +71,23 @@ interface Detail {
speakerName: string;
addressLat: number;
addressLong: number;
isYoutube: boolean;
youtubeUrl: string;
needApprovalFrom: number;
uploadedById: number;
}
export default function FormDetailLiveReport() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
const userId = getCookiesDecrypt("uie");
const userLevelId = getCookiesDecrypt("ulie");
const roleId = getCookiesDecrypt("urie");
const userLevelNumber = getCookiesDecrypt("ulne");
console.log("cookie", userId, userLevelId, roleId, userLevelNumber);
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [date, setDate] = useState<DateRange | undefined>();
@ -75,6 +97,12 @@ export default function FormDetailLiveReport() {
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const t = useTranslations("Form");
const [status, setStatus] = useState("");
const [description, setDescription] = useState("");
const [modalOpen, setModalOpen] = useState(false);
const {
control,
handleSubmit,
@ -82,9 +110,6 @@ export default function FormDetailLiveReport() {
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
async function getDataByDate() {
@ -98,27 +123,30 @@ export default function FormDetailLiveReport() {
}
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);
}
getDataByDate();
}
}
initState();
}, [refresh, setValue]);
}, [refresh]);
async function initState() {
if (id) {
loading();
const response = await detailSchedule(id);
close();
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);
}
getDataByDate();
}
}
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
@ -128,6 +156,75 @@ export default function FormDetailLiveReport() {
setEndTime(e.target.value);
};
const actionApproval = (e: string) => {
setStatus(e);
setDescription("");
setModalOpen(true);
};
const submit = async () => {
if (
description?.length > 1 &&
(Number(status) == 3 || Number(status) == 2 || Number(status) == 4)
) {
save();
}
};
async function save() {
const data = {
scheduleId: Number(id),
statusId: Number(status),
message: description,
isPublish: status === "2",
placements: schedulePlacements?.filter((val) => val != "all")?.join(","),
};
loading();
const response = await postApprovalSchedule(data);
close();
setModalOpen(false);
if (response?.error) {
error(response?.message);
return false;
}
initState();
return false;
}
const [schedulePlacements, setSchedulePlacements] = useState<string[]>([]);
const setupPlacement = (placement: string, checked: boolean) => {
let temp = [...schedulePlacements];
if (checked) {
if (placement === "all") {
temp = ["all", "mabes", "polda", "international"];
} else {
const now = temp;
now.push(placement);
if (now.length === 3 && !now.includes("all")) {
now.push("all");
}
temp = now;
}
} else {
if (placement === "all") {
temp = [];
} else {
const now = temp.filter((a) => a !== placement);
console.log("now", now);
temp = now;
if (now.length === 3 && now.includes("all")) {
const newData = now.filter((b) => b !== "all");
temp = newData;
}
}
}
console.log("temp");
setSchedulePlacements(temp);
};
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
@ -157,39 +254,24 @@ export default function FormDetailLiveReport() {
<div className="mt-6">
<Label>Live Streaming</Label>
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<p className="text-sm">Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
checked={detail.isYoutube}
color="primary"
id="c2"
onCheckedChange={(checked) =>
setIsLiveStreamingEnabled(checked)
}
/>
</div>
</div>
</div>
{isLiveStreamingEnabled && (
{detail.isYoutube && (
<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"
/>
)}
<Input
size={"md"}
type="text"
value={detail.youtubeUrl}
placeholder="Masukan ID youtube"
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
@ -332,12 +414,6 @@ export default function FormDetailLiveReport() {
) : (
""
)}
{/* Submit Button
<div className="mt-4">
<Button type="submit" color="primary">
Submit
</Button>
</div> */}
</div>
</Card>
<Card className="w-full lg:w-3/12">
@ -349,13 +425,31 @@ export default function FormDetailLiveReport() {
</AccordionTrigger>
<AccordionContent>
{todayList?.length > 0 ? (
<ul className="list-disc ml-4">
<div className="list-disc ">
{todayList.map((item: any, index) => (
<li key={index} className="py-1">
{item.name}
</li>
<div key={index} className="">
<li className="text-base font-semibold">{item.title}</li>
<p className="text-sm ml-5 flex my-2 gap-2">
<CalendarIcon size={20} />
{formatDate(item?.startDate)}-
{formatDate(item?.endDate)}
</p>
<p className="text-sm ml-5 flex my-2 gap-2">
<Clock1 size={20} />
{item?.startTime}-{item?.endTime}
</p>
<p className="text-sm ml-5 flex items-center my-2 gap-2">
<MapPin size={20} />
{item?.address}
</p>
<p className="text-sm ml-5">Disampaikan oleh:</p>
<p className="text-sm ml-5 flex my-2 items-center gap-2">
<User2 size={20} />
{item?.speakerTitle} {item?.speakerName}
</p>
</div>
))}
</ul>
</div>
) : (
<p className="text-gray-500">Tidak ada jadwal hari ini</p>
)}
@ -373,26 +467,25 @@ export default function FormDetailLiveReport() {
{nextDayList.map((item: any, index) => (
<div key={index} className="">
<li className="text-base font-semibold">{item.title}</li>
<p className="text-sm ml-5 flex my-2">
<p className="text-sm ml-5 flex my-2 gap-2">
<CalendarIcon size={20} />
{formatDate(item?.startDate)}-
{formatDate(item?.endDate)}
</p>
<p className="text-sm ml-5 flex my-2">
<p className="text-sm ml-5 flex my-2 gap-2">
<Clock1 size={20} />
{item?.startTime}-{item?.endTime}
</p>
<p className="text-sm ml-5 flex items-center my-2">
<MapPin size={50} />
<p className="text-sm ml-5 flex items-center my-2 gap-2">
<MapPin size={20} />
{item?.address}
</p>
<p className="text-sm ml-5">Disampaikan oleh:</p>
<p className="text-sm ml-5 flex my-2">
<User2 />
<p className="text-sm ml-5 flex my-2 items-center gap-2">
<User2 size={20} />
{item?.speakerTitle} {item?.speakerName}
</p>
</div>
// <p>{item.startDate}</p>
))}
</div>
) : (
@ -401,7 +494,162 @@ export default function FormDetailLiveReport() {
</AccordionContent>
</AccordionItem>
</Accordion>
{Number(detail?.needApprovalFrom) == Number(userLevelId) &&
Number(userLevelNumber) < 2 ? (
Number(detail?.uploadedById) == Number(userId) ? (
""
) : (
<div className="flex flex-col gap-2 p-3">
<Button
onClick={() => actionApproval("2")}
color="primary"
type="button"
>
<Icon icon="fa:check" className="mr-3" />
{t("accept")}
</Button>
<Button
onClick={() => actionApproval("3")}
className="bg-orange-400 hover:bg-orange-300"
type="button"
>
<Icon icon="fa:comment-o" className="mr-3" /> {t("revision")}
</Button>
<Button
onClick={() => actionApproval("4")}
color="destructive"
type="button"
>
<Icon icon="fa:times" className="mr-3" />
{t("reject")}
</Button>
</div>
)
) : (
""
)}
</Card>
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
<DialogContent className="overflow-y-auto">
<DialogHeader>
<DialogTitle>{t("leave-comment")}</DialogTitle>
</DialogHeader>
<div className="flex flex-col gap-1 text-sm">
<p>
{" "}
Status:{" "}
<span
className={
status === "2"
? "text-primary"
: status === "3"
? "text-warning"
: "text-destructive"
}
>
{status === "2"
? "Disetujui"
: status === "3"
? "Revisi"
: "Ditolak"}
</span>
</p>
{status === "2" && (
<div className="flex flex-row gap-2">
<div className="flex items-center space-x-2">
<Checkbox
id="terms"
value="all"
checked={schedulePlacements?.includes("all")}
onCheckedChange={(e) => setupPlacement("all", Boolean(e))}
/>
<label
htmlFor="terms"
className="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
{t("all")}
</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={schedulePlacements?.includes("mabes")}
onCheckedChange={(e) => setupPlacement("mabes", Boolean(e))}
/>
<label
htmlFor="terms"
className="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Nasional
</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={schedulePlacements?.includes("polda")}
onCheckedChange={(e) => setupPlacement("polda", Boolean(e))}
/>
<label
htmlFor="terms"
className="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Wilayah
</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={schedulePlacements?.includes("international")}
onCheckedChange={(e) =>
setupPlacement("international", Boolean(e))
}
/>
<label
htmlFor="terms"
className="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Internasional
</label>
</div>
</div>
)}
<p>Deskripsi:</p>
<div className="flex flex-col gap-4">
<Textarea
placeholder="Type your message here."
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</div>
</div>
<DialogFooter>
<Button
type="button"
color="primary"
onClick={() => submit()}
disabled={
description.length < 1 ||
(schedulePlacements.length < 1 && status === "2")
}
>
{t("submit")}
</Button>
<Button
type="button"
color="destructive"
onClick={() => {
setModalOpen(false);
}}
>
{t("cancel")}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
}

View File

@ -39,12 +39,14 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { toast } from "sonner";
import { close, loading } from "@/config/swal";
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" }),
title: z.string().min(1, { message: "Judul harus diisi" }),
level: z.string().min(1, { message: "Pangkat harus diisi" }),
name: z.string().min(1, { message: "Nama harus diisi" }),
location: z.string().min(1, { message: "Lokasi harus diisi" }),
});
export default function FormLiveReport() {
@ -56,9 +58,11 @@ export default function FormLiveReport() {
const [startTime, setStartTime] = useState("08:00");
const [endTime, setEndTime] = useState("09:00");
const [scheduleTypeId, setScheduleTypeId] = React.useState<string>("1");
const [youtubeUrl, setYoutubeUrl] = useState("");
const [date, setDate] = React.useState<DateRange | undefined>({
from: new Date(2024, 0, 1),
from: new Date(),
to: new Date(),
});
const handleStartTime = (e: any) => {
@ -106,12 +110,14 @@ export default function FormLiveReport() {
startDate: date?.from ? format(date.from, "yyyy-MM-dd") : null,
endDate: date?.to ? format(date.to, "yyyy-MM-dd") : null,
isYoutube: isLiveStreamingEnabled,
youtubeUrl: isLiveStreamingEnabled ? youtubeUrl : null,
scheduleTypeId: Number(scheduleTypeId),
};
console.log("Form Data Submitted:", requestData);
loading();
const response = await postSchedule(requestData);
close();
if (response?.error) {
error(response?.message);
return false;
@ -134,6 +140,11 @@ export default function FormLiveReport() {
};
const onSubmit = (data: TaskSchema) => {
if (isLiveStreamingEnabled && youtubeUrl == "") {
toast(<p className="text-red-600">Youtube ID harus diisi</p>);
return false;
}
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
@ -195,24 +206,13 @@ export default function FormLiveReport() {
{isLiveStreamingEnabled && (
<div className="mb-2 mt-1">
<Controller
control={control}
name="title"
render={({ field }) => (
<Input
size={"md"}
type="text"
value={field.value}
onChange={field.onChange}
placeholder="Masukan ID youtube"
/>
)}
<Input
size={"md"}
type="text"
value={youtubeUrl}
onChange={(e) => setYoutubeUrl(e.target.value)}
placeholder="Masukan Youtube ID"
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
<div className="flex flex-col space-y-2">
@ -314,9 +314,11 @@ export default function FormLiveReport() {
/>
)}
/>
<div className="invalid-feedback">
{errors.location?.message}
</div>
{errors.location?.message && (
<p className="text-red-400 text-sm">
{errors.location.message}
</p>
)}
</div>
<p className="text-sm mt-4 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col ">
@ -376,9 +378,9 @@ export default function FormLiveReport() {
</form>
</div>
</Card>
<Card className="w-full lg:w-3/12">
{/* <Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</Card> */}
</div>
);
}

View File

@ -9,7 +9,7 @@ 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 { useParams, useRouter, useSearchParams } from "next/navigation";
import { Switch } from "@/components/ui/switch";
import {
Popover,
@ -29,12 +29,13 @@ 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 { toast } from "sonner";
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" }),
title: z.string().min(1, { message: "Judul harus diisi" }),
level: z.string().min(1, { message: "Pangkat harus diisi" }),
name: z.string().min(1, { message: "Nama harus diisi" }),
location: z.string().min(1, { message: "Lokasi harus diisi" }),
});
interface Detail {
@ -49,8 +50,9 @@ interface Detail {
export default function FormUpdateLiveReport() {
const { id } = useParams() as { id: string };
console.log(id);
const router = useRouter();
const params = useSearchParams();
const scheduleTypeId = params?.get("scheduleType");
const MySwal = withReactContent(Swal);
const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false);
type TaskSchema = z.infer<typeof taskSchema>;
@ -60,7 +62,7 @@ export default function FormUpdateLiveReport() {
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const [location, setLocation] = useState("");
const [youtubeUrl, setYoutubeUrl] = useState("");
const {
control,
@ -69,28 +71,28 @@ export default function FormUpdateLiveReport() {
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;
const data = response?.data?.data;
setDetail(details);
if (details) {
if (data) {
setDetail(data);
setValue("title", data.title);
setValue("level", data.speakerTitle);
setValue("name", data.speakerName);
setValue("location", data.address);
setDate({
from: parseISO(details.startDate),
to: parseISO(details.endDate),
from: parseISO(data.startDate),
to: parseISO(data.endDate),
});
}
if (details) {
setStartTime(details.startTime);
setEndTime(details.endTime);
setLocation(details.address);
setStartTime(data.startTime);
setYoutubeUrl(data.youtubeUrl);
setEndTime(data.endTime);
setIsLiveStreamingEnabled(data.isYoutube);
}
}
}
@ -107,7 +109,6 @@ export default function FormUpdateLiveReport() {
const handleLocationChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const value = e.target.value;
setLocation(value);
setValue("location", value);
};
@ -126,6 +127,7 @@ export default function FormUpdateLiveReport() {
endDate: string | null;
isYoutube: boolean;
scheduleTypeId: number;
youtubeUrl: string;
} = {
title: data.title,
address: data.location,
@ -138,7 +140,8 @@ export default function FormUpdateLiveReport() {
startDate: date?.from ? format(date.from, "yyyy-MM-dd") : null,
endDate: date?.to ? format(date.to, "yyyy-MM-dd") : null,
isYoutube: isLiveStreamingEnabled,
scheduleTypeId: 1,
scheduleTypeId: Number(scheduleTypeId),
youtubeUrl: youtubeUrl,
};
if (id) {
@ -165,11 +168,16 @@ export default function FormUpdateLiveReport() {
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/en/contributor/schedule/press-conference");
router.push("/en/contributor/schedule/live-report");
});
};
const onSubmit = (data: TaskSchema) => {
if (isLiveStreamingEnabled && youtubeUrl == "") {
toast(<p className="text-red-600">Youtube ID harus diisi</p>);
return false;
}
MySwal.fire({
title: "Simpan Data",
text: "Apakah Anda yakin ingin menyimpan data ini?",
@ -191,7 +199,7 @@ export default function FormUpdateLiveReport() {
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Konferensi Pers</p>
<form onSubmit={handleSubmit(onSubmit)}>
{detail !== undefined ? (
{detail ? (
<div className=" gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2">
@ -202,7 +210,7 @@ export default function FormUpdateLiveReport() {
render={({ field }) => (
<Input
type="text"
defaultValue={detail?.title}
value={field.value}
onChange={field.onChange}
/>
)}
@ -219,7 +227,7 @@ export default function FormUpdateLiveReport() {
<div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p>
<Switch
defaultChecked={isLiveStreamingEnabled}
checked={isLiveStreamingEnabled}
color="primary"
id="c2"
onCheckedChange={(checked) =>
@ -231,25 +239,14 @@ export default function FormUpdateLiveReport() {
</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"
/>
)}
<div className="mb-2 mt-1">
<Input
size={"md"}
type="text"
value={youtubeUrl}
onChange={(e) => setYoutubeUrl(e.target.value)}
placeholder="Masukan Youtube ID"
/>
{errors.title?.message && (
<p className="text-red-400 text-sm">
{errors.title.message}
</p>
)}
</div>
)}
@ -319,7 +316,6 @@ export default function FormUpdateLiveReport() {
<MapHome
draggable
setLocation={(location) => {
setLocation(location);
setValue("location", location);
}}
/>
@ -331,8 +327,8 @@ export default function FormUpdateLiveReport() {
render={({ field }) => (
<Textarea
rows={3}
value={location}
onChange={handleLocationChange}
value={field.value}
onChange={field.onChange}
placeholder="Masukan lokasi"
/>
)}
@ -352,7 +348,7 @@ export default function FormUpdateLiveReport() {
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerTitle}
value={field.value}
onChange={field.onChange}
placeholder="Masukan Nama Pangkat"
/>
@ -375,7 +371,7 @@ export default function FormUpdateLiveReport() {
<Input
size={"md"}
type="text"
defaultValue={detail?.speakerName}
value={field.value}
onChange={field.onChange}
placeholder="Masukan Nama Lengkap"
/>
@ -401,9 +397,9 @@ export default function FormUpdateLiveReport() {
</form>
</div>
</Card>
<Card className="w-full lg:w-3/12">
{/* <Card className="w-full lg:w-3/12">
<div className="px-3 py-3">Jadwal Selanjutnya</div>
</Card>
</Card> */}
</div>
);
}

View File

@ -1804,6 +1804,42 @@ export function getMenuList(pathname: string, t: any): Group[] {
},
],
},
// {
// groupLabel: "",
// id: "schedule",
// menus: [
// {
// id: "schedule",
// href: "/contributor/schedule",
// label: t("schedule"),
// active: pathname.includes("/schedule"),
// icon: "uil:schedule",
// submenus: [
// {
// href: "/contributor/schedule/press-conference",
// label: t("press-conference"),
// active: pathname.includes("/schedule/press-conference"),
// icon: "heroicons:arrow-trending-up",
// children: [],
// },
// {
// href: "/contributor/schedule/event",
// label: t("event"),
// active: pathname.includes("/schedule/event"),
// icon: "heroicons:shopping-cart",
// children: [],
// },
// {
// href: "/contributor/schedule/press-release",
// label: t("press-release"),
// active: pathname.includes("/schedule/press-release"),
// icon: "heroicons:shopping-cart",
// children: [],
// },
// ],
// },
// ],
// },
{
groupLabel: "",
id: "schedule",
@ -1816,26 +1852,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
icon: "uil:schedule",
submenus: [
{
href: "/contributor/schedule/press-conference",
label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"),
href: "/contributor/schedule/live-report",
label: t("live-report"),
active: pathname.includes("/schedule/live-report"),
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/contributor/schedule/event",
label: t("event"),
active: pathname.includes("/schedule/event"),
icon: "heroicons:shopping-cart",
children: [],
},
{
href: "/contributor/schedule/press-release",
label: t("press-release"),
active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart",
children: [],
},
// {
// href: "/contributor/schedule/calendar-polri",
// label: t("calendar-polri"),
// active: pathname.includes("/schedule/calendar-polri"),
// icon: "heroicons:arrow-trending-up",
// children: [],
// },
],
},
],

View File

@ -39,6 +39,11 @@ export async function postSchedule(data: any) {
return httpPostInterceptor(url, data);
}
export async function deleteSchedule(id: string | number) {
const url = `schedule?id=${id}`;
return httpDeleteInterceptor(url);
}
export async function detailSchedule(id: any) {
const url = `public/schedule?id=${id}`;
return httpGetInterceptor(url);
@ -98,3 +103,8 @@ export async function deleteCalendar(id: any) {
const url = `calendars?id=${id}`;
return httpDeleteInterceptor(url);
}
export async function postApprovalSchedule(data: any) {
const url = "schedule/approval";
return httpPostInterceptor(url, data);
}