diff --git a/src/components/HamburgerMenu.jsx b/src/components/HamburgerMenu.jsx
index 5f9ff71..e3df2d2 100644
--- a/src/components/HamburgerMenu.jsx
+++ b/src/components/HamburgerMenu.jsx
@@ -4,57 +4,57 @@ import { Help } from './Help.jsx'
import { Icon } from './Icon.jsx'
export const HamburgerMenu = ({ onClose, mode, setMode, source, setSource, theme, setTheme }) => {
- return (
-
+
*/}
+
+
+
+ Guida
+
+
+
+
+ )
}
diff --git a/src/components/Optionbar.jsx b/src/components/Optionbar.jsx
new file mode 100644
index 0000000..8333016
--- /dev/null
+++ b/src/components/Optionbar.jsx
@@ -0,0 +1,41 @@
+import { CompoundButton } from './CompoundButton.jsx'
+import { MODE_COURSE, MODE_SCHEDULE, MODE_WORKWEEK, MODE_WORKWEEK_GRID } from './EventsView.jsx'
+import { Icon } from './Icon.jsx'
+
+export const Optionbar = ({ mode, setMode, source, setSource, onHelp }) => {
+ return (
+
+
+
+ },
+ ]}
+ value={source}
+ setValue={setSource}
+ />
+
+
+
+
+ },
+ {
+ value: MODE_WORKWEEK_GRID,
+ label: ,
+ },
+ { value: MODE_SCHEDULE, label: },
+ ]}
+ value={mode}
+ setValue={setMode}
+ />
+
+
+
+ )
+}
diff --git a/src/main.jsx b/src/main.jsx
index cd033fe..8765eec 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -9,186 +9,196 @@ 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'
window._ = _
window.dataBuffer = {}
const CALENDAR_IDS = {
- 'anno-1': ['6308cfcb1df5cb026699ce32'],
- 'anno-2': ['6308e2dc09352a0208fefdd9'],
- 'anno-3': ['6308e42a1df5cb026699ced4'],
- 'magistrale': ['6308e8ea0c34e703bb1f7e85'],
- 'tutti': [
- '6308cfcb1df5cb026699ce32',
- '6308e2dc09352a0208fefdd9',
- '6308e42a1df5cb026699ced4',
- '6308e8ea0c34e703bb1f7e85',
- ],
+ '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 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 = ({}) => {
- // Data Sources
- const [source, setSource] = useState('anno-1')
- const [eventi, setEventi] = useState([])
-
- // View Modes
- const [mode, setMode] = useState(MODE_WORKWEEK_GRID)
-
- // Selection
- const [selectedCourses, setSelectedCourses] = useState([])
- const [hideOtherCourses, setHideOtherCourses] = useState(false)
-
- // Menus
- const [helpVisible, setHelpVisible] = useState(false)
- const [showMobileMenu, setShowMobileMenu] = useState(false)
-
- useEffect(async () => {
- console.log('source changed')
- const eventi = await loadEventi(CALENDAR_IDS[source])
-
- window.dataBuffer[source] = eventi
-
- setEventi(eventi)
- }, [source])
-
- const groupIds = new Set(eventi.map(e => e.nome))
- const toolOverlayVisible =
- selectedCourses.length > 0 && selectedCourses.filter(id => groupIds.has(id)).length > 0
-
- useEffect(() => {
- console.log('course length changed')
- const groupIds = new Set(eventi.map(e => e.nome))
-
- if (
- selectedCourses.length === 0 ||
- selectedCourses.filter(id => groupIds.has(id)).length === 0
- ) {
- setHideOtherCourses(false)
- }
- }, [eventi, selectedCourses.length])
-
- const [theme, setTheme] = useState(
- localStorage.getItem('theme') ??
- (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
- )
-
- document.body.classList.toggle('dark-mode', theme === 'dark')
- localStorage.setItem('theme', theme)
-
- return (
- <>
- setShowMobileMenu(true),
- onHelp: () => setHelpVisible(true),
- theme,
- setTheme,
- }}
- />
- ({
- id: nome,
- 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'
- ),
- }))}
- />
- {toolOverlayVisible && (
- setHideOtherCourses(s => !s)}
- onClose={() => {
- setSelectedCourses([])
- setHideOtherCourses(false)
- }}
- />
- )}
- {showMobileMenu && (
- {
- setShowMobileMenu(false)
- },
- }}
- />
- )}
- {helpVisible && (
-
- Guida
- >
- }
- onClose={() => setHelpVisible(false)}
- >
-
-
- )}
- >
- )
+ // Data Sources
+ const [source, setSource] = useState('anno-1')
+ const [eventi, setEventi] = useState([])
+
+ // View Modes
+ const [mode, setMode] = useState(MODE_WORKWEEK_GRID)
+
+ // Selection
+ const [selectedCourses, setSelectedCourses] = useState([])
+ const [hideOtherCourses, setHideOtherCourses] = useState(false)
+
+ // Menus
+ const [helpVisible, setHelpVisible] = useState(false)
+ const [showMobileMenu, setShowMobileMenu] = useState(false)
+
+ useEffect(async () => {
+ console.log('source changed')
+ const eventi = await loadEventi(CALENDAR_IDS[source])
+
+ window.dataBuffer[source] = eventi
+
+ setEventi(eventi)
+ }, [source])
+
+ const groupIds = new Set(eventi.map(e => e.nome))
+ const toolOverlayVisible =
+ selectedCourses.length > 0 && selectedCourses.filter(id => groupIds.has(id)).length > 0
+
+ useEffect(() => {
+ console.log('course length changed')
+ const groupIds = new Set(eventi.map(e => e.nome))
+
+ if (
+ selectedCourses.length === 0 ||
+ selectedCourses.filter(id => groupIds.has(id)).length === 0
+ ) {
+ setHideOtherCourses(false)
+ }
+ }, [eventi, selectedCourses.length])
+
+ const [theme, setTheme] = useState(
+ localStorage.getItem('theme') ??
+ (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
+ )
+
+ document.body.classList.toggle('dark-mode', theme === 'dark')
+ localStorage.setItem('theme', theme)
+
+ return (
+ <>
+ setShowMobileMenu(true),
+ onHelp: () => setHelpVisible(true),
+ theme,
+ setTheme,
+ }}
+ />
+ setHelpVisible(true),
+ }}
+ />
+ ({
+ id: nome,
+ 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'
+ ),
+ }))}
+ />
+ {toolOverlayVisible && (
+ setHideOtherCourses(s => !s)}
+ onClose={() => {
+ setSelectedCourses([])
+ setHideOtherCourses(false)
+ }}
+ />
+ )}
+ {showMobileMenu && (
+ {
+ setShowMobileMenu(false)
+ },
+ }}
+ />
+ )}
+ {helpVisible && (
+
+ Guida
+ >
+ }
+ onClose={() => setHelpVisible(false)}
+ >
+
+
+ )}
+ >
+ )
}
render(, document.body)
diff --git a/src/styles/main.scss b/src/styles/main.scss
index 5d44a3d..79cd77d 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -28,35 +28,34 @@ html {
--accent-500: #6cc16c;
--accent-900: #244624;
-
- --bubble-red: hsl(359, 100%, 92%);
- --bubble-purple: hsl(274, 100%, 92%);
- --bubble-blue: hsl(241, 100%, 92%);
- --bubble-yellow: hsl(50, 100%, 92%);
- --bubble-green: hsl(125, 100%, 92%);
- --bubble-orange: hsl(25, 100%, 92%);
- --bubble-lightlightblue: hsl(176, 100%, 92%);
- --bubble-lightblue: hsl(198, 100%, 92%);
-
- --bubble-highlight-red: hsl(359, 100%, 85%);
- --bubble-highlight-purple: hsl(274, 100%, 85%);
- --bubble-highlight-blue: hsl(241, 100%, 85%);
- --bubble-highlight-yellow: hsl(50, 100%, 85%);
- --bubble-highlight-green: hsl(125, 100%, 85%);
- --bubble-highlight-orange: hsl(25, 100%, 85%);
- --bubble-highlight-lightlightblue: hsl(176, 100%, 85%);
- --bubble-highlight-lightblue: hsl(198, 100%, 85%);
-
- --bubble-border-red: hsl(359, 75%, 51%);
- --bubble-border-purple: hsl(274, 75%, 51%);
- --bubble-border-blue: hsl(241, 75%, 51%);
- --bubble-border-yellow: hsl(50, 75%, 51%);
- --bubble-border-green: hsl(125, 75%, 51%);
- --bubble-border-orange: hsl(25, 75%, 51%);
- --bubble-border-lightlightblue: hsl(176, 75%, 51%);
- --bubble-border-lightblue: hsl(198, 75%, 51%);
-
- --bold-on-dark: 300;
+ --bubble-red: hsl(359, 100%, 92%);
+ --bubble-purple: hsl(274, 100%, 92%);
+ --bubble-blue: hsl(241, 100%, 92%);
+ --bubble-yellow: hsl(50, 100%, 92%);
+ --bubble-green: hsl(125, 100%, 92%);
+ --bubble-orange: hsl(25, 100%, 92%);
+ --bubble-lightlightblue: hsl(176, 100%, 92%);
+ --bubble-lightblue: hsl(198, 100%, 92%);
+
+ --bubble-highlight-red: hsl(359, 100%, 85%);
+ --bubble-highlight-purple: hsl(274, 100%, 85%);
+ --bubble-highlight-blue: hsl(241, 100%, 85%);
+ --bubble-highlight-yellow: hsl(50, 100%, 85%);
+ --bubble-highlight-green: hsl(125, 100%, 85%);
+ --bubble-highlight-orange: hsl(25, 100%, 85%);
+ --bubble-highlight-lightlightblue: hsl(176, 100%, 85%);
+ --bubble-highlight-lightblue: hsl(198, 100%, 85%);
+
+ --bubble-border-red: hsl(359, 75%, 51%);
+ --bubble-border-purple: hsl(274, 75%, 51%);
+ --bubble-border-blue: hsl(241, 75%, 51%);
+ --bubble-border-yellow: hsl(50, 75%, 51%);
+ --bubble-border-green: hsl(125, 75%, 51%);
+ --bubble-border-orange: hsl(25, 75%, 51%);
+ --bubble-border-lightlightblue: hsl(176, 75%, 51%);
+ --bubble-border-lightblue: hsl(198, 75%, 51%);
+
+ --bold-on-dark: 300;
}
body.dark-mode {
@@ -74,32 +73,31 @@ body.dark-mode {
--accent-500: hsl(269, 40%, 70%);
--accent-900: hsl(269, 30%, 90%);
-
- --bubble-red: hsl(359, 40%, 25%);
- --bubble-purple: hsl(274, 40%, 25%);
- --bubble-blue: hsl(241, 40%, 25%);
- --bubble-yellow: hsl(50, 40%, 25%);
- --bubble-green: hsl(125, 40%, 25%);
- --bubble-orange: hsl(25, 40%, 25%);
- --bubble-lightblue: hsl(176, 40%, 25%);
-
- --bubble-border-red: hsl(359, 75%, 51%);
- --bubble-border-purple: hsl(274, 75%, 51%);
- --bubble-border-blue: hsl(241, 75%, 51%);
- --bubble-border-yellow: hsl(50, 75%, 51%);
- --bubble-border-green: hsl(125, 75%, 51%);
- --bubble-border-orange: hsl(25, 75%, 51%);
- --bubble-border-lightblue: hsl(176, 75%, 51%);
-
- --bubble-highlight-red: hsl(359, 40%, 31%);
- --bubble-highlight-purple: hsl(274, 40%, 31%);
- --bubble-highlight-blue: hsl(241, 40%, 31%);
- --bubble-highlight-yellow: hsl(50, 40%, 31%);
- --bubble-highlight-green: hsl(125, 40%, 31%);
- --bubble-highlight-orange: hsl(25, 40%, 31%);
- --bubble-highlight-lightblue: hsl(176, 40%, 31%);
-
- --bold-on-dark: 500;
+ --bubble-red: hsl(359, 40%, 25%);
+ --bubble-purple: hsl(274, 40%, 25%);
+ --bubble-blue: hsl(241, 40%, 25%);
+ --bubble-yellow: hsl(50, 40%, 25%);
+ --bubble-green: hsl(125, 40%, 25%);
+ --bubble-orange: hsl(25, 40%, 25%);
+ --bubble-lightblue: hsl(176, 40%, 25%);
+
+ --bubble-border-red: hsl(359, 75%, 51%);
+ --bubble-border-purple: hsl(274, 75%, 51%);
+ --bubble-border-blue: hsl(241, 75%, 51%);
+ --bubble-border-yellow: hsl(50, 75%, 51%);
+ --bubble-border-green: hsl(125, 75%, 51%);
+ --bubble-border-orange: hsl(25, 75%, 51%);
+ --bubble-border-lightblue: hsl(176, 75%, 51%);
+
+ --bubble-highlight-red: hsl(359, 40%, 31%);
+ --bubble-highlight-purple: hsl(274, 40%, 31%);
+ --bubble-highlight-blue: hsl(241, 40%, 31%);
+ --bubble-highlight-yellow: hsl(50, 40%, 31%);
+ --bubble-highlight-green: hsl(125, 40%, 31%);
+ --bubble-highlight-orange: hsl(25, 40%, 31%);
+ --bubble-highlight-lightblue: hsl(176, 40%, 31%);
+
+ --bold-on-dark: 500;
}
$device-s-width: 600px;
@@ -450,9 +448,38 @@ body {
}
}
}
+.optionbar {
+ @extend .panel;
+
+ padding: 1rem 0.75rem 1rem 1rem;
+
+ border-radius: 0;
+ border: none;
+ border-bottom: 1px solid var(--border-500);
+
+ height: 4rem;
+
+ display: none;
+ align-items: center;
+ justify-content: space-between;
+
+ @media screen and (max-width: $device-s-width), (pointer: coarse) {
+ display: flex;
+ }
+
+ .option-group {
+ display: flex;
+ align-items: center;
+
+ gap: 0.75rem;
+ }
+}
.events-view {
height: calc(100vh - 4rem);
+ @media screen and (max-width: $device-s-width), (pointer: coarse) {
+ height: calc(100vh - 8rem);
+ }
.course-view {
padding: 1rem;
@@ -880,109 +907,108 @@ body {
height: 100%;
overflow: scroll;
- .grid {
- width: 100%;
- max-width: 55rem;
- display: grid;
- grid-template-columns: 3rem repeat(var(--time-length), 1fr);
- grid-template-rows: 2rem repeat(var(--days-length), 1fr);
- border: 2px solid var(--border-500);
- border-radius: 10px 10px 0 0;
-
-
- @media screen and (max-width: $device-s-width), (pointer: coarse) {
- font-size: 12px;
- }
-
- .time {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0.5rem;
- grid-row: 1;
- grid-column: var(--offset) / span 2;
- }
- .day-name {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0.5rem;
- grid-column: 1;
- grid-row: var(--line);
- }
-
- .event {
- display: flex;
- flex-direction: row;
- @media screen and (max-width: $device-s-width), (pointer: coarse) {
- flex-direction: column;
- }
- gap: 0.25rem;
- align-items: center;
- justify-content: center;
- margin: 0.25rem;
- padding: 0.5rem;
- grid-row: var(--line);
- grid-column: var(--offset) / span var(--length);
- background-color: var(--color);
- border: 3px solid var(--color);
- border-radius: 10px;
- font-weight: var(--bold-on-dark);
- text-align: center;
-
- &.highlight {
- background-color: var(--highlight-color);
- border: 3px solid var(--highlight-color);
- }
- &.selected {
- border: 3px solid var(--border-color);
- }
- }
-
- .hline {
- grid-column: 1 / 13;
- grid-row: var(--line);
- height: 0px;
- border-bottom: 1px solid var(--border-500);
- }
-
- .vline {
- grid-column: var(--offset);
- grid-row: 1 / calc(2 + var(--days-length));
- width: 0px;
- border-right: 1px dashed var(--border-500);
- }
- }
- .legend {
- max-width: 55rem;
- display: grid;
- grid-template-columns: min-content 1fr;
- border: 2px solid var(--border-500);
- border-radius: 0 0 10px 10px;
- border-top: none;
- padding: 1rem;
- gap: 0.5rem 1rem;
- align-items: center;
- justify-content: center;
- width: 100%;
-
- .name {
- width: 100%;
- }
-
- .color {
- display: flex;
- justify-content: center;
- align-items: center;
- font-weight: 500;
- width: 2rem;
- height: 1.5rem;
- background-color: var(--color);
- border: 2px solid var(--border-color);
- border-radius: 10px;
- font-weight: var(--bold-on-dark);
- }
- }
+ .grid {
+ width: 100%;
+ max-width: 55rem;
+ display: grid;
+ grid-template-columns: 3rem repeat(var(--time-length), 1fr);
+ grid-template-rows: 2rem repeat(var(--days-length), 1fr);
+ border: 2px solid var(--border-500);
+ border-radius: 10px 10px 0 0;
+
+ @media screen and (max-width: $device-s-width), (pointer: coarse) {
+ font-size: 12px;
+ }
+
+ .time {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0.5rem;
+ grid-row: 1;
+ grid-column: var(--offset) / span 2;
+ }
+ .day-name {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0.5rem;
+ grid-column: 1;
+ grid-row: var(--line);
+ }
+
+ .event {
+ display: flex;
+ flex-direction: row;
+ @media screen and (max-width: $device-s-width), (pointer: coarse) {
+ flex-direction: column;
+ }
+ gap: 0.25rem;
+ align-items: center;
+ justify-content: center;
+ margin: 0.25rem;
+ padding: 0.5rem;
+ grid-row: var(--line);
+ grid-column: var(--offset) / span var(--length);
+ background-color: var(--color);
+ border: 3px solid var(--color);
+ border-radius: 10px;
+ font-weight: var(--bold-on-dark);
+ text-align: center;
+
+ &.highlight {
+ background-color: var(--highlight-color);
+ border: 3px solid var(--highlight-color);
+ }
+ &.selected {
+ border: 3px solid var(--border-color);
+ }
+ }
+
+ .hline {
+ grid-column: 1 / 13;
+ grid-row: var(--line);
+ height: 0px;
+ border-bottom: 1px solid var(--border-500);
+ }
+
+ .vline {
+ grid-column: var(--offset);
+ grid-row: 1 / calc(2 + var(--days-length));
+ width: 0px;
+ border-right: 1px dashed var(--border-500);
+ }
+ }
+ .legend {
+ max-width: 55rem;
+ display: grid;
+ grid-template-columns: min-content 1fr;
+ border: 2px solid var(--border-500);
+ border-radius: 0 0 10px 10px;
+ border-top: none;
+ padding: 1rem;
+ gap: 0.5rem 1rem;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+
+ .name {
+ width: 100%;
+ }
+
+ .color {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-weight: 500;
+ width: 2rem;
+ height: 1.5rem;
+ background-color: var(--color);
+ border: 2px solid var(--border-color);
+ border-radius: 10px;
+ font-weight: var(--bold-on-dark);
+ }
+ }
}
.schedule-view {