diff --git a/src/Schedule/Day.jsx b/src/Schedule/Day.jsx new file mode 100644 index 0000000..83e061e --- /dev/null +++ b/src/Schedule/Day.jsx @@ -0,0 +1,12 @@ +import PropTypes from 'prop-types'; + +export default function Day({ + date, +}) { + // TODO: format with date-fns + return date.getDate().toString().concat('.').concat((date.getMonth() + 1).toString()).concat(' - ').concat(date.getDay()); +} + +Day.propTypes = { + date: PropTypes.object.isRequired, +}; diff --git a/src/Schedule/Schedule.jsx b/src/Schedule/Schedule.jsx index 2cf1d82..674a663 100644 --- a/src/Schedule/Schedule.jsx +++ b/src/Schedule/Schedule.jsx @@ -8,6 +8,7 @@ import './Schedule.scss'; import { langs } from './constants.js'; import Speaker from './Speaker.jsx'; import FeedbackLink from './FeedbackLink.jsx'; +import Day from './Day.jsx'; export default function Schedule({ conferenceId, @@ -55,7 +56,8 @@ export default function Schedule({ {rows.map(row => {row.cells.map(cell => - + {cell.day && } + {cell.event && } )} )} diff --git a/src/hooks/useScheduleTable.js b/src/hooks/useScheduleTable.js index 07ac1a2..882eb69 100644 --- a/src/hooks/useScheduleTable.js +++ b/src/hooks/useScheduleTable.js @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { sorter } from '../utils.js'; +import { getMidnightTimestamp, isSameDay, sorter } from '../utils.js'; export default function useScheduleTable({ eventTypeId, @@ -12,7 +12,7 @@ export default function useScheduleTable({ const filteredEventIds = filteredEvents.map(event => event.id); const filteredSlots = slots.sort(sorter('starts_at')).filter(slot => filteredEventIds.includes(slot.event_id)); const days = Array.from(new Set(filteredSlots.map(slot => - slot.starts_at.setHours(0, 0, 0, 0) + getMidnightTimestamp(slot.starts_at) ))).map(ts => new Date(ts)); const filteredHallIds = new Set(filteredSlots.map(slot => slot.hall_id)); const filteredHalls = halls.filter(hall => filteredHallIds.has(hall.id)); @@ -25,17 +25,28 @@ export default function useScheduleTable({ void(hallSlots); const header = filteredHalls; - const rows = filteredEvents.map(event => ({ - id: event.id, + const rows = days.flatMap(day => [{ + id: 'header-'.concat(day.getTime().toString()), cells: [{ id: 1, attributes: { - className: 'schedule-'.concat(event.language).concat(' ').concat(event.track?.css_class), - colSpan: 2, + colSpan: header.length, }, - event, - }], - })); + day, + }] + }, + ...filteredSlots.filter(slot => isSameDay(slot.starts_at, day)).map(slot => ({ + id: slot.id, + cells: [{ + id: 1, + attributes: { + className: 'schedule-'.concat(slot.event.language).concat(' ').concat(slot.event.track?.css_class), + colSpan: 2, + }, + event: slot.event, + }], + })) + ]); return { header, diff --git a/src/utils.js b/src/utils.js index 2ce61b5..6f24027 100644 --- a/src/utils.js +++ b/src/utils.js @@ -61,3 +61,9 @@ export const normalizeResponse = (items = [], relations = []) => })), }) ); + +export const getMidnightTimestamp = date => (new Date(date.getTime())).setHours(0, 0, 0, 0); + +export function isSameDay(dateA, dateB) { + return getMidnightTimestamp(dateA) === getMidnightTimestamp(dateB); +}