code 1

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 8

saya punya code ini = "use client";

import FullCalendar from "@fullcalendar/react";


import dayGridPlugin from "@fullcalendar/daygrid";
import listWeekPlugin from "@fullcalendar/list";
import { Avatar, Button, Checkbox, Input, Modal, Select, Spin } from "antd";
import type { RadioChangeEvent } from "antd";
import { useEffect, useRef, useState } from "react";
import NotificationBellIcon from "@/components/common/notificationBellIcon";

import {
FiBell,
FiChevronLeft,
FiChevronRight,
FiFilter,
FiGrid,
FiInfo,
FiList,
FiSearch,
} from "react-icons/fi";
import dayjs from "dayjs";
import Link from "next/link";
import { UserOutlined, PlusOutlined } from "@ant-design/icons";
import { imageType } from "@/utils/imageType";
import Image from "next/image";
import { useGetCalendarQuery } from "@/store/api/user/eventApi";
import CheckboxValueType from "antd/es/checkbox/Group";
import { useRouter } from "next/navigation";
import ThemeSwitcher from "@/components/common/themeSwitcher";
import RadioButtonGroup from "@/components/common/feed/radioButtonGroup";
import { useIsDesktop } from "@/hooks/useIsDesktop";
import ListCalendar from "./partials/listCalendar";
import GridCalendar from "./partials/gridCalendar";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "@/store";
import BottomNav from "@/components/common/feed/bottomNav";
import debounce from "lodash/debounce";

