kontenhumas-fe/components/form/schedule/pers-release--detail-form.tsx

586 lines
21 KiB
TypeScript

"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, Clock1, Eye, MapPin, Plus, User2 } 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 {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { formatDate } from "@fullcalendar/core/index.js";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Link } from "@/i18n/routing";
import $ from "jquery";
import { detailSchedule, getListScheduleAttachment, listScheduleNext, listScheduleToday } from "@/service/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;
}
interface Attachment {
id: any;
title: string;
fileTypeId: number;
type: number;
fileTypeName: string;
}
export default function FormDetailPressRillis() {
const [open, setOpen] = useState(false);
const { id } = useParams() as { id: string };
const MySwal = withReactContent(Swal);
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 [todayList, setTodayList] = useState([]);
const [nextDayList, setNextDayList] = useState([]);
const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false);
const {
control,
handleSubmit,
setValue,
formState: { errors },
} = useForm<TaskSchema>({
resolver: zodResolver(taskSchema),
defaultValues: {
location: "",
},
});
const [lampiran, setDataLampiran] = useState<Attachment[]>([]);
async function getDataAttachment() {
const response = await getListScheduleAttachment(id);
console.log("data attach", response?.data?.data?.content);
setDataLampiran(response?.data?.data?.content);
}
async function getDataByDate() {
const resToday = await listScheduleToday();
const today = resToday?.data?.data;
setTodayList(today);
const resNext = await listScheduleNext();
const next = resNext?.data?.data;
setNextDayList(next);
}
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();
getDataAttachment();
}, [refresh, setValue]);
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setStartTime(e.target.value);
};
const handleEndTime = (e: React.ChangeEvent<HTMLInputElement>) => {
setEndTime(e.target.value);
};
const handleDestinationUpload = (
type: number,
id: string | number,
setOpen: (open: boolean) => void,
router: any
) => {
setOpen(false); // Tutup modal dialog
if (id !== undefined) {
Cookies.set("scheduleId", id.toString(), { expires: 1 });
Cookies.set("scheduleType", "3", { expires: 1 });
const routes: Record<number, string> = {
1: "/in/contributor/schedule/media/image/create",
2: "/in/contributor/schedule/media/video/create",
3: "/in/contributor/schedule/media/text/create",
4: "/in/contributor/schedule/media/audio/create",
};
router.push(routes[type] || "/admin/schedule/media/audio/create");
}
};
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-6">
<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-6 items-start lg:items-center justify-between">
<div className="flex flex-col space-y-2">
<Label className="mr-3 mb-1">Tanggal</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[280px] lg:w-[250px] justify-start text-left font-normal px-0 md:px-0 lg:px-4",
!date && "text-muted-foreground"
)}
>
<CalendarIcon size={15} className="mr-3" />
{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="space-y-2">
<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 className="mt-6">
{/* 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-6 space-y-2">
<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 mt-6">
DI SAMPAIKAN OLEH
</p>
<div className="flex flex-col ">
<div className="mt-1 space-y-2">
<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 space-y-2">
<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>
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<div className="flex justify-between">
<Button color="primary" size="sm" type="button">
<Plus /> Tambah Lampiran
</Button>
<p>{lampiran?.length || 0} Lampiran</p>
</div>
</DialogTrigger>
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
<h2 className="text-lg font-semibold">
Pilih Jenis Lampiran
</h2>
<div className="space-y-4 gap-y-4">
{[
{
type: 2,
img: "/assets/img/upload-video.png",
label: "Audio Visual",
},
{
type: 1,
img: "/assets/img/upload-image.png",
label: "Foto",
},
{
type: 3,
img: "/assets/img/upload-text.png",
label: "Teks",
},
{
type: 4,
img: "/assets/img/upload-audio.png",
label: "Audio",
},
].map((item) => (
<a
key={item.type}
onClick={() =>
handleDestinationUpload(
item.type,
id,
setOpen,
router
)
}
>
<div className="flex flex-row items-center space-x-4">
<div className="flex flex-col w-4/12 items-center">
<img
src={item.img}
alt={item.label}
className="w-12 h-12"
/>
<h3 className="text-base font-semibold">
{item.label}
</h3>
</div>
<div className="w-8/12">
<p className="text-sm text-gray-600">
Unggah media berupa {item.label.toLowerCase()}{" "}
dengan format sesuai yang didukung.
</p>
</div>
</div>
</a>
))}
</div>
</DialogContent>
</Dialog>
</div>
) : (
""
)}
<div className="mt-6">
<table className="w-full border border-gray-300 rounded-lg">
<thead className="bg-gray-200 text-left">
<tr>
<th className="p-3 font-semibold">Judul Konten</th>
<th className="p-3 font-semibold">Konten</th>
<th className="p-3 font-semibold">Tindakan</th>
<th className="p-3 font-semibold">Aksi</th>
</tr>
</thead>
<tbody>
{lampiran.map((item, index) => (
<tr key={index} className="border-t border-gray-300">
<td className="p-3 text-blue-600 cursor-pointer">
{item.title}
</td>
<td className="p-3">{item.fileTypeName}</td>
<td className="p-3 text-blue-600">Konfersi Ai</td>
<td className="p-3">
<Link
href={
Number(item.fileTypeId) == 1
? `/contributor/content/image/detail/${item.id}`
: Number(item.fileTypeId) == 2
? `/contributor/content/video/detail/${item.id}`
: Number(item.fileTypeId) == 3
? `/contributor/content/teks/detail/${item.id}`
: `/contributor/content/audio/detail/${item.id}`
}
target="_blank"
className="btn"
rel="noreferrer"
>
<Eye
className={
item.type === 1 ? "text-blue-600" : "text-black"
}
/>
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="mt-4 flex justify-end">
<Button type="submit" color="primary">
Submit
</Button>
</div>
</div>
</Card>
<Card className="w-full lg:w-3/12">
<Accordion type="single" collapsible>
{/* Jadwal Hari Ini */}
<AccordionItem value="today">
<AccordionTrigger className="font-semibold">
Jadwal Hari Ini
</AccordionTrigger>
<AccordionContent>
{todayList?.length > 0 ? (
<ul className="list-disc ml-4">
{todayList.map((item: any, index) => (
<li key={index} className="py-1">
{item.name}
</li>
))}
</ul>
) : (
<p className="text-gray-500">Tidak ada jadwal hari ini</p>
)}
</AccordionContent>
</AccordionItem>
{/* Jadwal Selanjutnya */}
<AccordionItem value="next">
<AccordionTrigger className="font-semibold">
Jadwal Selanjutnya
</AccordionTrigger>
<AccordionContent>
{nextDayList?.length > 0 ? (
<div className="list-disc ">
{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">
<CalendarIcon size={20} />
{formatDate(item?.startDate)}-
{formatDate(item?.endDate)}
</p>
<p className="text-sm ml-5 flex my-2">
<Clock1 size={20} />
{item?.startTime}-{item?.endTime}
</p>
<p className="text-sm ml-5 flex items-center my-2">
<MapPin size={50} />
{item?.address}
</p>
<p className="text-sm ml-5">Disampaikan oleh:</p>
<p className="text-sm ml-5 flex my-2">
<User2 />
{item?.speakerTitle} {item?.speakerName}
</p>
</div>
// <p>{item.startDate}</p>
))}
</div>
) : (
<p className="text-gray-500">Tidak ada jadwal selanjutnya</p>
)}
</AccordionContent>
</AccordionItem>
</Accordion>
</Card>
</div>
);
}