|
|
@ -9,41 +9,40 @@ import { layoutIntervals } from '../../interval-layout.js'
|
|
|
|
export const WorkWeekGrid = ({ events, selection, setSelection, hideOtherCourses }) => {
|
|
|
|
export const WorkWeekGrid = ({ events, selection, setSelection, hideOtherCourses }) => {
|
|
|
|
const selectionSet = new Set(selection)
|
|
|
|
const selectionSet = new Set(selection)
|
|
|
|
|
|
|
|
|
|
|
|
const colorList = [
|
|
|
|
const colorList = ['red', 'purple', 'blue', 'yellow', 'green', 'orange', 'lightblue']
|
|
|
|
'red',
|
|
|
|
|
|
|
|
'purple',
|
|
|
|
const courses = _.uniqBy(
|
|
|
|
'blue',
|
|
|
|
|
|
|
|
'yellow',
|
|
|
|
|
|
|
|
'green',
|
|
|
|
|
|
|
|
'orange',
|
|
|
|
|
|
|
|
'lightblue',
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const courses = _.uniqBy(!hideOtherCourses ? events : events.filter(e => selectionSet.has(e.id)), event => event.id);
|
|
|
|
|
|
|
|
const colors = Object.fromEntries(courses.map((course, index) => {
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
|
|
course.id,
|
|
|
|
|
|
|
|
[
|
|
|
|
|
|
|
|
colorList[index % colorList.length],
|
|
|
|
|
|
|
|
courses.length <= colorList.length ? '' : String.fromCharCode(65 + Math.floor(index / colorList.length))
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const base = {
|
|
|
|
|
|
|
|
1: [],
|
|
|
|
|
|
|
|
2: [],
|
|
|
|
|
|
|
|
3: [],
|
|
|
|
|
|
|
|
4: [],
|
|
|
|
|
|
|
|
5: [],
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const eventsByWeekday = {
|
|
|
|
|
|
|
|
... base,
|
|
|
|
|
|
|
|
... _.groupBy(
|
|
|
|
|
|
|
|
!hideOtherCourses ? events : events.filter(e => selectionSet.has(e.id)),
|
|
|
|
!hideOtherCourses ? events : events.filter(e => selectionSet.has(e.id)),
|
|
|
|
event => event.start.getDay()
|
|
|
|
event => event.id
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
const colors = Object.fromEntries(
|
|
|
|
|
|
|
|
courses.map((course, index) => {
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
|
|
course.id,
|
|
|
|
|
|
|
|
[
|
|
|
|
|
|
|
|
colorList[index % colorList.length],
|
|
|
|
|
|
|
|
courses.length <= colorList.length
|
|
|
|
|
|
|
|
? ''
|
|
|
|
|
|
|
|
: String.fromCharCode(65 + Math.floor(index / colorList.length)),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const base = {
|
|
|
|
|
|
|
|
1: [],
|
|
|
|
|
|
|
|
2: [],
|
|
|
|
|
|
|
|
3: [],
|
|
|
|
|
|
|
|
4: [],
|
|
|
|
|
|
|
|
5: [],
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const eventsByWeekday = {
|
|
|
|
|
|
|
|
...base,
|
|
|
|
|
|
|
|
..._.groupBy(
|
|
|
|
|
|
|
|
!hideOtherCourses ? events : events.filter(e => selectionSet.has(e.id)),
|
|
|
|
|
|
|
|
event => event.start.getDay()
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const dayIntervalLayout = _.mapValues(eventsByWeekday, events =>
|
|
|
|
const dayIntervalLayout = _.mapValues(eventsByWeekday, events =>
|
|
|
|
layoutIntervals(
|
|
|
|
layoutIntervals(
|
|
|
@ -54,36 +53,39 @@ export const WorkWeekGrid = ({ events, selection, setSelection, hideOtherCourses
|
|
|
|
}))
|
|
|
|
}))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
const startsAndEnds = Object.entries(dayIntervalLayout).flatMap(([index, layout]) => layout.flatMap(events => events.map(event => [event.start, event.end])));
|
|
|
|
const startsAndEnds = Object.entries(dayIntervalLayout).flatMap(([index, layout]) =>
|
|
|
|
const minStart = Math.min(...startsAndEnds.map(([s, e]) => s)) / 60;
|
|
|
|
layout.flatMap(events => events.map(event => [event.start, event.end]))
|
|
|
|
const maxEnd = Math.max(...startsAndEnds.map(([s, e]) => e)) / 60;
|
|
|
|
)
|
|
|
|
// const timeStart = minStart < 9 ? 7 :
|
|
|
|
const minStart = Math.min(...startsAndEnds.map(([s, e]) => s)) / 60
|
|
|
|
// minStart < 11 ? 9 :
|
|
|
|
const maxEnd = Math.max(...startsAndEnds.map(([s, e]) => e)) / 60
|
|
|
|
// minStart < 13 ? 11 :
|
|
|
|
// const timeStart = minStart < 9 ? 7 :
|
|
|
|
// minStart < 14 ? 13 :
|
|
|
|
// minStart < 11 ? 9 :
|
|
|
|
// minStart < 16 ? 14 :
|
|
|
|
// minStart < 13 ? 11 :
|
|
|
|
// minStart < 18 ? 16 :
|
|
|
|
// minStart < 14 ? 13 :
|
|
|
|
// 18;
|
|
|
|
// minStart < 16 ? 14 :
|
|
|
|
// const timeEnd = maxEnd > 18 ? 20 :
|
|
|
|
// minStart < 18 ? 16 :
|
|
|
|
// maxEnd > 16 ? 18 :
|
|
|
|
// 18;
|
|
|
|
// maxEnd > 14 ? 16 :
|
|
|
|
// const timeEnd = maxEnd > 18 ? 20 :
|
|
|
|
// maxEnd > 13 ? 14 :
|
|
|
|
// maxEnd > 16 ? 18 :
|
|
|
|
// maxEnd > 11 ? 13 :
|
|
|
|
// maxEnd > 14 ? 16 :
|
|
|
|
// maxEnd > 9 ? 11 :
|
|
|
|
// maxEnd > 13 ? 14 :
|
|
|
|
// 9;
|
|
|
|
// maxEnd > 11 ? 13 :
|
|
|
|
const timeStart = minStart < 9 ? 7 : 9;
|
|
|
|
// maxEnd > 9 ? 11 :
|
|
|
|
const timeEnd = maxEnd > 18 ? 20 : 18;
|
|
|
|
// 9;
|
|
|
|
|
|
|
|
const timeStart = minStart < 9 ? 7 : 9
|
|
|
|
|
|
|
|
const timeEnd = maxEnd > 18 ? 20 : 18
|
|
|
|
const daySizes = Object.entries(dayIntervalLayout).map(([index, layout]) => Math.max(1, layout.length));
|
|
|
|
|
|
|
|
const dayOffsets = daySizes.map((v, i) => {
|
|
|
|
const daySizes = Object.entries(dayIntervalLayout).map(([index, layout]) =>
|
|
|
|
let sum = 0;
|
|
|
|
Math.max(1, layout.length)
|
|
|
|
for(let j = 0; j < i; j++) {
|
|
|
|
)
|
|
|
|
sum += daySizes[j];
|
|
|
|
const dayOffsets = daySizes.map((v, i) => {
|
|
|
|
}
|
|
|
|
let sum = 0
|
|
|
|
return sum;
|
|
|
|
for (let j = 0; j < i; j++) {
|
|
|
|
});
|
|
|
|
sum += daySizes[j]
|
|
|
|
const daysLength = daySizes[4] + dayOffsets[4];
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const daysLength = daySizes[4] + dayOffsets[4]
|
|
|
|
|
|
|
|
|
|
|
|
const [currentlyHovered, setCurrentlyHovered] = useState(null)
|
|
|
|
const [currentlyHovered, setCurrentlyHovered] = useState(null)
|
|
|
|
const element = useRef()
|
|
|
|
const element = useRef()
|
|
|
@ -111,56 +113,76 @@ export const WorkWeekGrid = ({ events, selection, setSelection, hideOtherCourses
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div class="work-week-grid-view" ref={element}>
|
|
|
|
<div class="work-week-grid-view" ref={element}>
|
|
|
|
<div class="grid" style={{'--days-length': daysLength, '--time-length': timeEnd - timeStart}}>
|
|
|
|
<div
|
|
|
|
{[7, 9, 11, 14, 16, 18].map(n =>
|
|
|
|
class="grid"
|
|
|
|
<>
|
|
|
|
style={{ '--days-length': daysLength, '--time-length': timeEnd - timeStart }}
|
|
|
|
{n + 2 > timeStart && n < timeEnd && (
|
|
|
|
>
|
|
|
|
<div class="time" style={{'--offset': n - timeStart + 2}}>{n}-{n+2}</div>
|
|
|
|
{[7, 9, 11, 14, 16, 18].map(n => (
|
|
|
|
)}
|
|
|
|
<>
|
|
|
|
</>
|
|
|
|
{n + 2 > timeStart && n < timeEnd && (
|
|
|
|
)}
|
|
|
|
<div class="time" style={{ '--offset': n - timeStart + 2 }}>
|
|
|
|
<div class="vline" style="--offset: 2"></div>
|
|
|
|
{n}-{n + 2}
|
|
|
|
{[9, 11, 13, 14, 16, 18].map(n =>
|
|
|
|
</div>
|
|
|
|
<>
|
|
|
|
)}
|
|
|
|
{n > timeStart && n < timeEnd && (
|
|
|
|
</>
|
|
|
|
<div class="vline" style={{'--offset': n - timeStart + 2}}></div>
|
|
|
|
))}
|
|
|
|
)}
|
|
|
|
<div class="vline" style="--offset: 2"></div>
|
|
|
|
</>
|
|
|
|
{[9, 11, 13, 14, 16, 18].map(n => (
|
|
|
|
)}
|
|
|
|
<>
|
|
|
|
|
|
|
|
{n > timeStart && n < timeEnd && (
|
|
|
|
<div class="day-name" style={{'--line': 2 + dayOffsets[0]}}>Lun</div>
|
|
|
|
<div class="vline" style={{ '--offset': n - timeStart + 2 }}></div>
|
|
|
|
<div class="day-name" style={{'--line': 2 + dayOffsets[1]}}>Mar</div>
|
|
|
|
)}
|
|
|
|
<div class="day-name" style={{'--line': 2 + dayOffsets[2]}}>Mer</div>
|
|
|
|
</>
|
|
|
|
<div class="day-name" style={{'--line': 2 + dayOffsets[3]}}>Gio</div>
|
|
|
|
))}
|
|
|
|
<div class="day-name" style={{'--line': 2 + dayOffsets[4]}}>Ven</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="day-name" style={{ '--line': 2 + dayOffsets[0] }}>
|
|
|
|
<div class="hline" style={{'--line': 2 + dayOffsets[0]}}></div>
|
|
|
|
Lun
|
|
|
|
<div class="hline" style={{'--line': 2 + dayOffsets[1]}}></div>
|
|
|
|
</div>
|
|
|
|
<div class="hline" style={{'--line': 2 + dayOffsets[2]}}></div>
|
|
|
|
<div class="day-name" style={{ '--line': 2 + dayOffsets[1] }}>
|
|
|
|
<div class="hline" style={{'--line': 2 + dayOffsets[3]}}></div>
|
|
|
|
Mar
|
|
|
|
<div class="hline" style={{'--line': 2 + dayOffsets[4]}}></div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="day-name" style={{ '--line': 2 + dayOffsets[2] }}>
|
|
|
|
{Object.entries(dayIntervalLayout).map(([index, layout]) => (
|
|
|
|
Mer
|
|
|
|
<>
|
|
|
|
</div>
|
|
|
|
{layout.map((events, stackIndex) => (
|
|
|
|
<div class="day-name" style={{ '--line': 2 + dayOffsets[3] }}>
|
|
|
|
<>
|
|
|
|
Gio
|
|
|
|
{events.map(event => (
|
|
|
|
</div>
|
|
|
|
<div class={
|
|
|
|
<div class="day-name" style={{ '--line': 2 + dayOffsets[4] }}>
|
|
|
|
'event' +
|
|
|
|
Ven
|
|
|
|
(currentlyHovered === event.data.id
|
|
|
|
</div>
|
|
|
|
? ' highlight'
|
|
|
|
|
|
|
|
: '') +
|
|
|
|
<div class="hline" style={{ '--line': 2 + dayOffsets[0] }}></div>
|
|
|
|
(selectionSet.has(event.data.id) ? ' selected' : '')
|
|
|
|
<div class="hline" style={{ '--line': 2 + dayOffsets[1] }}></div>
|
|
|
|
}
|
|
|
|
<div class="hline" style={{ '--line': 2 + dayOffsets[2] }}></div>
|
|
|
|
|
|
|
|
<div class="hline" style={{ '--line': 2 + dayOffsets[3] }}></div>
|
|
|
|
|
|
|
|
<div class="hline" style={{ '--line': 2 + dayOffsets[4] }}></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{Object.entries(dayIntervalLayout).map(([index, layout]) => (
|
|
|
|
|
|
|
|
<>
|
|
|
|
|
|
|
|
{layout.map((events, stackIndex) => (
|
|
|
|
|
|
|
|
<>
|
|
|
|
|
|
|
|
{events.map(event => (
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
class={
|
|
|
|
|
|
|
|
'event' +
|
|
|
|
|
|
|
|
(currentlyHovered === event.data.id
|
|
|
|
|
|
|
|
? ' highlight'
|
|
|
|
|
|
|
|
: '') +
|
|
|
|
|
|
|
|
(selectionSet.has(event.data.id) ? ' selected' : '')
|
|
|
|
|
|
|
|
}
|
|
|
|
data-event-id={event.data.id}
|
|
|
|
data-event-id={event.data.id}
|
|
|
|
style={{
|
|
|
|
style={{
|
|
|
|
'--line': 2 + dayOffsets[index-1] + stackIndex,
|
|
|
|
'--line': 2 + dayOffsets[index - 1] + stackIndex,
|
|
|
|
'--offset': event.start / 60 - timeStart + 2,
|
|
|
|
'--offset': event.start / 60 - timeStart + 2,
|
|
|
|
'--length': (event.end - event.start) / 60,
|
|
|
|
'--length': (event.end - event.start) / 60,
|
|
|
|
'--color': `var(--bubble-${colors[event.data.id][0]})`,
|
|
|
|
'--color': `var(--bubble-${colors[event.data.id][0]})`,
|
|
|
|
'--border-color': `var(--bubble-border-${colors[event.data.id][0]})`,
|
|
|
|
'--border-color': `var(--bubble-border-${
|
|
|
|
'--highlight-color': `var(--bubble-highlight-${colors[event.data.id][0]})`
|
|
|
|
colors[event.data.id][0]
|
|
|
|
}}
|
|
|
|
})`,
|
|
|
|
|
|
|
|
'--highlight-color': `var(--bubble-highlight-${
|
|
|
|
|
|
|
|
colors[event.data.id][0]
|
|
|
|
|
|
|
|
})`,
|
|
|
|
|
|
|
|
}}
|
|
|
|
onClick={() => {
|
|
|
|
onClick={() => {
|
|
|
|
if (!selectionSet.has(event.data.id))
|
|
|
|
if (!selectionSet.has(event.data.id))
|
|
|
|
setSelection([...selection, event.data.id])
|
|
|
|
setSelection([...selection, event.data.id])
|
|
|
@ -169,32 +191,36 @@ export const WorkWeekGrid = ({ events, selection, setSelection, hideOtherCourses
|
|
|
|
selection.filter(id => event.data.id !== id)
|
|
|
|
selection.filter(id => event.data.id !== id)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{colors[event.data.id][1] !== '' && (
|
|
|
|
{colors[event.data.id][1] !== '' && (
|
|
|
|
<div className="distinguisher">{`(${colors[event.data.id][1]})`}</div>
|
|
|
|
<div className="distinguisher">{`(${
|
|
|
|
)}
|
|
|
|
colors[event.data.id][1]
|
|
|
|
{event.data.aula}</div>
|
|
|
|
})`}</div>
|
|
|
|
))}
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
{event.data.aula}
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
))}
|
|
|
|
))}
|
|
|
|
</>
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
<div class="legend">
|
|
|
|
</>
|
|
|
|
{courses.map(course => (
|
|
|
|
))}
|
|
|
|
<>
|
|
|
|
</div>
|
|
|
|
<div class="color"
|
|
|
|
<div class="legend">
|
|
|
|
style={{
|
|
|
|
{courses.map(course => (
|
|
|
|
'--color': `var(--bubble-${colors[course.id][0]})`,
|
|
|
|
<>
|
|
|
|
'--border-color': `var(--bubble-border-${colors[course.id][0]})`
|
|
|
|
<div
|
|
|
|
}}
|
|
|
|
class="color"
|
|
|
|
>
|
|
|
|
style={{
|
|
|
|
{colors[course.id][1]}
|
|
|
|
'--color': `var(--bubble-${colors[course.id][0]})`,
|
|
|
|
</div>
|
|
|
|
'--border-color': `var(--bubble-border-${colors[course.id][0]})`,
|
|
|
|
<div class="name">{normalizeCourseName(course.name)}</div>
|
|
|
|
}}
|
|
|
|
</>
|
|
|
|
>
|
|
|
|
))}
|
|
|
|
{colors[course.id][1]}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="name">{normalizeCourseName(course.name)}</div>
|
|
|
|
|
|
|
|
</>
|
|
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|