Schedule view
This commit is contained in:
@@ -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 }) => {
|
||||
|
||||
@@ -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' },
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 (
|
||||
<div class="schedule-view">
|
||||
{Object.entries(eventsByWeekday).map(([index, dailyEvents]) => (
|
||||
<>
|
||||
<div class="header giorno">
|
||||
<div class="inner">{WEEK_DAYS[index]}</div>
|
||||
</div>
|
||||
{Object.values(dailyEvents).map(events => (
|
||||
<>
|
||||
<div class="header orario">{format(events[0].start, 'H:mm')}</div>
|
||||
{events.map(event => (
|
||||
<div
|
||||
class={withClasses([
|
||||
'event',
|
||||
selectionSet.has(event.id) && 'selected',
|
||||
])}
|
||||
onClick={() => {
|
||||
if (!selectionSet.has(event.id))
|
||||
setSelection([...selection, event.id])
|
||||
else
|
||||
setSelection(
|
||||
selection.filter(selId => selId !== event.id)
|
||||
)
|
||||
}}
|
||||
>
|
||||
<div class="title">{normalizeCourseName(event.name)}</div>
|
||||
<div class="orario">
|
||||
{format(event.start, 'H:mm')} –{' '}
|
||||
{format(event.end, 'H:mm')}
|
||||
</div>
|
||||
<div class="aula">{event.aula}</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+2
-2
@@ -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([])
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user