Add date functions, add day headers in the schedule

This commit is contained in:
Vencislav Atanasov 2024-09-26 20:07:23 +03:00
parent cd6cce7d1e
commit 4e68064e02
4 changed files with 41 additions and 10 deletions

12
src/Schedule/Day.jsx Normal file
View File

@ -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,
};

View File

@ -8,6 +8,7 @@ import './Schedule.scss';
import { langs } from './constants.js'; import { langs } from './constants.js';
import Speaker from './Speaker.jsx'; import Speaker from './Speaker.jsx';
import FeedbackLink from './FeedbackLink.jsx'; import FeedbackLink from './FeedbackLink.jsx';
import Day from './Day.jsx';
export default function Schedule({ export default function Schedule({
conferenceId, conferenceId,
@ -55,7 +56,8 @@ export default function Schedule({
<tbody> <tbody>
{rows.map(row => <tr key={row.id}> {rows.map(row => <tr key={row.id}>
{row.cells.map(cell => <td key={cell.id} {...cell.attributes}> {row.cells.map(cell => <td key={cell.id} {...cell.attributes}>
<Event {...cell.event} /> {cell.day && <Day date={cell.day} />}
{cell.event && <Event {...cell.event} />}
</td>)} </td>)}
</tr>)} </tr>)}
</tbody> </tbody>

View File

@ -1,5 +1,5 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { sorter } from '../utils.js'; import { getMidnightTimestamp, isSameDay, sorter } from '../utils.js';
export default function useScheduleTable({ export default function useScheduleTable({
eventTypeId, eventTypeId,
@ -12,7 +12,7 @@ export default function useScheduleTable({
const filteredEventIds = filteredEvents.map(event => event.id); const filteredEventIds = filteredEvents.map(event => event.id);
const filteredSlots = slots.sort(sorter('starts_at')).filter(slot => filteredEventIds.includes(slot.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 => 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)); ))).map(ts => new Date(ts));
const filteredHallIds = new Set(filteredSlots.map(slot => slot.hall_id)); const filteredHallIds = new Set(filteredSlots.map(slot => slot.hall_id));
const filteredHalls = halls.filter(hall => filteredHallIds.has(hall.id)); const filteredHalls = halls.filter(hall => filteredHallIds.has(hall.id));
@ -25,17 +25,28 @@ export default function useScheduleTable({
void(hallSlots); void(hallSlots);
const header = filteredHalls; const header = filteredHalls;
const rows = filteredEvents.map(event => ({ const rows = days.flatMap(day => [{
id: event.id, id: 'header-'.concat(day.getTime().toString()),
cells: [{ cells: [{
id: 1, id: 1,
attributes: { attributes: {
className: 'schedule-'.concat(event.language).concat(' ').concat(event.track?.css_class), colSpan: header.length,
},
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, colSpan: 2,
}, },
event, event: slot.event,
}], }],
})); }))
]);
return { return {
header, header,

View File

@ -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);
}