Skip to content

Commit

Permalink
Merge pull request #147 from wearefuturegov/TOP-203-expand-regular-sc…
Browse files Browse the repository at this point in the history
…hedule-options-to-include-more-fields

Top 203 expand regular schedule options to include more fields
  • Loading branch information
apricot13 authored Sep 5, 2024
2 parents bb7dbd5 + f79df86 commit 029a405
Show file tree
Hide file tree
Showing 10 changed files with 498 additions and 112 deletions.
24 changes: 24 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Filter from "./components/Filter"
import RadioFilter from "./components/Filter/RadioFilter"
import KeywordFilter from "./components/Filter/KeywordFilter"
import AgeFilter from "./components/Filter/AgeFilter"
import StarttimeEndtimeDayFilter from "./components/Filter/StarttimeEndtimeDay"
import ListMap from "./components/ListMap"
import ListMapStatic from "./components/ListMapStatic"
import Pagination from "./components/Pagination"
Expand Down Expand Up @@ -69,6 +70,9 @@ const App = ({ children, location, navigate }) => {
array: true,
})
const [days, setDays] = useQuery("days", [], { array: true })
const [startTime, setStartTime] = useQuery("start_time", [], { array: true })
const [endTime, setEndTime] = useQuery("end_time", [], { array: true })
const [day, setDay] = useQuery("day", [], { array: true })
const [minAge, setMinAge] = useQuery("min_age", false, { numerical: true })
const [maxAge, setMaxAge] = useQuery("max_age", false, { numerical: true })
const [only, setOnly] = useQuery("only", [], { array: true })
Expand Down Expand Up @@ -284,6 +288,21 @@ const App = ({ children, location, navigate }) => {
/>
)

const filterStarttimeEndTimeDay = daysOptions.length > 0 && (
<StarttimeEndtimeDayFilter
key="opening-times"
legend="Availability"
startTime={startTime}
endTime={endTime}
day={day}
setStartTime={setStartTime}
setEndTime={setEndTime}
setDay={setDay}
setPage={setPage}
foldable
/>
)

