Minimal working prototype, no mobile, no printing

This commit is contained in:
2022-09-08 18:57:48 +02:00
parent 5d4c303b4a
commit c42ccc58dc
9 changed files with 415 additions and 57 deletions
+25
View File
@@ -0,0 +1,25 @@
// import { createContext } from 'preact'
// import { toChildArray } from 'preact'
// import { useContext, useState } from 'preact/hooks'
// const AnimationContext = createContext()
// export const useAnimation = animation => {
// const [styles, setStyles] = useState({})
// const start = () => {
// setStyles({ animation })
// }
// return [
// start,
// {
// styles,
// onAnimationEnd: e => {
// console.log('animation end')
// },
// },
// ]
// }
// export const Animation = ({ animation, children }) => {}
+19
View File
@@ -0,0 +1,19 @@
import { useRef } from 'preact/hooks'
import { Icon } from './Icon.jsx'
export const ComboBox = ({ selected, options }) => {
const selectRef = useRef()
return (
<div class="input-combo" onClick={() => selectRef.current?.click()}>
<select ref={selectRef}>
{options.map(({ label, value }) => (
<option value={value} selected={value === selected}>
{label}
</option>
))}
</select>
<Icon name="expand_more" />
</div>
)
}
+1 -1
View File
@@ -3,7 +3,7 @@ import { Icon } from './Icon.jsx'
export const ToolOverlay = ({ visibility, toggleVisibility, onClose }) => (
<div class="overlay">
<button class="icon primary" onClick={toggleVisibility}>
<Icon name={visibility ? 'visibility' : 'visibility_off'} />
<Icon name={visibility ? 'visibility_off' : 'visibility'} />
</button>
<button class="icon" onClick={onClose}>
<Icon name="close" />
+28 -19
View File
@@ -2,7 +2,7 @@
// Modes
//
import { differenceInMinutes, format, getWeek, startOfDay } from 'date-fns'
import { differenceInMinutes, format, startOfDay } from 'date-fns'
import { it } from 'date-fns/locale'
import _ from 'lodash'
@@ -22,6 +22,23 @@ function hashString(str, seed = 0) {
return 4294967296 * (2097151 & h2) + (h1 >>> 0)
}
function normalizeCourseName(name) {
return name
.split(' ')
.map(word => word.toLowerCase())
.map(word => {
if (word.trim().length === 0) return word
return /(^del|^nel|^di$|^dei$|^con$|^alla$|^per$|^e$|^la$)/.test(word)
? word
: word[0].toUpperCase() + word.slice(1)
})
.join(' ')
.replaceAll('Ii', 'II')
.replaceAll('Iii', 'III')
.replaceAll(/'(.)/g, ({}, letter) => "'" + letter.toUpperCase())
}
const WorkWeekView = ({ events }) => {
const eventsByWeekday = _.groupBy(events, event => event.start.getDay())
@@ -105,10 +122,7 @@ const WorkWeekView = ({ events }) => {
}}
ref={eventRef}
>
{_.startCase(_.lowerCase(event.data.name))
.replaceAll('Ii', 'II')
.replaceAll('Iii', 'III')
.replaceAll(/\bE\b/g, 'e')}
{normalizeCourseName(event.data.name)}
</div>
)
}
@@ -159,9 +173,11 @@ const WorkWeekVerticalView = ({ events, selection, setSelection, hideOtherCourse
}
element.current.addEventListener('mousemove', l)
element.current.addEventListener('mouseleave', l)
return () => {
element.current.removeEventListener('mousemove', l)
element.current.removeEventListener('mouseleave', l)
}
}
}, [element.current])
@@ -246,10 +262,7 @@ const WorkWeekVerticalView = ({ events, selection, setSelection, hideOtherCourse
}}
>
<div class="title">
{_.startCase(_.lowerCase(event.data.name))
.replaceAll('Ii', 'II')
.replaceAll('Iii', 'III')
.replaceAll(/\bE\b/g, 'e')}
{normalizeCourseName(event.data.name)}
</div>
<div class="aula">{event.data.aula}</div>
</div>
@@ -274,10 +287,9 @@ const WorkWeekVerticalView = ({ events, selection, setSelection, hideOtherCourse
const CourseView = ({ events, selection, setSelection, hideOtherCourses }) => {
const selectionSet = new Set(selection)
const eventsByCourse = _.groupBy(
!hideOtherCourses ? events : events.filter(e => selectionSet.has(e.name)),
'name'
)
const visibleEvents = !hideOtherCourses ? events : events.filter(e => selectionSet.has(e.name))
const eventsByCourse = _.groupBy(_.sortBy(visibleEvents, 'name'), 'name')
const [currentlyHovered, setCurrentlyHovered] = useState(null)
const element = useRef()
@@ -294,9 +306,11 @@ const CourseView = ({ events, selection, setSelection, hideOtherCourses }) => {
}
element.current.addEventListener('mousemove', l)
element.current.addEventListener('mouseleave', l)
return () => {
element.current.removeEventListener('mousemove', l)
element.current.removeEventListener('mouseleave', l)
}
}
}, [element.current])
@@ -317,12 +331,7 @@ const CourseView = ({ events, selection, setSelection, hideOtherCourses }) => {
else setSelection(selection.filter(n => n !== name))
}}
>
<div class="title">
{_.startCase(_.lowerCase(name))
.replaceAll('Ii', 'II')
.replaceAll('Iii', 'III')
.replaceAll(/\bE\b/g, 'e')}
</div>
<div class="title">{normalizeCourseName(name)}</div>
<div class="docenti">{courseEvents[0].docenti.join(', ')}</div>
<div class="events">
{courseEvents.map(course => (
+25
View File
@@ -0,0 +1,25 @@
import { ComboBox } from './ComboBox.jsx'
import { Icon } from './Icon.jsx'
export const HamburgerMenu = ({ onClose }) => {
return (
<div class="menu">
<div class="header">
<button class="flat icon" onClick={onClose}>
<Icon name="close" />
</button>
<div class="item logo">PHC / Orari</div>
</div>
<div class="options">
<ComboBox
selected={1}
options={[
{ label: 'Prova 1', value: 1 },
{ label: 'Prova 2', value: 2 },
{ label: 'Prova 3', value: 3 },
]}
/>
</div>
</div>
)
}
+44 -2
View File
@@ -1,10 +1,50 @@
import { Icon } from './Icon.jsx'
export const Toolbar = ({ mode, setMode }) => {
export const Toolbar = ({ mode, setMode, source, setSource, onShowMenu }) => {
return (
<div class="toolbar">
<div class="mobile">
<button class="flat icon" onClick={onShowMenu}>
<Icon name="menu" />
</button>
</div>
<div class="item logo">PHC / Orari</div>
<div class="options">
<div class="option-group">
<div class="item option">
<div class="compound">
<button
class={'radio' + (source === 'anno-1' ? ' selected' : '')}
onClick={() => setSource('anno-1')}
>
I
</button>
<button
class={'radio' + (source === 'anno-2' ? ' selected' : '')}
onClick={() => setSource('anno-2')}
>
II
</button>
<button
class={'radio' + (source === 'anno-3' ? ' selected' : '')}
onClick={() => setSource('anno-3')}
>
III
</button>
<button
class={'radio' + (source === 'magistrale' ? ' selected' : '')}
onClick={() => setSource('magistrale')}
>
Magistrale
</button>
{/* TODO: Aggiungere il pulsante per "tutti" */}
{/* <button
class={'radio' + (source === 'tutti' ? ' selected' : '')}
onClick={() => setSource('tutti')}
>
Tutti
</button> */}
</div>
</div>
<div class="item option">
<div class="compound">
<button
@@ -27,6 +67,8 @@ export const Toolbar = ({ mode, setMode }) => {
</button>
</div>
</div>
</div>
<div class="option-group">
<div class="item option">
<button class="icon">
<Icon name="print" />