import _ from 'lodash'
import { render } from 'preact'
import { useEffect, useState } from 'preact/hooks'
// import { ToolOverlay } from './components/ToolOverlay.jsx'
//
// import {
// EventsView,
// MODE_COURSES,
// MODE_SCHEDULE,
// } from './components/EventsView.jsx'
import { Courses } from './components/view/Courses.jsx'
import { Schedule } from './components/view/Schedule.jsx'
import { HamburgerMenu } from './components/HamburgerMenu.jsx'
import { Help } from './components/Help.jsx'
import { Icon } from './components/Icon.jsx'
import { Popup } from './components/Popup.jsx'
import { Toolbar } from './components/Toolbar.jsx'
import { OptionBar } from './components/OptionBar.jsx'
import {
prettyAulaName,
prettyProfName,
clearOldPersistentStates,
usePersistentState,
} from './utils.jsx'
// Che fanno queste due righe?
window._ = _
window.dataBuffer = {}
const TIMETABLE_IDS = {
'anno-1': '64a7c1c651f079001d52e9c8',
'anno-2': '6308e2dc09352a0208fefdd9',
'anno-3': '6308e42a1df5cb026699ced4',
'magistrale': '64a7c7091ab813002c5d9ede',
}
const DEFAULT_DATE_RANGE = {
from: '2023-10-09T00:00:00.000Z',
to: '2023-10-14T00:00:00.000Z',
}
const DATE_RANGES = {
'64a7c1c651f079001d52e9c8': DEFAULT_DATE_RANGE,
'6308e2dc09352a0208fefdd9': DEFAULT_DATE_RANGE,
'6308e42a1df5cb026699ced4': DEFAULT_DATE_RANGE,
'64a7c7091ab813002c5d9ede': DEFAULT_DATE_RANGE,
}
function specialEventPatches(eventi) {
// Il laboratorio del primo anno in realtà è in due canali separati
let i = 1
eventi.forEach(evento => {
if (
evento.nome ===
'LABORATORIO DI INTRODUZIONE ALLA MATEMATICA COMPUTAZIONALE'
) {
evento.nome += ` (${i})`
i++
}
})
return eventi
}
function formatEvents(timetable) {
return timetable.map(({ nome, dataInizio, dataFine, docenti, aule }) => {
return {
id: nome,
name: _.split(nome, '-', 1)[0].trim(),
start: new Date(dataInizio),
end: new Date(dataFine),
docenti: docenti.map(({ nome, cognome }) =>
prettyProfName(nome, cognome)
),
aule: aule.map(aula => prettyAulaName(aula.codice)),
}
})
}
async function loadCalendari() {
async function req(id) {
// Almost directly copy-pasted from Chrome Dev Tools
const req = await fetch(
'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
{
headers: {
'content-type': 'application/json;charset=UTF-8',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
},
body: JSON.stringify({
mostraImpegniAnnullati: true,
mostraIndisponibilitaTotali: false,
linkCalendarioId: id,
clienteId: '628de8b9b63679f193b87046',
pianificazioneTemplate: false,
dataInizio: DATE_RANGES[id].from,
dataFine: DATE_RANGES[id].to,
}),
method: 'POST',
mode: 'cors',
credentials: 'omit',
}
)
return await req.json()
}
const requests = [
req(TIMETABLE_IDS['anno-1']),
req(TIMETABLE_IDS['anno-2']),
req(TIMETABLE_IDS['anno-3']),
req(TIMETABLE_IDS['magistrale']),
]
const results = await Promise.all(requests)
const timetablesRaw = results.map(timetable =>
specialEventPatches(_.uniqBy(timetable, 'id'))
)
const allRaw = specialEventPatches(_.uniqBy(_.concat(...results), 'id'))
return {
'anno-1': formatEvents(timetablesRaw[0]),
'anno-2': formatEvents(timetablesRaw[1]),
'anno-3': formatEvents(timetablesRaw[2]),
'magistrale': formatEvents(timetablesRaw[3]),
'tutti': formatEvents(allRaw),
}
}
const View = ({ view, selection, setSelection, timetables }) => {
if (view === 'orario') {
return
} else if (view === 'lista') {
return (
)
} else {
return (
)
}
}
const App = ({}) => {
// Clear persistent states unless state_token corresponds to the one passed
// as the argument. Useful with breaking updates. Change this token if your
// (breaking) update needs a reset of persistent states to avoid crashes.
//
// Use any random string of your choice
// clearOldPersistentStates('e73cba02')
// Data Sources
const [view, setView] = usePersistentState('view', 'magistrale')
const [timetables, setTimetables] = useState(null)
useEffect(async () => {
setTimetables(await loadCalendari())
}, [])
// View Modes
// const [mode, setMode] = usePersistentState('orario.mode', MODE_COURSES)
// Selection
const [selectedCourses, setSelectedCourses] = usePersistentState(
'selection',
[]
)
// Menus
const [helpVisible, setHelpVisible] = useState(false)
const [showMobileMenu, setShowMobileMenu] = useState(false)
// const groupIds = new Set(eventi.map(e => e.nome))
const toolOverlayVisible = selectedCourses.length > 0
const [theme, setTheme] = usePersistentState(
'theme',
'light'
// window.matchMedia('(prefers-color-scheme: dark)').matches
// ? 'dark'
// : 'light'
)
document.body.classList.toggle('dark-mode', theme === 'dark')
return (
<>
setShowMobileMenu(true),
onHelp: () => setHelpVisible(true),
theme,
setTheme,
}}
/>
setHelpVisible(true),
}}
orizzontale
/>
{timetables && (
)}
{showMobileMenu && (
{
setShowMobileMenu(false)
},
}}
/>
)}
{helpVisible && (
Guida
>
}
onClose={() => setHelpVisible(false)}
>
)}
>
)
}
render(, document.body)