diff --git a/src/pages/index.tsx b/src/pages/index.tsx index c4cc2a6..59465d8 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -6,112 +6,18 @@ import { useMemo, useState } from "react"; import { EventScale, EventStatus } from "@/types/event"; import { Switch } from "@headlessui/react"; import { sendTrack } from "@/utils/track"; - -enum DurationType { - Passed = "passed", //already done. - Now = "now", // in the duration of event. - Soon = "soon", // in the same month of event start date. - Next = "next", // not start yet but plan in this year. - NextYear = "nextYear", // in the next year -} +import { DurationType } from "@/types/list"; +import { filteringEvents, groupByCustomDurationEvent } from "@/utils/event"; export default function Home(props: { events: Event[] }) { const [selectedFilter, setFilter] = useState({ onlyAvailable: false, eventScale: ["All"], }); - const filteredEvents = props.events.filter((event) => { - const now = Date.now(); - const endTime = event.endDate - ? new Date(new Date(event.endDate).setHours(23, 59, 59, 999)).getTime() - : null; - if (selectedFilter.onlyAvailable) { - if (event.status === EventStatus.EventCancelled) { - return false; - } - if (endTime && now > endTime) { - return false; - } - } - - if ( - selectedFilter.eventScale[0] !== "All" && - !selectedFilter.eventScale.includes(event.scale) - ) { - return false; - } - return true; - }); - const groupByCustomDurationEvent = useMemo(() => { - const currentMonth = new Date().getUTCMonth() + 1; - const now = Date.now(); - - const durationObject: { [x in DurationType]: Event[] } = { - now: [], - soon: [], - next: [], - nextYear: [], - passed: [], - }; - - filteredEvents.forEach((event) => { - const startTime = event.startDate - ? new Date(new Date(event.startDate).setHours(0, 0, 0, 0)).getTime() - : null; - const endTime = event.endDate - ? new Date(new Date(event.endDate).setHours(23, 59, 59, 999)).getTime() - : null; - - // if a event end date is next year, then count it in next year not in current year. - const isNextYear = - event.startDate && event.endDate - ? new Date(event.startDate).getUTCFullYear() > - new Date().getUTCFullYear() || - new Date(event.endDate).getUTCFullYear() > - new Date().getUTCFullYear() - : false; - - const startMonth = event.startDate - ? new Date(event.startDate).getUTCMonth() + 1 + (isNextYear ? 12 : 0) - : null; - const endMonth = event.endDate - ? new Date(event.endDate).getUTCMonth() + 1 + (isNextYear ? 12 : 0) - : null; - - if ( - startTime === null || - endTime === null || - startMonth === null || - endMonth === null - ) { - return durationObject.next.push(event); - } - //Passed events - if (now > endTime) { - return durationObject.passed.push(event); - } - - if (startMonth <= currentMonth) { - //Now events - if (now > startTime && now < endTime) { - return durationObject.now.push(event); - } else { - //Soon events - return durationObject.soon.push(event); - } - } - - //Next events - if (startMonth > currentMonth) { - if (startMonth > 12) { - return durationObject.nextYear.push(event); - } - return durationObject.next.push(event); - } - }); - return durationObject; - }, [filteredEvents]); + const filteredEvents = filteringEvents(props.events, selectedFilter); + const groupByCustomDurationEvents = + groupByCustomDurationEvent(filteredEvents); return ( <> @@ -131,12 +37,12 @@ export default function Home(props: { events: Event[] }) {

)} - {Object.keys(groupByCustomDurationEvent).map((type) => - groupByCustomDurationEvent[type as DurationType].length ? ( + {Object.keys(groupByCustomDurationEvents).map((type) => + groupByCustomDurationEvents[type as DurationType].length ? ( ) : null )} diff --git a/src/types/list.ts b/src/types/list.ts new file mode 100644 index 0000000..b67bb70 --- /dev/null +++ b/src/types/list.ts @@ -0,0 +1,14 @@ +import { EventScale } from "./event"; + +export enum DurationType { + Passed = "passed", //already done. + Now = "now", // in the duration of event. + Soon = "soon", // in the same month of event start date. + Next = "next", // not start yet but plan in this year. + NextYear = "nextYear", // in the next year +} + +export type SelectedFilterType = { + onlyAvailable: boolean; + eventScale: (typeof EventScale)[keyof typeof EventScale][]; +}; diff --git a/src/utils/event.ts b/src/utils/event.ts index 355d494..bf28104 100644 --- a/src/utils/event.ts +++ b/src/utils/event.ts @@ -1,5 +1,15 @@ +import { EventStatus } from "@/types/event"; +import { DurationType, SelectedFilterType } from "@/types/list"; import { Event } from "@/xata/xata"; import groupBy from "lodash-es/groupBy"; +import { + isBefore, + isAfter, + endOfDay, + startOfDay, + endOfToday, + startOfToday, +} from "date-fns"; export function sortByStartDateDesc(data: Event[]) { const groupByStartDate = groupBy(data, (e) => @@ -21,3 +31,106 @@ export function sortByStartDateDesc(data: Event[]) { return years.map((year) => ({ year, events: groupByStartDate[year] })); } + +export function filteringEvents( + events: Event[], + selectedFilter: SelectedFilterType +) { + return events.filter((event) => { + const now = Date.now(); + const endTime = event.endDate + ? new Date(new Date(event.endDate).setHours(23, 59, 59, 999)).getTime() + : null; + if (selectedFilter.onlyAvailable) { + // for now, if event is cancelled, the data willn't include it at all. + // if (event.status === EventStatus.EventCancelled) { + // return false; + // } + if (endTime && now > endTime) { + return false; + } + } + + if ( + selectedFilter.eventScale[0] !== "All" && + !selectedFilter.eventScale.includes(event.scale) + ) { + return false; + } + return true; + }); +} + +function isDateBelongNextYear(testDate: string) { + return new Date(testDate).getUTCFullYear() > new Date().getUTCFullYear(); +} + +function getDateMonth(testDate: string) { + const isNextYear = isDateBelongNextYear(testDate); + const dateBelongMonth = new Date(testDate).getUTCMonth() + 1; + return isNextYear ? dateBelongMonth + 12 : dateBelongMonth; +} + +export function groupByCustomDurationEvent(events: Event[]) { + const currentMonth = new Date().getUTCMonth() + 1; + const now = Date.now(); + + const durationObject: { [x in DurationType]: Event[] } = { + now: [], + soon: [], + next: [], + nextYear: [], + passed: [], + }; + + events.forEach((event) => { + const startTime = event.startDate + ? new Date(new Date(event.startDate).setHours(0, 0, 0, 0)).getTime() + : null; + const endTime = event.endDate + ? new Date(new Date(event.endDate).setHours(23, 59, 59, 999)).getTime() + : null; + + const startMonth = event.startDate + ? getDateMonth(event.startDate.toString()) + : null; + const endMonth = event.endDate + ? getDateMonth(event.endDate.toString()) + : null; + + //next events + if ( + startTime === null || + endTime === null || + startMonth === null || + endMonth === null + ) { + return durationObject.next.push(event); + } + + //Passed events + if (isAfter(now, endTime)) { + return durationObject.passed.push(event); + } + + //Now events + if (isAfter(now, startTime) && isBefore(now, endTime)) { + return durationObject.now.push(event); + } + + //Soon events + if (startMonth === currentMonth && isBefore(now, startTime)) { + return durationObject.soon.push(event); + } + + //Next events + if (startMonth > currentMonth) { + if (startMonth > 12) { + return durationObject.nextYear.push(event); + } + return durationObject.next.push(event); + } + }); + + return durationObject; +}