import _ from 'lodash' import { render } from 'preact' import { useEffect, useState } from 'preact/hooks' import { ToolOverlay } from './components/CourseVisibility.jsx' import { EventsView } from './components/EventsView.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' window._ = _ window.dataBuffer = {} const CALENDAR_IDS = { 'anno-1': ['6308cfcb1df5cb026699ce32'], 'anno-2': ['6308e2dc09352a0208fefdd9'], 'anno-3': ['6308e42a1df5cb026699ced4'], 'magistrale': ['6308e8ea0c34e703bb1f7e85'], 'tutti': [ '6308cfcb1df5cb026699ce32', '6308e2dc09352a0208fefdd9', '6308e42a1df5cb026699ced4', '6308e8ea0c34e703bb1f7e85', ], } async function loadEventi(ids) { const calendari = await Promise.all( ids.map(async 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: '2022-10-02T22:00:00.000Z', dataFine: '2022-10-07T22:00:00.000Z', }), method: 'POST', mode: 'cors', credentials: 'omit', } ) return await req.json() }) ) // console.log(calendari) if (ids.length === 1) { return calendari[0] } return _.uniqBy(_.concat(...calendari), 'id') } const App = ({}) => { const [source, setSource] = useState('magistrale') const [eventi, setEventi] = useState([]) const [selectedCourses, setSelectedCourses] = useState([]) useEffect(() => { setSelectedCourses([]) }, [source]) useEffect(async () => { const eventi = await loadEventi(CALENDAR_IDS[source]) window.dataBuffer[source] = eventi setEventi(eventi) }, [source]) const [helpVisible, setHelpVisible] = useState(false) const [mode, setMode] = useState('course') const [hideOtherCourses, setHideOtherCourses] = useState(false) // TODO: Should wrap in "useEffect"? if (selectedCourses.length === 0) { setHideOtherCourses(false) } const [showMobileMenu, setShowMobileMenu] = useState(false) useEffect(async () => { const eventi = await loadEventi(CALENDAR_IDS[source]) // window.dataBuffer[source] = eventi setEventi(eventi) }, [source]) const [theme, setTheme] = useState(localStorage.getItem('theme') ?? 'light') document.body.classList.toggle('dark-mode', theme === 'dark') localStorage.setItem('theme', theme) return ( <> setShowMobileMenu(true), onHelp: () => setHelpVisible(true), theme, setTheme, }} /> ({ name: _.split(nome, '-', 1)[0].trim(), start: new Date(dataInizio), end: new Date(dataFine), docenti: docenti.map(({ nome, cognome }) => _.startCase(_.lowerCase(nome) + ' ' + _.lowerCase(cognome)) ), aula: _.startCase(aule[0].codice.toLowerCase()).replace( /([A-Z]) ([1-9])/, '$1$2' ), }))} /> {selectedCourses.length > 0 && ( setHideOtherCourses(s => !s)} onClose={() => { setSelectedCourses([]) setHideOtherCourses(false) }} /> )} {showMobileMenu && ( { setShowMobileMenu(false) }, }} /> )} {helpVisible && ( Guida } onClose={() => setHelpVisible(false)} > )} ) } render(, document.body)