Merge pull request 'Fixed iOS date picker bug' (#14) from dev into main

Reviewed-on: #14
main
Antonio De Lucreziis 9 months ago
commit 65b800806f

@ -0,0 +1,9 @@
{
"printWidth": 90,
"singleQuote": true,
"quoteProps": "consistent",
"tabWidth": 4,
"semi": false,
"arrowParens": "avoid",
"proseWrap": "always"
}

@ -1,12 +1,19 @@
import { useRef } from 'preact/hooks'
import { Icon } from './Icon.jsx'
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
export const DatePicker = ({ date, setDate }) => {
const input = useRef()
const [year, month, day] = date.split('T')[0].split('-')
return (
<div class="date-picker" onClick={() => input.current.showPicker()}>
<div
class="date-picker"
onClick={() =>
isSafari ? input.current.focus() : input.current.showPicker()
}
>
<input
ref={input}
type="date"

@ -24,7 +24,6 @@ const viewModeMap = {
export const EventsView = ({ mode, source, ...viewProps }) => {
// const Mode = viewModeMap[mode]
if (source === 'orario') {
return (

@ -4,33 +4,31 @@ export const Help = ({}) => (
<>
<h3>Visualizzazione Corsi</h3>
<p>
Per visualizzare i corsi che ti interessano nella tabella
dell'orario, devi prima selezionarli. Puoi selezionare dei corsi
cliccandoli, cercandoli nelle sezioni Primo anno (<b>I</b>), Secondo
anno (<b>II</b>), Terzo anno (<b>III</b>), Magistrale (<b>M</b>), o
Tutti.
Per visualizzare i corsi che ti interessano nella tabella dell'orario, devi
prima selezionarli. Puoi selezionare dei corsi cliccandoli, cercandoli nelle
sezioni Primo anno (<b>I</b>), Secondo anno (<b>II</b>), Terzo anno (
<b>III</b>), Magistrale (<b>M</b>), o Tutti.
</p>
<p>
Una volta compiuta la selezione, è possibile vedere la tabella delle
lezioni andando nella visualizzazione Orario (
Una volta compiuta la selezione, è possibile vedere la tabella delle lezioni
andando nella visualizzazione Orario (
<Icon name="calendar_view_month" />)
</p>
<p>
Per via di eventuali preferenze personali, è possibile cambiare
l'orientazione della tabella Orario trasponendola, utilizzando il
pulsante Trasponi (
Per via di eventuali preferenze personali, è possibile cambiare l'orientazione
della tabella Orario trasponendola, utilizzando il pulsante Trasponi (
<Icon name="switch_left" style="transform: rotate(-45deg)" />)
</p>
<p>
È anche possibile visualizzare in uno specchietto riassuntivo
soltanto i corsi selezionati, andando nella visualizzazione Lista (
È anche possibile visualizzare in uno specchietto riassuntivo soltanto i corsi
selezionati, andando nella visualizzazione Lista (
<Icon name="list" />)
</p>
<h3>Stampa</h3>
<p>
Da desktop puoi stampare l'orario attualmente visibile con il
bottone <Icon name="print" /> (è consigliato controllare le opzioni
di stampa per ottenere un risultato soddisfacente).
Da desktop puoi stampare l'orario attualmente visibile con il bottone{' '}
<Icon name="print" /> (è consigliato controllare le opzioni di stampa per
ottenere un risultato soddisfacente).
</p>
<h3>Bug &amp; Contatti</h3>
<p>

@ -7,13 +7,9 @@ export const SettingsBar = ({ theme, setTheme, date, setDate }) => {
<div class="settings-group">
<button
class="icon"
onClick={() =>
setTheme(theme === 'dark' ? 'light' : 'dark')
}
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
<Icon
name={theme === 'dark' ? 'dark_mode' : 'light_mode'}
/>
<Icon name={theme === 'dark' ? 'dark_mode' : 'light_mode'} />
</button>
<DatePicker date={date} setDate={setDate} />
</div>

@ -24,8 +24,7 @@ export const Toolbar = ({
</button>
</div>
<div class="item logo">
<img src="logo-circuit-board.svg" alt="logo" /> /{' '}
<span>Orario</span>
<img src="logo-circuit-board.svg" alt="logo" /> / <span>Orario</span>
</div>
<div class="option-group">
<div class="item option">
@ -64,13 +63,9 @@ export const Toolbar = ({
<div class="item option">
<button
class="icon"
onClick={() =>
setTheme(theme === 'dark' ? 'light' : 'dark')
}
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
<Icon
name={theme === 'dark' ? 'dark_mode' : 'light_mode'}
/>
<Icon name={theme === 'dark' ? 'dark_mode' : 'light_mode'} />
</button>
</div>
<div class="item option">

@ -72,27 +72,18 @@ export const Courses = ({
}
data-course-id={id}
onClick={() => {
if (!selectionSet.has(id))
setSelection([...selection, id])
else
setSelection(
selection.filter(selId => selId !== id)
)
if (!selectionSet.has(id)) setSelection([...selection, id])
else setSelection(selection.filter(selId => selId !== id))
}}
>
<div class="title">
{prettyCourseName(courseEvents[0].name)}
</div>
<div class="docenti">
{profsPerCourse[id].join(', ')}
</div>
<div class="title">{prettyCourseName(courseEvents[0].name)}</div>
<div class="docenti">{profsPerCourse[id].join(', ')}</div>
<div class="events">
{courseEvents.map(course => (
<div>
{WEEK_DAYS[course.start.getDay()]}{' '}
{format(course.start, 'H:mm')}&ndash;
{format(course.end, 'H:mm')}{' '}
{course.aule.join(', ')}
{format(course.end, 'H:mm')} {course.aule.join(', ')}
</div>
))}
</div>

@ -3,11 +3,7 @@ import { useEffect, useRef, useState } from 'preact/hooks'
import _ from 'lodash'
import { differenceInMinutes, startOfDay } from 'date-fns'
import {
WEEK_DAYS_SHORT,
prettyCourseName,
usePersistentState,
} from '../../utils.jsx'
import { WEEK_DAYS_SHORT, prettyCourseName, usePersistentState } from '../../utils.jsx'
import { layoutEvents, layoutIntervals } from '../../interval-layout.js'
import { Popup } from '../Popup.jsx'
import { Icon } from '../Icon.jsx'
@ -17,28 +13,23 @@ const TransposePopup = ({ onClose }) => {
<Popup
title={
<>
<Icon name="info" /> Attenzione! La tabella è stata
trasposta!
<Icon name="info" /> Attenzione! La tabella è stata trasposta!
</>
}
onClose={onClose}
>
<p>
A grande richiesta popolare abbiamo trasposto la tabella
dell'orario!
</p>
<p>A grande richiesta popolare abbiamo trasposto la tabella dell'orario!</p>
<p>
Assicurati quindi di leggerla correttamente (dall'alto verso il
basso invece che da sinistra verso destra).
Assicurati quindi di leggerla correttamente (dall'alto verso il basso
invece che da sinistra verso destra).
</p>
<p>
Se preferisci utilizzare la versione vecchia, puoi utilizzare il
pulsante Trasponi{' '}
<Icon name="switch_left" style="transform: rotate(-45deg)" />{' '}
nell'origine della tabella per trasporla. Questa scelta verrà
salvata nei cookie e verrà ricordata in futuro
Se preferisci utilizzare la versione vecchia, puoi utilizzare il pulsante
Trasponi <Icon name="switch_left" style="transform: rotate(-45deg)" />{' '}
nell'origine della tabella per trasporla. Questa scelta verrà salvata nei
cookie e verrà ricordata in futuro
</p>
</Popup>
)
@ -49,8 +40,8 @@ const NoCourseWarning = () => {
<div class="warning">
<p>Non hai ancora selezionato nessun corso.</p>
<p>
Clicca sui corsi nelle altre visuali per selezionarli e
visualizzarli nell'orario
Clicca sui corsi nelle altre visuali per selezionarli e visualizzarli
nell'orario
</p>
</div>
)
@ -75,13 +66,10 @@ const Layout = ({ layout, day, colors }) => {
style={{
'--block-size': block.end - block.start,
'--size': event.end - event.start,
'--relative-start':
event.start - block.start,
'--relative-start': event.start - block.start,
'--index': event.index,
'--of': block.layers,
'--color': `var(--event-${
colors[event.id]
})`,
'--color': `var(--event-${colors[event.id]})`,
}}
>
<div class="event">
@ -118,16 +106,11 @@ const ScheduleGrid = ({
class="small"
onClick={() =>
setOrientation(
orientation === 'original'
? 'transposed'
: 'original'
orientation === 'original' ? 'transposed' : 'original'
)
}
>
<Icon
name="switch_left"
style="transform: rotate(-45deg)"
/>
<Icon name="switch_left" style="transform: rotate(-45deg)" />
</button>
</div>
{[1, 2, 3, 4, 5].map(n => (
@ -215,20 +198,9 @@ export const Schedule = ({ timetables, selection }) => {
'transpose_info',
'false'
)
const [orientation, setOrientation] = usePersistentState(
'orientation',
'original'
)
const [orientation, setOrientation] = usePersistentState('orientation', 'original')
const colorList = [
'red',
'purple',
'blue',
'yellow',
'green',
'orange',
'lightblue',
]
const colorList = ['red', 'purple', 'blue', 'yellow', 'green', 'orange', 'lightblue']
const allEvents = timetables['tutti']
const selectionSet = new Set(selection)

@ -42,10 +42,7 @@ function layoutBlockEvents(events) {
let viableIndex = 0
while (
result.filter(
e =>
e.index === viableIndex &&
e.start < event.end &&
event.start < e.end
e => e.index === viableIndex && e.start < event.end && event.start < e.end
).length !== 0
) {
viableIndex += 1
@ -57,8 +54,7 @@ function layoutBlockEvents(events) {
return result
}
export function layoutEvents(events) {
const overlap = (event, block) =>
event.start < block.end && block.start < event.end
const overlap = (event, block) => event.start < block.end && block.start < event.end
events.sort((a, b) => a.start - b.start)
@ -68,10 +64,7 @@ export function layoutEvents(events) {
if (blocks.length > 0) {
layout = layout.filter(block => !overlap(event, block))
layout.push({
start: Math.min(
event.start,
...blocks.map(block => block.start)
),
start: Math.min(event.start, ...blocks.map(block => block.start)),
end: Math.max(event.end, ...blocks.map(block => block.end)),
events: blocks.flatMap(block => block.events).concat([event]),
})

@ -53,8 +53,7 @@ function specialEventPatches(eventi) {
// Il laboratorio del primo anno in realtà è in due gruppi separati
eventi.forEach(evento => {
if (
evento.nome ===
'LABORATORIO DI INTRODUZIONE ALLA MATEMATICA COMPUTAZIONALE'
evento.nome === 'LABORATORIO DI INTRODUZIONE ALLA MATEMATICA COMPUTAZIONALE'
) {
if (evento.docenti[0].nome === 'GIOVANNI') {
evento.nome += ' (A)'
@ -75,9 +74,7 @@ function formatEvents(timetable) {
name: _.split(nome, '-', 1)[0].trim(),
start: new Date(dataInizio),
end: new Date(dataFine),
docenti: docenti.map(({ nome, cognome }) =>
prettyProfName(nome, cognome)
),
docenti: docenti.map(({ nome, cognome }) => prettyProfName(nome, cognome)),
aule: aule.map(aula => prettyAulaName(aula.codice)),
}
})
@ -191,10 +188,7 @@ const App = ({}) => {
// const [mode, setMode] = usePersistentState('orario.mode', MODE_COURSES)
// Selection
const [selectedCourses, setSelectedCourses] = usePersistentState(
'selection',
[]
)
const [selectedCourses, setSelectedCourses] = usePersistentState('selection', [])
// Menus
const [helpVisible, setHelpVisible] = useState(false)
@ -265,16 +259,15 @@ const App = ({}) => {
) : timetables['tutti'].length === 0 ? (
<div class="warning">
<p>
Non esistono corsi per la settimana selezionata:
buone vacanze! 🎉
Non esistono corsi per la settimana selezionata: buone
vacanze! 🎉
</p>
<p>
Per cambiare settimana puoi usare il widget
Calendario (
Per cambiare settimana puoi usare il widget Calendario (
<Icon name="calendar_month" />) in alto a destra
<br />
In versione mobile, il widget Calendario è
situato dentro il Menu (
In versione mobile, il widget Calendario è situato dentro
il Menu (
<Icon name="menu" />)
</p>
</div>

@ -644,8 +644,7 @@ body {
border: 1px solid var(--border-600);
border-radius: 10px 10px 0 0;
@media screen and (max-width: $device-s-width),
(pointer: coarse) {
@media screen and (max-width: $device-s-width), (pointer: coarse) {
font-size: 12px;
}
@ -700,10 +699,7 @@ body {
&.original {
grid-template-columns: auto repeat(5, 1fr);
grid-template-rows: min-content repeat(
var(--time-slots),
1fr
);
grid-template-rows: min-content repeat(var(--time-slots), 1fr);
.transpose-button,
.day-label {
@ -730,22 +726,16 @@ body {
}
.event-block-wrapper {
grid-row: calc(var(--time-start) + 2) /
calc(var(--time-end) + 2);
grid-row: calc(var(--time-start) + 2) / calc(var(--time-end) + 2);
grid-column: calc(var(--day-position) + 1);
.event-block {
.event-wrapper {
width: calc(100% / var(--of));
height: calc(
100% * var(--size) / var(--block-size)
);
height: calc(100% * var(--size) / var(--block-size));
transform: translateX(calc(100% * var(--index)))
translateY(
calc(
100% * var(--relative-start) /
var(--size)
)
calc(100% * var(--relative-start) / var(--size))
);
}
}
@ -753,10 +743,7 @@ body {
}
&.transposed {
grid-template-rows: auto repeat(5, 1fr);
grid-template-columns: min-content repeat(
var(--time-slots),
1fr
);
grid-template-columns: min-content repeat(var(--time-slots), 1fr);
.transpose-button,
.day-label {
@ -792,15 +779,10 @@ body {
.event-block {
.event-wrapper {
height: calc(100% / var(--of));
width: calc(
100% * var(--size) / var(--block-size)
);
width: calc(100% * var(--size) / var(--block-size));
transform: translateY(calc(100% * var(--index)))
translateX(
calc(
100% * var(--relative-start) /
var(--size)
)
calc(100% * var(--relative-start) / var(--size))
);
}
}

@ -12,15 +12,7 @@ export const WEEK_DAYS = [
'Sabato',
]
export const WEEK_DAYS_SHORT = [
'Dom',
'Lun',
'Mar',
'Mer',
'Gio',
'Ven',
'Sab'
]
export const WEEK_DAYS_SHORT = ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab']
// Hashing
@ -32,12 +24,8 @@ export function hashString(str, seed = 0) {
h1 = Math.imul(h1 ^ ch, 2654435761)
h2 = Math.imul(h2 ^ ch, 1597334677)
}
h1 =
Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^
Math.imul(h2 ^ (h2 >>> 13), 3266489909)
h2 =
Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^
Math.imul(h1 ^ (h1 >>> 13), 3266489909)
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)
return 4294967296 * (2097151 & h2) + (h1 >>> 0)
}
@ -50,9 +38,7 @@ export function prettyCourseName(name) {
.map(word => {
if (word.trim().length === 0) return word
return /(^del|^nel|^di$|^dei$|^con$|^alla$|^per$|^e$|^la$)/.test(
word
)
return /(^del|^nel|^di$|^dei$|^con$|^alla$|^per$|^e$|^la$)/.test(word)
? word
: word[0].toUpperCase() + word.slice(1)
})
@ -61,7 +47,7 @@ export function prettyCourseName(name) {
.replaceAll('IIi', 'III')
.replaceAll('Iii', 'III')
.replaceAll(/'(.)/g, ({}, letter) => "'" + letter.toUpperCase())
.replaceAll(/\((a|b)\)/g, ({}, letter) => "(" + letter.toUpperCase() + ")")
.replaceAll(/\((a|b)\)/g, ({}, letter) => '(' + letter.toUpperCase() + ')')
}
export function prettyAulaName(name) {

Loading…
Cancel
Save