From a53a3833eb0b948094e77895afa673b84a941c29 Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Mon, 12 Jun 2023 19:43:12 -0700 Subject: [PATCH 1/4] fix: Solve timezones for app slots bug back-end Day.toInterval needed to be supplied UTC timezone to allow for event times to properly overlap --- lib/availability/getPotentialTimes.ts | 4 ++-- pages/index.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/availability/getPotentialTimes.ts b/lib/availability/getPotentialTimes.ts index 6a4c846..9bf454a 100644 --- a/lib/availability/getPotentialTimes.ts +++ b/lib/availability/getPotentialTimes.ts @@ -23,8 +23,8 @@ export default function getPotentialTimes({ // Sort the slots by start time const days = eachDayOfInterval({ - start: start.toInterval().start, - end: end.toInterval().end, + start: start.toInterval("Etc/GMT").start, + end: end.toInterval("Etc/GMT").end, }) days.forEach((day) => { const dayOfWeek = day.getDay() diff --git a/pages/index.tsx b/pages/index.tsx index f3205a4..84c9268 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -52,8 +52,8 @@ function Page({ const slots = offers.filter((slot) => { return ( - slot.start >= startDay.toInterval().start && - slot.end <= endDay.toInterval().end + slot.start >= startDay.toInterval("Etc/GMT").start && + slot.end <= endDay.toInterval("Etc/GMT").end ) }) From 0d404274b75f6562e59dd0bbfc19bcc3576ce078 Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Mon, 12 Jun 2023 17:05:20 -0700 Subject: [PATCH 2/4] fix: fix useEffect bug for first avail suggestion Bug in pages/index.ts useEffect points user to first available appointment time, but only sometimes suggests the next day due to timezone issues. This commit fixes that by converting the date of the first appointment start time `slots[0].start` to the user's local timezone, then back to a date string for the Day class. --- lib/locale.ts | 16 ++++++++++++++++ pages/index.tsx | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 lib/locale.ts diff --git a/lib/locale.ts b/lib/locale.ts new file mode 100644 index 0000000..5ecfcad --- /dev/null +++ b/lib/locale.ts @@ -0,0 +1,16 @@ +/** + * Returns a string representation of the Date object + * in 'YYYY-MM-DD' format, respecting the user's timezone. + * + * @returns {string} The formatted date string. + */ +export default function localeDayString(date: Date): string { + const dateOptions: Intl.DateTimeFormatOptions = { + year: 'numeric', + month: '2-digit', + day: '2-digit', + timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone + }; + const dateString: string = date.toLocaleString('en-ca', dateOptions).replace(/\//g, '-'); + return dateString +} diff --git a/pages/index.tsx b/pages/index.tsx index 84c9268..b7ef9b7 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -22,6 +22,7 @@ import { mapStringsToDates, } from "@/lib/availability/helpers" import Day from "@/lib/day" +import localeDayString from "@/lib/locale" export type PageProps = InferGetServerSidePropsType @@ -61,9 +62,12 @@ function Page({ // with some availability. useEffect(() => { if (!selectedDate && slots.length > 0) { + const date: Date = slots[0].start; + const dateString: string = localeDayString(date) + dispatch({ type: "SET_SELECTED_DATE", - payload: Day.dayFromDate(slots[0].start), + payload: Day.dayFromString(dateString), //payload from date respecting timezone }) } // Run once, on initial render. From cefdd1a3d6ec3b5d02954b961646ae9f46fbdf5a Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Wed, 14 Jun 2023 18:48:16 -0700 Subject: [PATCH 3/4] fix: DayButton isDisabled boolean correction * Remove IsOutOfRange * Base isDisabled on whether or not offers[date] has a length greater than 0 --- components/availability/date/Calendar.tsx | 2 ++ components/availability/date/DayButton.tsx | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/availability/date/Calendar.tsx b/components/availability/date/Calendar.tsx index 5036c55..870a3db 100644 --- a/components/availability/date/Calendar.tsx +++ b/components/availability/date/Calendar.tsx @@ -64,6 +64,7 @@ export default function Calendar({ ))} {days.map((day) => { + const availabilityTest = offers[day.toString()] ?? [] return ( 0} /> ) })} diff --git a/components/availability/date/DayButton.tsx b/components/availability/date/DayButton.tsx index 2c892b2..4f4fc67 100644 --- a/components/availability/date/DayButton.tsx +++ b/components/availability/date/DayButton.tsx @@ -8,6 +8,7 @@ import Day from "@/lib/day" type DayProps = { date: Day availabilityScore: number + hasAvailability: boolean } & DetailedHTMLProps< ButtonHTMLAttributes, HTMLButtonElement @@ -16,6 +17,7 @@ type DayProps = { export default function DayButton({ date, availabilityScore, + hasAvailability, ...props }: DayProps): JSX.Element { const { @@ -29,13 +31,11 @@ export default function DayButton({ const isToday = date.toString() === now.toString() - const isOutOfRange = date < now || date > end || date < start - const isSelected = selectedDate ? date.toString() === selectedDate.toString() : false - const isDisabled = isOutOfRange || availabilityScore === 0 + const isDisabled = !hasAvailability return (