Skip to content

Commit

Permalink
Improved next open time string
Browse files Browse the repository at this point in the history
  • Loading branch information
pookmish committed Jul 5, 2024
1 parent d25b05e commit fccb5c0
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import {ChevronDownIcon} from "@heroicons/react/20/solid"
import {Table, Thead, Tbody, Tr, Th, Td} from "react-super-responsive-table"
import "react-super-responsive-table/dist/SuperResponsiveTableStyle.css"
import {Maybe, NodeSulLibrary} from "@/lib/gql/__generated__/drupal"
import {useId} from "react"
import {useCallback, useId, useRef} from "react"
import Image from "next/image"
import Link from "next/link"
import Address from "@/components/patterns/elements/address"
import useLibraryHours, {DayHours, LocationHours} from "@/lib/hooks/useLibraryHours"
import {useBoolean} from "usehooks-ts"
import {useBoolean, useEventListener} from "usehooks-ts"
import useOutsideClick from "@/lib/hooks/useOutsideClick"
import useTodayLibraryHours from "@/lib/hooks/useTodayLibraryHours"

export type BranchLocation = {
id: NodeSulLibrary["id"]
Expand All @@ -36,6 +37,7 @@ const BranchLocationFilteringTable = ({items}: Props) => {
const filterLocations = () => {
const rightNow = new Date()
const openBranches: string[] = []

Object.keys(libraryHours).map(hourId => {
const todayHours = libraryHours[hourId].primaryHours.find(day => {
const dayDate = new Date(day.day + " 20:00:00").toLocaleDateString("en-us", {
Expand Down Expand Up @@ -192,76 +194,50 @@ const TableRow = ({id, imageUrl, path, title, phone, email, mapUrl, address, hou
}

const BranchHours = ({hoursId}: {hoursId: string}) => {
const containerRef = useRef<HTMLDivElement>(null)
const buttonRef = useRef<HTMLButtonElement>(null)
const {value: expandedHours, setFalse: collapseHours, toggle: toggleExpandedHours} = useBoolean(false)
const outsideClickProps = useOutsideClick(collapseHours)
const id = useId()
const libraryHours = useLibraryHours<LocationHours>(hoursId)
if (!libraryHours.primaryHours) {
return
}
const todayLibraryHours = useTodayLibraryHours(hoursId)

// To test out various scenarios adjust right now. Go back 20 hours:
// const rightNow = new Date(new Date().getTime() - 20 * 60 * 60 * 1000)
// Go forward 10 hours
// const rightNow = new Date(new Date().getTime() + 10 * 60 * 60 * 1000)
const rightNow = new Date()
// If the user presses escape on the keyboard, close the submenus.
const handleEscape = useCallback(
(event: KeyboardEvent) => {
if (event.key !== "Escape" || !expandedHours) return

const todayHours = libraryHours.primaryHours.find(day => {
// Set the time so that it works with UTC time.
const dayDate = new Date(day.day + " 20:00:00").toLocaleDateString("en-us", {weekday: "long", timeZone: "America/Los_Angeles"})
return dayDate === rightNow.toLocaleDateString("en-us", {weekday: "long", timeZone: "America/Los_Angeles"})
}) as DayHours
collapseHours()
buttonRef.current?.focus()
},
[collapseHours, expandedHours]
)

let openTime,
closeTime,
isOpen = false
useEventListener("keydown", handleEscape, containerRef)

if (!todayHours.closed && todayHours.opens_at && todayHours.closes_at) {
openTime = new Date(todayHours.opens_at)
closeTime = new Date(todayHours.closes_at)
isOpen = rightNow > openTime && rightNow < closeTime
if (!libraryHours.primaryHours || !todayLibraryHours) {
return
}

const closeTimeString =
isOpen &&
closeTime &&
closeTime.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/Los_Angeles",
})

const tomorrowHours = libraryHours.primaryHours.find(day => {
// Set the time so that it works with UTC time.
const dayDate = new Date(day.day + " 20:00:00").toLocaleDateString("en-us", {weekday: "long", timeZone: "America/Los_Angeles"})
return dayDate === new Date(rightNow.getTime() + 1000 * 60 * 60 * 24).toLocaleDateString("en-us", {weekday: "long", timeZone: "America/Los_Angeles"})
}) as DayHours

const openTimeString =
!isOpen &&
tomorrowHours?.opens_at &&
new Date(tomorrowHours.opens_at).toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/Los_Angeles",
})
const {isOpen, closingTime, nextOpeningTime} = todayLibraryHours

return (
<div
{...outsideClickProps}
ref={containerRef}
className="relative flex text-16 md:block"
>
{isOpen && <span className="m-auto mb-8 mr-8 block w-fit rounded-full bg-digital-green p-10 text-white sm:text-center md:m-0 md:text-left lg:mx-auto lg:text-center">Open</span>}

{!isOpen && <span className="m-auto mr-8 flex w-fit sm:text-center md:m-0 md:text-left lg:mx-auto lg:text-center">Closed</span>}

<div className="flex w-fit items-center whitespace-nowrap sm:text-center md:text-left lg:mx-auto lg:text-center">
{closeTimeString && <>Until {closeTimeString}</>}
{openTimeString && <>Until {openTimeString}</>}

{!closeTimeString && !openTimeString && "Hours this week"}
{isOpen && closingTime && `Until ${closingTime}`}
{!isOpen && nextOpeningTime && `Until ${nextOpeningTime}`}
{!closingTime && !nextOpeningTime && "Hours this week"}

<button
ref={buttonRef}
onClick={toggleExpandedHours}
aria-controls={id}
aria-expanded={expandedHours}
Expand Down
12 changes: 5 additions & 7 deletions src/lib/hooks/useLibraryHours.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ export type LocationHours = {
name: string
type: string
primaryHours: DayHours[]
additionalLocations: [
{
id: string
name: string
hours: DayHours[]
},
]
additionalLocations: {
id: string
name: string
hours: DayHours[]
}[]
}

const useLibraryHours = <T extends Record<string, LocationHours> | LocationHours>(branchId?: string): T => {
Expand Down
64 changes: 46 additions & 18 deletions src/lib/hooks/useTodayLibraryHours.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import useLibraryHours, {DayHours, LocationHours} from "@/lib/hooks/useLibraryHours";
import {getLibrarySelectOptions, HoursSelectOption} from "@/components/node/sul-library/library-select-options";
import useLibraryHours, {DayHours, LocationHours} from "@/lib/hooks/useLibraryHours"
import {getLibrarySelectOptions, HoursSelectOption} from "@/components/node/sul-library/library-select-options"

type HoursProps = {
closedAllDay: boolean
Expand All @@ -8,46 +8,74 @@ type HoursProps = {
closingTime?: string
afterClose: boolean
selectOptions: HoursSelectOption[]
nextOpeningTime?: string
}

const useTodayLibraryHours = (branchId?: string): HoursProps | undefined => {
const libraryHours = useLibraryHours(branchId) as LocationHours;
const libraryHours = useLibraryHours<LocationHours>(branchId)
if (!libraryHours || !libraryHours?.primaryHours) {
return;
return
}

const rightNow = new Date()

const todayHours = libraryHours.primaryHours.find(day => {
// Set the time so that it works with UTC time.
const dayDate = new Date(day.day + " 20:00:00").toLocaleDateString('en-us', {weekday: "long", timeZone: 'America/Los_Angeles'})
return dayDate === rightNow.toLocaleDateString('en-us', {weekday: "long", timeZone: 'America/Los_Angeles'})
}) as DayHours;
const dayDate = new Date(day.day + " 20:00:00").toLocaleDateString("en-us", {weekday: "long", timeZone: "America/Los_Angeles"})
return dayDate === rightNow.toLocaleDateString("en-us", {weekday: "long", timeZone: "America/Los_Angeles"})
}) as DayHours

let openTime, closeTime, isOpen = false, closedAllDay = todayHours?.closed;
let openTime,
closeTime,
isOpen = false,
closedAllDay = todayHours?.closed

if (!todayHours.closed && todayHours.opens_at && todayHours.closes_at) {
openTime = new Date(todayHours.opens_at);
closeTime = new Date(todayHours.closes_at);
isOpen = rightNow > openTime && rightNow < closeTime;
openTime = new Date(todayHours.opens_at)
closeTime = new Date(todayHours.closes_at)
isOpen = rightNow > openTime && rightNow < closeTime
}

const closingTime = closeTime?.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: 'America/Los_Angeles'
});
timeZone: "America/Los_Angeles",
})

const openingTime = openTime?.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: 'America/Los_Angeles'
});
timeZone: "America/Los_Angeles",
})

const selectOptions = getLibrarySelectOptions(libraryHours.primaryHours);
const selectOptions = getLibrarySelectOptions(libraryHours.primaryHours)

const afterClose = (closeTime && closeTime <= rightNow) || false
return {closedAllDay, isOpen, openingTime, closingTime, selectOptions, afterClose}
let nextOpeningTime = undefined

// If the location is open, no need to return the next open time.
if (!isOpen) {
const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
let dayHours
// Start with tomorrow and find the next day that has a time that is open.
for (let i = rightNow.getDay(); i < 7; i++) {
dayHours = libraryHours.primaryHours.find(day => day.weekday === weekdays[i])
if (dayHours?.opens_at) {
const format: Intl.DateTimeFormatOptions = {weekday: "short", hour: "numeric"}
const openDateTime = new Date(dayHours.opens_at)

if (openDateTime < rightNow) continue

if (openDateTime.getMinutes() !== 0) {
format.minute = "2-digit"
}
nextOpeningTime = openDateTime.toLocaleString("en-us", format)
i += 6
}
}
}

return {closedAllDay, isOpen, openingTime, closingTime, selectOptions, afterClose, nextOpeningTime}
}

export default useTodayLibraryHours;
export default useTodayLibraryHours

0 comments on commit fccb5c0

Please sign in to comment.