const filterSuitabilities = suitabilityOptions.length > 0 && (
<Filter
key="suitabilities"
Expand Down Expand Up @@ -322,6 +341,11 @@ const App = ({ children, location, navigate }) => {
clear: [setDays],
clearValue: [[]],
},
startTimeEndTimeDay: {
component: filterStarttimeEndTimeDay,
clear: [setStartTime, setEndTime, setDay],
clearValue: [[], [], []],
},
suitabilities: {
component: filterSuitabilities,
clear: [setSuitabilities],
Expand Down
114 changes: 93 additions & 21 deletions src/components/DetailDialog/ScheduleTable.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,102 @@
import React from "react"
import styled from "styled-components"
import { Crosshead, CrossheadSub, Columns, Table } from "./DetailDialog.styles"
import { twelveHourTime } from "../../lib/utils"

export const EventList = styled.div`
margin-bottom: 30px;
&:last-of-type {
margin-bottom: 0px;
}
div {
margin-bottom: 20px;
&:last-of-type {
margin-bottom: 0px;
}
}
/* @supports (display: grid) {
@media screen and (min-width: ${props => props.theme.styles.breakpointM}) {
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 35px;
row-gap: 25px;
div {
margin-bottom: 0px;
}
}
} */
`

export const List = styled.ul`
padding-left: 30px;
`

export const ListItem = styled.li`
position: relative;
line-height: 1.5;
padding-left: 15px;
margin-bottom: 10px;
&:last-of-type {
margin-bottom: 0px;
}
`

const ScheduleTable = ({ title, subtitle, regular_schedules }) => {
const { event_times, opening_times } = regular_schedules.reduce(
(acc, sched) => {
if (sched.dtstart) {
acc.event_times.push(sched)
} else {
acc.opening_times.push(sched)
}
return acc
},
{ event_times: [], opening_times: [] }
)

const OpeningTimes = () => (
<Table>
<tbody>
{opening_times.map((sched, i) => (
<tr key={i}>
<td>
<strong>{sched.weekday}s</strong>
</td>
<td>
{twelveHourTime(sched.opens_at)} to{" "}
{twelveHourTime(sched.closes_at)}
</td>
</tr>
))}
</tbody>
</Table>
)

const EventTimes = () => (
<List>
{event_times.map((sched, i) => (
<ListItem>{sched.description}</ListItem>
))}
</List>
)

return (
regular_schedules.length > 0 && (
<Columns>
{title && <Crosshead>{title}</Crosshead>}
{subtitle && <CrossheadSub>{subtitle}</CrossheadSub>}
<Table>
<tbody>
{regular_schedules.map((sched, i) => (
<tr key={i}>
<td>
<strong>{sched.weekday}s</strong>
</td>
<td>
{twelveHourTime(sched.opens_at)} to{" "}
{twelveHourTime(sched.closes_at)}
</td>
</tr>
))}
</tbody>
</Table>
</Columns>
)
<>
{opening_times.length > 0 && (
<Columns>
{title && <Crosshead>{title}</Crosshead>}
{subtitle && <CrossheadSub>{subtitle}</CrossheadSub>}
<OpeningTimes />
</Columns>
)}
{event_times.length > 0 && (
<EventList>
{title && <Crosshead>{title}</Crosshead>}
{subtitle && <CrossheadSub>{subtitle}</CrossheadSub>}
<EventTimes />
</EventList>
)}
</>
)
}

Expand Down
103 changes: 83 additions & 20 deletions src/components/DetailDialog/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,43 @@ const DetailDialog = ({ serviceId, location, navigate }) => {
if (service.name) {
let goodToKnow = buildGoodToKnow(service)
let categories = service.taxonomies

const all_location_regular_schedules = service.regular_schedules.filter(
v => v.service_at_location === null
)

const {
all_location_event_times,
all_location_opening_times,
} = all_location_regular_schedules.reduce(
(acc, sched) => {
if (sched.dtstart) {
acc.all_location_event_times.push(sched)
} else {
acc.all_location_opening_times.push(sched)
}
return acc
},
{ all_location_event_times: [], all_location_opening_times: [] }
)

const location_regular_schedules = service.service_at_locations.reduce(
(acc, schedule) => {
if (schedule.regular_schedule && schedule.regular_schedule.length > 0) {
const locationId = schedule.location_id
if (!acc[locationId]) {
acc[locationId] = {
location: schedule.location,
regular_schedules: [],
}
}
acc[locationId].regular_schedules.push(...schedule.regular_schedule)
}
return acc
},
{}
)

return (
<Dialog handleDismiss={handleDismiss} dialogTitle={service.name}>
<Helmet>
Expand Down Expand Up @@ -321,32 +358,58 @@ const DetailDialog = ({ serviceId, location, navigate }) => {
</TickList>
</Columns>
)}
{/* 4 options
just opening hours
just event times
event times and opening hours
{service.regular_schedules.length > 0 && (
all at location */}
{/* opening times for all locations and locations */}
{all_location_opening_times.length > 0 && (
<ScheduleTable
title="Hours"
regular_schedules={service.regular_schedules.filter(
v => v.service_at_location === null
)}
regular_schedules={all_location_opening_times}
/>
)}

{service.service_at_locations.length > 1 && (
<>
{service.service_at_locations.map((service_at_location, i) => (
<ScheduleTable
key={service_at_location.id}
subtitle={
service_at_location.location.name ||
service_at_location.location.address_1 ||
`Location ${i + 1}`
}
regular_schedules={service_at_location.regular_schedule}
/>
))}
</>
{Object.entries(location_regular_schedules).map(
([location_id, location]) => (
<ScheduleTable
key={location_id}
subtitle={
location.name ||
location.address_1 ||
`Location ${location_id}`
}
regular_schedules={location.regular_schedules.filter(
v => v.dtstart === null
)}
/>
)
)}
{/* event times for all locations and locations */}
{all_location_event_times.length > 0 && (
<ScheduleTable
title="Times"
regular_schedules={all_location_event_times}
/>
)}{" "}
{Object.entries(location_regular_schedules).map(
([location_id, location]) => (
<ScheduleTable
key={location_id}
subtitle={
location.name ||
location.address_1 ||
`Location ${location_id}`
}
regular_schedules={location.regular_schedules.filter(
v => v.dtstart !== null
)}
/>
)
)}

{service.cost_options.length > 0 && (
<Columns>
<Crosshead>Fees</Crosshead>
Expand Down
47 changes: 5 additions & 42 deletions src/components/Filter/RadioFilter.jsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,14 @@
import React from "react"
import styled from "styled-components"

import { Outer, Label, Field } from "./layout"

const Input = styled.input`
position: absolute;
left: 0px;
top: 0px;
width: 29px;
border-radius: 100%;
height: 29px;
opacity: 0;
&:checked + label:after {
position: absolute;
content: "";
display: block;
border-radius: 100%;
background: ${props => props.theme.styles.text};
height: 19px;
width: 19px;
left: 5px;
top: 5px;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
`
import { Outer, RadioLabel, RadioField, InputRadio } from "./layout"

export const Content = styled.div`
padding: 25px 0px;
border-top: 1px solid ${props => props.theme.styles.cardShadow};
border-bottom: 1px solid ${props => props.theme.styles.cardShadow};
`

export const StyledField = styled(Field)`
&:focus-within label:before {
outline: none;
box-shadow: 0px 0px 0px 3px ${props => props.theme.styles.focus};
}
`

export const StyledLabel = styled(Label)`
&:before {
border-radius: 100%;
}
`

const RadioFilter = ({
name,
options,
Expand All @@ -66,17 +29,17 @@ const RadioFilter = ({
<Outer>
<Content>
{options.map((o, i) => (
<StyledField key={`${o.slug}_${i}`}>
<Input
<RadioField key={`${o.slug}_${i}`}>
<InputRadio
type="radio"
id={o.slug}
name={name}
value={o.slug}
onChange={handleChange}
checked={selection === o.slug}
/>
<StyledLabel htmlFor={o.slug}>{o.label}</StyledLabel>
</StyledField>
<RadioLabel htmlFor={o.slug}>{o.label}</RadioLabel>
</RadioField>
))}
</Content>
</Outer>
Expand Down
Loading

0 comments on commit 029a405

Please sign in to comment.