From c0340c3407e514de55509a995e746641c6d05108 Mon Sep 17 00:00:00 2001 From: Antonio De Lucreziis Date: Mon, 12 Sep 2022 20:02:04 +0200 Subject: [PATCH] Schedule view --- src/components/EventsView.jsx | 3 ++ src/components/HamburgerMenu.jsx | 3 +- src/components/Toolbar.jsx | 3 +- src/components/view/Schedule.jsx | 54 ++++++++++++++++++++++ src/main.jsx | 4 +- src/styles/main.scss | 79 ++++++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/components/view/Schedule.jsx diff --git a/src/components/EventsView.jsx b/src/components/EventsView.jsx index 3f83371..9a83bbf 100644 --- a/src/components/EventsView.jsx +++ b/src/components/EventsView.jsx @@ -1,15 +1,18 @@ import { Course } from './view/Course.jsx' +import { Schedule } from './view/Schedule.jsx' import { WorkWeek } from './view/WorkWeek.jsx' import { WorkWeekTranspose } from './view/WorkWeekTranspose.jsx' export const MODE_COURSE = 'course' export const MODE_WORKWEEK = 'work-week' +export const MODE_SCHEDULE = 'schedule' export const MODE_WORKWEEK_TRANSPOSE = 'work-week-transpose' const viewModeMap = { [MODE_COURSE]: Course, [MODE_WORKWEEK]: WorkWeek, [MODE_WORKWEEK_TRANSPOSE]: WorkWeekTranspose, + [MODE_SCHEDULE]: Schedule, } export const EventsView = ({ mode, ...viewProps }) => { diff --git a/src/components/HamburgerMenu.jsx b/src/components/HamburgerMenu.jsx index 995794f..19ef2eb 100644 --- a/src/components/HamburgerMenu.jsx +++ b/src/components/HamburgerMenu.jsx @@ -1,5 +1,5 @@ import { ComboBox } from './ComboBox.jsx' -import { MODE_COURSE, MODE_WORKWEEK } from './EventsView.jsx' +import { MODE_COURSE, MODE_SCHEDULE, MODE_WORKWEEK } from './EventsView.jsx' import { Help } from './Help.jsx' import { Icon } from './Icon.jsx' @@ -41,6 +41,7 @@ export const HamburgerMenu = ({ onClose, mode, setMode, source, setSource, theme setValue={setMode} options={[ { value: MODE_COURSE, label: 'Corsi' }, + { value: MODE_SCHEDULE, label: 'Giornaliera' }, { value: MODE_WORKWEEK, label: 'Settimana' }, ]} /> diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx index bc9a181..25e8568 100644 --- a/src/components/Toolbar.jsx +++ b/src/components/Toolbar.jsx @@ -1,5 +1,5 @@ import { CompoundButton } from './CompoundButton.jsx' -import { MODE_COURSE, MODE_WORKWEEK } from './EventsView.jsx' +import { MODE_COURSE, MODE_SCHEDULE, MODE_WORKWEEK } from './EventsView.jsx' import { Icon } from './Icon.jsx' export const Toolbar = ({ @@ -43,6 +43,7 @@ export const Toolbar = ({ options={[ { value: MODE_COURSE, label: 'Corsi' }, { value: MODE_WORKWEEK, label: 'Settimana' }, + { value: MODE_SCHEDULE, label: 'Giorno' }, ]} value={mode} setValue={setMode} diff --git a/src/components/view/Schedule.jsx b/src/components/view/Schedule.jsx new file mode 100644 index 0000000..eb05f18 --- /dev/null +++ b/src/components/view/Schedule.jsx @@ -0,0 +1,54 @@ +import { format } from 'date-fns' +import _ from 'lodash' +import { normalizeCourseName, WEEK_DAYS, withClasses } from '../../utils.jsx' + +export const Schedule = ({ events, selection, setSelection, hideOtherCourses }) => { + const selectionSet = new Set(selection) + + const visibleEvents = !hideOtherCourses ? events : events.filter(e => selectionSet.has(e.id)) + + const eventsByWeekday = _.mapValues( + _.groupBy(visibleEvents, e => e.start.getDay()), + dailyEvents => _.groupBy(dailyEvents, e => e.start.getHours()) + ) + + return ( +
+ {Object.entries(eventsByWeekday).map(([index, dailyEvents]) => ( + <> +
+
{WEEK_DAYS[index]}
+
+ {Object.values(dailyEvents).map(events => ( + <> +
{format(events[0].start, 'H:mm')}
+ {events.map(event => ( +
{ + if (!selectionSet.has(event.id)) + setSelection([...selection, event.id]) + else + setSelection( + selection.filter(selId => selId !== event.id) + ) + }} + > +
{normalizeCourseName(event.name)}
+
+ {format(event.start, 'H:mm')} –{' '} + {format(event.end, 'H:mm')} +
+
{event.aula}
+
+ ))} + + ))} + + ))} +
+ ) +} diff --git a/src/main.jsx b/src/main.jsx index f4e0399..be40c47 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -3,7 +3,7 @@ import { render } from 'preact' import { useEffect, useState } from 'preact/hooks' import { ToolOverlay } from './components/CourseVisibility.jsx' -import { EventsView } from './components/EventsView.jsx' +import { EventsView, MODE_SCHEDULE } from './components/EventsView.jsx' import { HamburgerMenu } from './components/HamburgerMenu.jsx' import { Help } from './components/Help.jsx' import { Icon } from './components/Icon.jsx' @@ -73,7 +73,7 @@ const App = ({}) => { const [eventi, setEventi] = useState([]) // View Modes - const [mode, setMode] = useState('course') + const [mode, setMode] = useState(MODE_SCHEDULE) // Selection const [selectedCourses, setSelectedCourses] = useState([]) diff --git a/src/styles/main.scss b/src/styles/main.scss index 993cbcd..5ed4220 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -810,6 +810,85 @@ body { } } } + + .schedule-view { + padding: 1rem; + + display: flex; + flex-direction: column; + align-items: center; + + gap: 1rem; + + overflow-y: scroll; + + height: 100%; + + & > * { + max-width: 50rem; + } + + .header { + position: relative; + + width: 100%; + display: grid; + place-content: center; + + &.giorno { + font-size: 24px; + font-weight: 400; + + .inner { + background: var(--bg-500); + padding: 0 0.5rem; + } + + &::before { + position: absolute; + + content: ''; + top: 50%; + left: 0; + right: 0; + height: 1px; + background: var(--border-600); + + z-index: -1; + } + } + + &.orario { + font-size: 18px; + font-weight: 300; + } + } + + .event { + @extend .panel; + + width: 100%; + + .title { + font-size: 22px; + } + + position: relative; + + &.selected { + background: var(--bg-selected-500); + + &::after { + content: ''; + position: absolute; + inset: -1px; + border-radius: 1rem; + + border: 3px solid var(--border-selected-500); + } + } + } + } } .overlay {