interface EventData {
event_id: string;
title: string;
event_date_start: string;
event_date_end: string;
location: {
city: string;
};
category: string;
subcategory: string;
type: string;
requirements: {
age_from: string;
age_to: string;
gender: string;
skill_level: string;
};
creator: string;
creater: {
avatar: string;
};
}
export default function Calendar() {
const router = useRouter();
const [calendarView, setCalendarView] = useState("dayGridMonth");
const calendarRef = useRef<FullCalendar>(null);
const [dataCalendar, setDataCalendar] = useState<any>([]);
const [calendarTitle, setCalendarTitle] = useState("");
const [infoOpen, setInfoOpen] = useState(false);
const [dataEvent, setDataEvent] = useState<{ [key: string]: EventData[] }>(
{}
);
const [startDate, setStartDate] = useState("");
const [endDate, setEndDate] = useState("");
const [isPersonal, setIspersonal] = useState(false);
const [eventPlace, setEventPlace] = useState("");

const [checkedValues, setCheckedValues] = useState<string[]>([]);


const [searchQuery, setSearchQuery] = useState("");

const isDesktop = useIsDesktop(987);

const trigger = useSelector((state: RootState) => state.calendar.trigger);

const {
data,
refetch,
isFetching,
isUninitialized,
isLoading,
isSuccess,
isError,
} = useGetCalendarQuery(
{
date_start_from: startDate,
date_start_to: endDate,
is_personal: isPersonal,
event_place: eventPlace,
search: searchQuery
},
{ skip: !startDate && !endDate && !eventPlace }
);

useEffect(() => {
if (!isUninitialized && !isLoading && (isSuccess || isError)) {
refetch();
}
}, [eventPlace, isUninitialized, isLoading, isSuccess, isError]);

useEffect(() => {
if (data) {
setDataEvent(data?.data);
}
}, [data]);

useEffect(() => {
if (trigger > 0 && !isUninitialized) {
refetch();
}
}, [trigger, isUninitialized]);
const handleEventPlaceChange = (checkedList: any) => {
setCheckedValues(checkedList as string[]);
let place = "";
if (checkedList.includes("1")) place += "on-ice,";
if (checkedList.includes("2")) place += "off-ice,";

place = place.endsWith(",") ? place.slice(0, -1) : place;


setEventPlace(place);
};

const handleDatesRender = (info: any) => {


const start = dayjs(info.view.currentStart).format("YYYY-MM-DDTHH:mm:ssZ");
const end = dayjs(info.view.currentEnd).format("YYYY-MM-DDTHH:mm:ssZ");
setStartDate(start);
setEndDate(end);
};
const handlePrev = () => {
if (calendarRef.current) {
calendarRef.current.getApi().prev();
updateCalendarTitle();
}
};

const handleNext = () => {


if (calendarRef.current) {
calendarRef.current.getApi().next();
updateCalendarTitle();
}
};
const updateCalendarTitle = () => {
if (calendarRef.current) {
const title = calendarRef.current.getApi().view.title;
setCalendarTitle(title);
}
};
useEffect(() => {
updateCalendarTitle();
}, [calendarView]);

useEffect(() => {
const formattedEvents = Object.keys(dataEvent).map((date: string) => {
const eventsForDate = dataEvent[date];
return eventsForDate.map((event: EventData) => ({
event_id: event.event_id,
title: event.title,
start: date,
event_date_end: event.event_date_end,
creater: event.creater?.avatar,
location: event.location?.city,
category: event.category,
subcategory: event.subcategory,
type: event.type,
age_from: event.requirements.age_from,
age_to: event.requirements.age_to,
creator: event.creator,
skill_level: event.requirements.skill_level,
gender: event.requirements.gender,
}));
});
const flattenedEvents = formattedEvents.flat();

setDataCalendar(flattenedEvents);
}, [dataEvent]);

const calenderViewChange = ({ target: { value } }: RadioChangeEvent) => {


setCalendarView(value);
};
const handleDetail = (info: any) => {
const id = info.event.extendedProps.event_id;
router.push(`/calendar/${id}`);
};

const handleSearchChange = debounce((e) => {


setSearchQuery(e.target.value);
}, 100);

return (
<div className="py-[20px] md:pb-0 pb-[90px]">
<div className="px-4 border-b-[1px] border-light-borderGrey dark:border-dark-
borderGrey border-solid">
<div className=" pb-4 flex gap-3 items-center">
<div className="flex-1">
<Input
placeholder="Search event here"
prefix={<FiSearch size="20" className="text-[#D0D5DD]" />}
onChange={handleSearchChange}
/>
</div>
<div className="pt-2">
<NotificationBellIcon />
</div>
</div>
<div className="flex items-center md:pb-0 pb-3">
<div>
<div className="md:text-[32px] text-[18px] font-[600] pr-5">
{calendarTitle}
</div>
</div>
<div>
<div className="flex items-center gap-3">
<div>
<Button
onClick={handlePrev}
className="p-0 w-[36px] h-[36px] flex items-center justify-center
bg-[#EAECF0] text-[#475467] hover:bg-[#b1bcd3] border-light-borderGrey dark:border-
dark-borderGrey hover:border-[#b1bcd3]"
>
<FiChevronLeft size="20" />
</Button>
</div>
<div>
<Button
onClick={handleNext}
className="p-0 w-[36px] h-[36px] flex items-center justify-center
bg-[#EAECF0] text-[#475467] hover:bg-[#b1bcd3] border-light-borderGrey dark:border-
dark-borderGrey hover:border-[#b1bcd3]"
>
<FiChevronRight size="20" />
</Button>
</div>
</div>
</div>
{/* <div className="ms-auto">
<RadioButtonGroup
options={[
{
value: "dayGridMonth",
icon: <FiList />,
label: isDesktop ? "Calendar view" : "",
},
{
value: "listWeek",
icon: <FiGrid />,
label: isDesktop ? "List View" : "",
},
]}
defaultValue="dayGridMonth"
onChange={calenderViewChange}
className="switch-calendar"
/>
</div> */}
</div>
</div>
<div className="p-4">
<div className="flex gap-3 justify-between items-center flex-wrap">
<div className="flex gap-3 items-center">
<Button
shape="round"
className={` border-0 text-[#344054] ${
!isPersonal ? "bg-[#D6DCE4] text-[#061E3C]" : "bg-[#F2F4F7]"
}`}
onClick={() => setIspersonal(false)}
>
Master
</Button>
<Button
shape="round"
className={` border-0 text-[#344054] ${
isPersonal ? "bg-[#D6DCE4] text-[#061E3C]" : "bg-[#F2F4F7]"
}`}
onClick={() => setIspersonal(true)}
>
Personal
</Button>
<div>
<FiInfo
className="text-[25px] text-[#D0D5DD] cursor-pointer"
onClick={() => setInfoOpen(true)}
/>
<Modal
title=""
closeIcon={false}
open={infoOpen}
centered
footer={null}
onCancel={() => setInfoOpen(false)}
width={270}
>
<Image
src={imageType.calendarConfirm}
width={63}
height={63}
alt="icon"
className="mx-auto"
/>
<h4 className="text-center font-bold text-[16px] my-2">
Event Color on Calendar
</h4>
<p className="text-center text-light-softerText">
Please remember the color for each event because they
represented by different color.
</p>

<div className="border border-Neutral-300 rounded-lg p-2 my-2">


<div className="flex justify-between">
<div className="flex items-center ml-5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<circle cx="8" cy="8" r="8" fill="#B9E6FE" />
</svg>
<span className="ml-2 font-[500] text-[12px]">
Event Group
</span>
</div>
{/* mid */}
<div className="flex items-center mr-5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<circle cx="8" cy="8" r="8" fill="#FECDD6" />
</svg>
<span className="ml-2 font-[500] text-[12px]">Event</span>
</div>
</div>
</div>

<Button
type="primary"
className="w-full"
onClick={() => setInfoOpen(false)}
>
OK
</Button>
</Modal>
</div>
</div>
<div className="flex items-center flex-wrap gap-3 md:w-auto w-full
md:justify-start justify-between">
<div>
<Checkbox.Group
value={checkedValues}
style={{ width: "100%" }}
onChange={(checkedList: any) => {
const newValue =
checkedList.length > 0
? [checkedList[checkedList.length - 1]]
: [];
handleEventPlaceChange(newValue);
}}
>
<Checkbox value="1">On Ice</Checkbox>
<Checkbox value="2">Off Ice</Checkbox>
</Checkbox.Group>
</div>
<div>
{/* <Button type="default" className="flex items-center gap-2">
<FiFilter /> Filter{" "}
</Button> */}
</div>
</div>
</div>
</div>
{isFetching && (
<Spin tip="Loading" size="large" className="h-[200px]">
<div className="content" />
</Spin>
)}

{/* {calendarView == "dayGridMonth" ? ( */}


<FullCalendar
ref={calendarRef}
plugins={[dayGridPlugin, listWeekPlugin]}
initialView="dayGridMonth"
events={dataCalendar}
headerToolbar={false}
eventClick={handleDetail}
datesSet={handleDatesRender}
dayMaxEvents={1}
handleWindowResize={true}
eventContent={(eventInfo) => {
// console.log("eventInfo = "+ JSON.stringify(eventInfo, null, 2));
return (
<div className="event-card max-h-96 overflow-y-auto">
<GridCalendar eventInfo={eventInfo} isDetail={false} />
</div>
);
}}
contentHeight="auto"
/>
{/* ) : (
<div className="calendar-list">
<div></div>
<FullCalendar
ref={calendarRef}
plugins={[dayGridPlugin, listWeekPlugin]}
initialView="listWeek"
events={dataCalendar}
headerToolbar={false}
eventContent={(eventInfo) => <ListCalendar eventInfo={eventInfo} />}
listDayFormat={false}
listDaySideFormat={false}
handleWindowResize={true}
contentHeight="auto"
/>
</div>
)} */}
<div className="md:hidden block">
<BottomNav />
</div>
</div>
);
}

saya ingin ketika mengarah ke fungsi = const handleSearchChange = debounce((e) => {


setSearchQuery(e.target.value);
}, 100);

maka dijalankan loading ketika masih proses get data dari useGetCalendarQuery

You might also like