Skip to content

Commit

Permalink
Merge pull request #266 from NIAEFEUP/feature/order-classes-in-mobile
Browse files Browse the repository at this point in the history
feat: slot boxes are now ordered on mobile and smaller devices
  • Loading branch information
tomaspalma committed Aug 28, 2024
2 parents 35e1ded + 3395f70 commit 7ea76ae
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 71 deletions.
2 changes: 1 addition & 1 deletion src/@types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export type CourseOption = {
export type ClassDescriptor = {
classInfo: ClassInfo
courseInfo: CourseInfo
slotInfo?: SlotInfo
slotInfo?: SlotInfo // used for conflict calculation
}

export type ConflictInfo = {
Expand Down
50 changes: 23 additions & 27 deletions src/components/planner/Schedule.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import '../../styles/schedule.css'
import classNames from 'classnames'
import { useEffect, useMemo, useRef, useState } from 'react'
import { ScheduleGrid, } from './schedules'
import { LessonBox, ScheduleGrid, } from './schedules'
import ToggleScheduleGrid from './schedule/ToggleScheduleGrid'
import PrintSchedule from './schedule/PrintSchedule'
import { useContext } from 'react'
import ClassBox from './schedules/ClassBox'
import SlotBox from './schedules/SlotBox'
import ScheduleTypes from './ScheduleType'
import { ClassDescriptor } from '../../@types'
import { ClassDescriptor, SlotInfo } from '../../@types'
import CourseContext from '../../contexts/CourseContext'
import MultipleOptionsContext from '../../contexts/MultipleOptionsContext'
import { useShowGrid } from '../../hooks'
import { maxHour, minHour, convertWeekdayLong, convertHour } from '../../utils'
import SlotBoxes from './schedules/SlotBoxes'

const dayValues = Array.from({ length: 6 }, (_, i) => i)
const hourValues = Array.from({ length: maxHour - minHour + 1 }, (_, i) => minHour + i)
Expand All @@ -21,6 +22,7 @@ const Schedule = () => {
const { multipleOptions, selectedOption } = useContext(MultipleOptionsContext)

const [classes, setClasses] = useState<ClassDescriptor[]>([])
const [slots, setSlots] = useState<SlotInfo[]>([])
const scheduleRef = useRef(null)

useEffect(() => {
Expand All @@ -43,6 +45,7 @@ const Schedule = () => {
}

setClasses(newClasses)
setSlots(newClasses.map((newClass) => newClass.classInfo.slots).flat())
}, [multipleOptions, pickedCourses, selectedOption])

// TODO: Improvements by functional programming
Expand All @@ -60,6 +63,12 @@ const Schedule = () => {
return Array.from(aux) as string[]
}, [classes])

const slotsOrderedByDay = (slots: Array<SlotInfo>): Array<SlotInfo> => {
return slots.sort((slot1, slot2) => (
slot1.day - slot2.day
));
}

// Bottom Bar Configurations
const [hiddenLessonsTypes, setHiddenLessonsTypes] = useState<string[]>([])
const [showGrid, setShowGrid] = useShowGrid()
Expand Down Expand Up @@ -93,23 +102,16 @@ const Schedule = () => {
<div className={classNames('schedule-grid-wrapper', showGrid ? 'show-grid-yes' : 'show-grid-no')}>
<ScheduleGrid showGrid={showGrid} />
<div className="schedule-classes">
{classes
.filter((c) => c.classInfo !== undefined)
.map((c) => (
<ClassBox
key={`course[${c.courseInfo.id}]-class[${c.classInfo.id}]`}
courseInfo={c.courseInfo}
classInfo={c.classInfo ?? null}
classes={classes}
hiddenLessonsTypes={hiddenLessonsTypes}
/>
))}
<SlotBoxes
slots={slots}
hiddenLessonsTypes={hiddenLessonsTypes}
classes={classes}
/>
</div>
</div>
</div>
</div>


{/* Bottom bar */}
<div className="flex justify-between gap-5 pl-16">
<div className="flex flex-wrap gap-4 gap-y-1 text-sm text-gray-600 dark:text-white 2xl:gap-y-2 2xl:text-base">
Expand All @@ -127,18 +129,12 @@ const Schedule = () => {
<div className="flex w-full items-center justify-start gap-2" key={`responsive-lesson-row-${""}`}>
<div className="h-full w-1 rounded bg-primary" />
<div className="flex w-full flex-row flex-wrap items-center justify-start gap-2">
{classes
.filter((c) => c.classInfo !== undefined)
.map((c) => (
<ClassBox
key={`course[${c.courseInfo.id}]-class[${c.classInfo.id}]`}
courseInfo={c.courseInfo}
classInfo={c.classInfo ?? null}
classes={classes}
hiddenLessonsTypes={hiddenLessonsTypes}
/>
))}
{classes.length === 0 && <p>Ainda não foram selecionadas turmas!</p>}
{slots.length === 0 && <p>Ainda não foram selecionadas turmas!</p>}
<SlotBoxes
slots={slotsOrderedByDay(slots)}
classes={classes}
hiddenLessonsTypes={hiddenLessonsTypes}
/>
</div>
</div>
</div>
Expand Down
43 changes: 0 additions & 43 deletions src/components/planner/schedules/ClassBox.tsx

This file was deleted.

37 changes: 37 additions & 0 deletions src/components/planner/schedules/SlotBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { CourseInfo, ClassInfo, ClassDescriptor, SlotInfo } from '../../../@types'
import LessonBox from './LessonBox'
import ResponsiveLessonBox from './ResponsiveLessonBox'

type Props = {
courseInfo: CourseInfo
classInfo: ClassInfo
slot: SlotInfo
classes: ClassDescriptor[]
}

const SlotBox = ({ courseInfo, classInfo, classes, slot }: Props) => {
return (
<>
<div className="hidden lg:flex lg:flex-col">
<LessonBox
key={`course[${courseInfo.id}]-class[${classInfo.id}]-${slot.lesson_type}-${slot.id}`}
courseInfo={courseInfo}
classInfo={classInfo}
slotInfo={slot}
classes={classes.filter((classDescriptor) => classDescriptor.classInfo.id !== classInfo.id)}
/>
</div>

<div className="lg:hidden flex flex-col ">
<ResponsiveLessonBox
key={`course[${courseInfo.id}]-class[${classInfo.id}]-${slot.lesson_type}-${slot.id}`}
courseInfo={courseInfo}
classInfo={classInfo}
slotInfo={slot}
/>
</div>
</>
)
}

export default SlotBox;
35 changes: 35 additions & 0 deletions src/components/planner/schedules/SlotBoxes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ClassDescriptor, SlotInfo } from "../../../@types"
import SlotBox from "./SlotBox"

type Props = {
slots: Array<SlotInfo>
classes: Array<ClassDescriptor>
hiddenLessonsTypes: Array<string>
}

const SlotBoxes = ({ slots, classes, hiddenLessonsTypes }: Props) => {
const filteredSlots = slots.filter((slot: SlotInfo) => !hiddenLessonsTypes.includes(slot.lesson_type));

return (
<>
{
filteredSlots.map((slot: SlotInfo) => {
const classDescriptor = classes.find((classDescriptor) => (
classDescriptor.classInfo.slots.filter((otherSlot) => otherSlot.id === slot.id).length > 0
))

if (!classDescriptor) return <></>;

return <SlotBox
courseInfo={classDescriptor.courseInfo}
classInfo={classDescriptor.classInfo}
classes={classes}
slot={slot}
/>
})
}
</>
);
}

export default SlotBoxes;

0 comments on commit 7ea76ae

Please sign in to comment.