From dcda74d61d2aac939f9b8313247528c26bf47559 Mon Sep 17 00:00:00 2001 From: Kevin Wu Date: Sun, 21 Jul 2024 17:58:58 -0700 Subject: [PATCH] feat: actually extract hooks --- src/app/pages/Events/useEvents.js | 47 +++++++++++++++++++++++++++++++ src/app/pages/Events/utils.js | 46 ++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/app/pages/Events/useEvents.js create mode 100644 src/app/pages/Events/utils.js diff --git a/src/app/pages/Events/useEvents.js b/src/app/pages/Events/useEvents.js new file mode 100644 index 00000000..389d2207 --- /dev/null +++ b/src/app/pages/Events/useEvents.js @@ -0,0 +1,47 @@ +import { useState, useEffect, useCallback } from "react"; +import { parseEvents, joinEvents } from "./utils.js"; +import EVENT_DATA from "assets/data/events/all.json"; +import { client } from "sanity-client.js"; + +const legacyEvents = parseEvents(EVENT_DATA); // events from manual JSON file + +export const useEvents = () => { + const [events, setEvents] = useState([]); + + const fetchEvents = useCallback(async () => { + const result = await client.fetch( + `*[_type == "event"] | order(time desc)`, + {}, + ); + return result.map((item) => ({ + title: item.title, + time: item.time, + duration: item.duration, + type: item.type, + desc: item.desc, + place: item.place, + links: item.links + ? item.links.map((linkItem) => ({ + label: linkItem.label, + link: linkItem.link, + })) + : [], + })); + }, []); + + useEffect(() => { + const getEvents = async () => { + try { + const data = await fetchEvents(); + const eventData = parseEvents(data); + const joinedEvents = joinEvents(eventData, legacyEvents); + setEvents(joinedEvents); + } catch (e) { + console.error(e); + } + }; + getEvents(); + }, [fetchEvents, legacyEvents]); + + return events; +}; diff --git a/src/app/pages/Events/utils.js b/src/app/pages/Events/utils.js new file mode 100644 index 00000000..eede8f3b --- /dev/null +++ b/src/app/pages/Events/utils.js @@ -0,0 +1,46 @@ +export const parseEvents = (events) => { + let eventData = { + upcoming: [], + past: [], + }; + + const now = new Date(); + + for (let event of events) { + const eventTime = new Date( + new Date(event.time).getTime() + event.duration * 60000, + ); + + if (now < eventTime) { + eventData.upcoming.unshift(event); + } else { + eventData.past.push(event); + } + } + + return eventData; +}; + +export const joinEvents = (a, b) => { + // handle uninitialized/unparsed event lists + a = a.upcoming && a.past ? a : { upcoming: [], past: [] }; + b = b.upcoming && b.past ? b : { upcoming: [], past: [] }; + + const combinedUpcoming = [...a.upcoming, ...b.upcoming]; + const combinedPast = [...a.past, ...b.past]; + + let nextEvent = null; + + if (combinedUpcoming.length > 0) { + combinedUpcoming.sort( + (e1, e2) => new Date(e1.time) - new Date(e2.time), + ); + nextEvent = combinedUpcoming.at(0) ?? null; + } + + return { + upcoming: combinedUpcoming, + past: combinedPast, + next: nextEvent, + }; +};