From 988163d61946662a95bb57cd7a1b117dc1f68135 Mon Sep 17 00:00:00 2001 From: Hanz Date: Fri, 28 Jun 2024 22:13:14 +0700 Subject: [PATCH] feat(Filters): Added Calendar Highlights section (fixes #924) --- page/src/app.hooks.js | 24 +++++++++++++-- page/src/components/Day/Day.jsx | 30 ++++++++++++++++++- page/src/components/Filters/Filters.jsx | 28 +++++++++++++++-- .../SelectedEvents/SelectedEvents.jsx | 4 ++- 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/page/src/app.hooks.js b/page/src/app.hooks.js index eeddbf364..4a6910a6e 100644 --- a/page/src/app.hooks.js +++ b/page/src/app.hooks.js @@ -87,9 +87,27 @@ export const useDayEvents = (monthEvents, day = null) => { let result = monthEvents; if (filterDay) { result = result.filter( - e => - (e.date[0] && new Date(e.date[0]).getDate() === filterDay.getDate()) || - (e.date[1] && new Date(e.date[1]).getDate() === filterDay.getDate()) + e => { + let retval = false; + + if (e.date[0]) { + const startDate = new Date(e.date[0]); + retval = (startDate.getDate() === filterDay.getDate()); + } + + if (e.date[1]) { + const endDate = new Date(e.date[1]); + retval = retval || (endDate.getDate() === filterDay.getDate()); + } + + if (e.date[0] && e.date[1]) { + const startDate = new Date(e.date[0]); + const endDate = new Date(e.date[1]); + retval = retval || (filterDay >= startDate && endDate >= filterDay); + } + + return retval; + } ); } return result; diff --git a/page/src/components/Day/Day.jsx b/page/src/components/Day/Day.jsx index 5e86bc71a..883ae682f 100644 --- a/page/src/components/Day/Day.jsx +++ b/page/src/components/Day/Day.jsx @@ -1,11 +1,39 @@ import {useDayEvents} from 'app.hooks'; import {useNavigate, useSearchParams, useParams} from 'react-router-dom'; +export function dayEventFilterFactory(search, date) { + // TODO: Make these boolean searchParams boolean, not strings. + let { showEventsMode0, showEventsMode1, showEventsMode2 } = search; + if (showEventsMode0 === undefined) { + showEventsMode0 = 'true'; + } + + return function (event) { + const start = new Date(event.date[0]); + const end = new Date(event.date[1]); + const hrs = 1000 * 60 * 60 * 24 - 1000; // 24 hours - 1 second + // edgeOfDay is crucial to prevent excess marks from appearing because of + // events ending above 00:00:00.000. + // For example, an event is expected to end at 11am. 0am < 11am will be evaluated as 'true'. + // but to mark the end of an event is the work of mode2, not mode1. + const edgeOfDay = end ? date.getTime() + hrs : 0; + + if (showEventsMode0 == 'true' && start.toDateString() == date.toDateString()) return true; + if (showEventsMode1 == 'true' && end && start < date && edgeOfDay < end) return true; + // TODO: One-day events ends at the same day, it should be included as well. + if (showEventsMode2 == 'true' && end && end.toDateString() == date.toDateString()) return true; + // if (showEventsMode2 == 'true' && event.date.length == 1 && start.toDateString() == date.toDateString()) return true; + + return false; + }; +} + const Day = ({date, events}) => { const dayEvents = useDayEvents(events, date) const navigate = useNavigate(); const {year} = useParams(); const [searchParams] = useSearchParams(); + const search = Object.fromEntries(searchParams); let intensity = ''; let invisible = 'invisible'; @@ -13,7 +41,7 @@ const Day = ({date, events}) => { if (date) { if (dayEvents.length > 0) { intensity = ` intensity-${Math.min( - dayEvents.length, + dayEvents.filter(dayEventFilterFactory(search, date)).length, 7 )}`; } diff --git a/page/src/components/Filters/Filters.jsx b/page/src/components/Filters/Filters.jsx index dc7bba249..b9d9fb078 100644 --- a/page/src/components/Filters/Filters.jsx +++ b/page/src/components/Filters/Filters.jsx @@ -10,7 +10,6 @@ import { FilterContext } from 'contexts/FilterContext'; const Filters = () => { const context = useContext(FilterContext); - console.log(context) const [searchParams, setSearchParams] = useSearchParams(context.searchParams); const [open, setOpen] = useState(context.open); @@ -20,12 +19,17 @@ const Filters = () => { }, [searchParams, open]); const onChange = useCallback((key, value) => { - setSearchParams({...Object.fromEntries(searchParams), [key]: value}) + const clone = { ...Object.fromEntries(searchParams), [key]: value }; + if (value === undefined) delete clone[key]; + setSearchParams(clone); }, [searchParams, setSearchParams]); const countries = useCountries() - const search = Object.fromEntries(searchParams) + const search = Object.fromEntries(searchParams); + if (search.showEventsMode0 === undefined) { + + } return (
@@ -68,6 +72,24 @@ const Filters = () => {
+
+ Calendar Highlight + + {/* TODO: Make showEventsMode an array */} +
+ onChange('showEventsMode0', e.target.checked || false)}/> + +
+
+ onChange('showEventsMode1', e.target.checked || undefined)}/> + +
+
+ onChange('showEventsMode2', e.target.checked || undefined)}/> + +
+
+