Skip to content

Commit

Permalink
Merge pull request #254 from NIAEFEUP/ui/little-improvements
Browse files Browse the repository at this point in the history
UI improvements, fix bug and add redirect on /
  • Loading branch information
thePeras committed Aug 24, 2024
2 parents 9b7ab57 + 976708f commit ab86239
Show file tree
Hide file tree
Showing 21 changed files with 100 additions and 100 deletions.
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const pages = [
]

const redirects = [
{ from: "/", to: getPath(config.paths.planner) },
{ from: config.pathPrefix, to: getPath(config.paths.planner) },
{ from: config.pathPrefix.slice(0, -1), to: getPath(config.paths.planner) },
{ from: getPath(config.paths.home), to: getPath(config.paths.about) },
Expand Down
5 changes: 2 additions & 3 deletions src/api/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,12 @@ const createCourseClass = async (course: CourseInfo) => {
const getCoursesClasses = async (courses: CourseInfo[]): Promise<CourseInfo[]> => {
const newCourses = [...courses];

Promise.all(newCourses.map(course => createCourseClass(course))).then((values) => {
return Promise.all(newCourses.map(course => createCourseClass(course))).then(() => {
return newCourses;
}).catch((e) => {
console.error(e);
return []
})

return newCourses;
}

/**
Expand Down
22 changes: 11 additions & 11 deletions src/api/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,61 @@ const getMultipleOptionsStorage = (): MultipleOptions => {
const defaultValue = [
{
id: 0,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f60e.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0031-fe0f-20e3.png',
name: 'Horário 1',
course_options: [],
},
{
id: 1,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f929.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0032-fe0f-20e3.png',
name: 'Horário 2',
course_options: [],
},
{
id: 2,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f973.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0033-fe0f-20e3.png',
name: 'Horário 3',
course_options: [],
},
{
id: 3,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f9d0.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0034-fe0f-20e3.png',
name: 'Horário 4',
course_options: [],
},
{
id: 4,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f525.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0035-fe0f-20e3.png',
name: 'Horário 5',
course_options: [],
},
{
id: 5,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f483.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0036-fe0f-20e3.png',
name: 'Horário 6',
course_options: [],
},
{
id: 6,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f976.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0037-fe0f-20e3.png',
name: 'Horário 7',
course_options: [],
},
{
id: 7,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f47b.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0038-fe0f-20e3.png',
name: 'Horário 8',
course_options: [],
},
{
id: 8,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f425.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/0039-fe0f-20e3.png',
name: 'Horário 9',
course_options: [],
},
{
id: 9,
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1fae1.png',
icon: 'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f51f.png',
name: 'Horário 10',
course_options: [],
},
Expand Down Expand Up @@ -110,7 +110,7 @@ const setMultipleOptionsStorage = (multipleOptions: MultipleOptions) => {

const getSelectedOptionStorage = () => {
const key = 'niaefeup-tts.selected-option';

let selectedOption = parseInt(localStorage.getItem(key));
if (isNaN(selectedOption)) {
selectedOption = 0;
Expand Down
6 changes: 3 additions & 3 deletions src/components/planner/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext } from 'react'
import { useContext, useState } from 'react'
import SessionController from './sidebar/SessionController'
import OptionsController from './sidebar/OptionsController'
import SelectedOptionController from './sidebar/SelectedOptionController'
Expand All @@ -12,15 +12,15 @@ const Sidebar = () => {
const { multipleOptions, selectedOption } = useContext(MultipleOptionsContext);

return (
<div className="lg:min-h-adjusted order-2 col-span-12 flex min-h-min flex-col justify-between rounded bg-lightest px-3 py-3 dark:bg-dark lg:col-span-3 2xl:px-4 2xl:py-4">
<div className="lg:min-h-adjusted order-2 col-span-12 flex min-h-min flex-col justify-between rounded-md bg-lightest px-3 py-3 dark:bg-dark lg:col-span-3 2xl:px-4 2xl:py-4">
<div className="space-y-2">
<div className="relative flex flex-row flex-wrap items-center justify-center gap-x-2 gap-y-2 lg:justify-start">
<SessionController />
<OptionsController />
<SelectedOptionController
currentOption={multipleOptions[selectedOption].course_options}
/>
<CoursesController/>
<CoursesController />
</div>
</div>
</div>
Expand Down
11 changes: 6 additions & 5 deletions src/components/planner/schedules/LessonPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ type Props = {
isOpenHook: [boolean, React.Dispatch<React.SetStateAction<boolean>>]
}

const LessonPopover = ({
courseInfo,
classInfo,
slotInfo,
isOpenHook
const LessonPopover = ({
courseInfo,
classInfo,
slotInfo,
isOpenHook
}: Props) => {
const [isOpen, setIsOpen] = isOpenHook

Expand Down Expand Up @@ -68,6 +68,7 @@ const LessonPopover = ({
</div>

<footer className="flex justify-end">
{/* TODO: Change to shadcn button */}
<button
type="button"
onClick={closeModal}
Expand Down
13 changes: 11 additions & 2 deletions src/components/planner/sidebar/CoursesController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@ import { useContext } from 'react'
import ClassSelector from './CoursesController/ClassSelector'
import CourseContext from '../../../contexts/CourseContext'
import { NoMajorSelectedSVG } from '../../svgs'
import { Button } from '../../ui/button'

const CoursesController = () => {
const { pickedCourses } = useContext(CourseContext)
const { pickedCourses, setUcsModalOpen } = useContext(CourseContext)

const noCoursesPicked = pickedCourses.length === 0

return (
<div className={`flex ${noCoursesPicked ? 'h-max justify-center' : ''} w-full flex-col gap-4 px-0 py-2`}>
{noCoursesPicked ? (
<NoMajorSelectedSVG className="my-20 h-40 w-full" />
<div className="my-20 w-full flex flex-col items-center gap-3 justify-center mt-5">
<NoMajorSelectedSVG className="h-32" />
<div className="text-center text-md">
Ainda sem nenhuma unidade curricular selecionada
</div>
<Button variant="icon" className="flex-grow gap-2 bg-primary" title="Selecionar Unidades Curriculares" onClick={() => setUcsModalOpen(true)}>
<span>Selecionar</span>
</Button>
</div>
) : (
pickedCourses
.sort((course1, course2) => course1.id - course2.id) // Same order as Sigarra
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const ClassSelector = ({ course }: Props) => {

newMultipleOptions[selectedOption].course_options = newCourseOptions;
setMultipleOptions(newMultipleOptions);

setPreview(null);
}

Expand Down Expand Up @@ -197,7 +197,7 @@ const ClassSelector = ({ course }: Props) => {
size="sm"
className="w-full justify-between truncate bg-lightish text-xs font-normal tracking-tighter hover:bg-primary/75 hover:text-white dark:bg-darkish"
>
<span>{getClassDisplayText(course, selectedClassId)} </span>
<span className={`${selectedClassId === null ? "opacity-50" : ""}`}>{getClassDisplayText(course, selectedClassId)}</span>
{!courseOption?.locked && <ChevronUpDownIcon className="text-blackish h-6 w-6 dark:text-lightish" />}
</Button>
</DropdownMenuTrigger>
Expand Down
11 changes: 3 additions & 8 deletions src/components/planner/sidebar/OptionsController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ const OptionsController = () => {
animation={200}
delay={2}
multiDrag
//set cursor-grabbing when dragging
onStart={() => document.body.style.cursor = 'grabbing'}
//set cursor-grab when not dragging
onEnd={() => document.body.style.cursor = 'grab'}
>
{multipleOptions.map((option: Option) => (
<OptionButton
Expand Down Expand Up @@ -54,15 +50,14 @@ const OptionButton = ({ option, selectedOption, setSelectedOption }: Props) => {
}}
className={`
group relative box-border flex aspect-square h-10 w-15 cursor-pointer flex-col
items-center justify-center rounded border-2 border-transparent p-2
items-center justify-center rounded-md border-2 border-transparent p-2
dark:shadow hover:dark:border-primary/50
${selectedOption === option.id ? 'bg-primary/75 dark:bg-primary/50' : 'bg-lightish dark:bg-darkish'}
`}
>
<div
className={`absolute inset-x-0 top-0 text-transparent transition-colors duration-300 dark:group-hover:text-white ${
selectedOption === option.id ? 'group-hover:text-white' : 'group-hover:text-slate-700'
}`}
className={`absolute inset-x-0 top-0 text-transparent transition-colors duration-300 dark:group-hover:text-white ${selectedOption === option.id ? 'group-hover:text-white' : 'group-hover:text-slate-700'
}`}
>
<EllipsisHorizontalIcon className="m-auto h-5 w-5 cursor-grab" />
</div>
Expand Down
12 changes: 6 additions & 6 deletions src/components/planner/sidebar/SelectedOptionController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@ const SelectedOptionController = ({

//TODO(thePeras): Fix these functions using states and setInterval
const startScroll = () => {
if(inputIsActive()) return;
if (inputIsActive()) return;

isHovered = true
input.current.scrollLeft += 5
}

const stopScroll = () => {
if(inputIsActive()) return;
if (inputIsActive()) return;

isHovered = false
input.current.scrollLeft = 0
}

const scroll = () => {
if(inputIsActive()) return;
if (inputIsActive()) return;

if (isHovered) {
if (isScrollingBack) {
Expand All @@ -66,15 +66,15 @@ const SelectedOptionController = ({
return multipleOptions.find((elem) => elem.id === id)
}

const [optionName , setOptionName] = useState(multipleOptions.find((elem) => elem.id === selectedOption).name ?? '');
const [optionName, setOptionName] = useState(multipleOptions.find((elem) => elem.id === selectedOption).name ?? '');

useEffect(() => {
setOptionName(multipleOptions.find((elem) => elem.id === selectedOption).name)
}, [selectedOption, multipleOptions])

const renameOptionName = (event) => {
const newName = event.target.value;
if(newName.length > 35) return;
if (newName.length > 35) return;
event.target.value = newName
setMultipleOptions((prevMultipleOptions) => {
const updatedMultipleOptions = prevMultipleOptions.map((item) =>
Expand All @@ -97,7 +97,7 @@ const SelectedOptionController = ({
<div className="flex w-full flex-col sm:flex-row lg:flex-col xl:flex-row xl:content-between xl:gap-5">
<div className="order-2 flex flex-grow gap-2 sm:order-1 lg:order-2 xl:order-1">
<Popover open={emojiPickerOpen} onOpenChange={setEmojiPickerOpen}>
<PopoverTrigger className="aspect-square h-10 w-15 rounded p-1 px-2 text-xl hover:bg-lightish hover:dark:bg-darkish">
<PopoverTrigger className="aspect-square h-10 w-15 rounded-md p-1 px-2 text-xl bg-lightish dark:bg-darkish border border-slate-200 dark:border-slate-800">
<img
src={getOptionById(selectedOption)?.icon}
alt={multipleOptions[selectedOption].name}
Expand Down
31 changes: 13 additions & 18 deletions src/components/planner/sidebar/sessionController/CoursePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import { MajorSearchCombobox, CourseYearTabs, PickedCoursesList, Ects } from './course-picker'
import { PencilSquareIcon, TrashIcon } from '@heroicons//react/24/solid'
import { useContext, useEffect, useState } from 'react'
import { CheckIcon } from '@heroicons/react/24/outline'
import StorageAPI from '../../../../api/storage'
import CourseContext from '../../../../contexts/CourseContext'
import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
import { removeAllCourseOptions } from '../../../../utils'
import { Desert } from '../../../svgs'
import { Button } from '../../../ui/button'
import { DialogHeader, DialogFooter, Dialog, DialogClose, DialogContent, DialogDescription, DialogTitle, DialogTrigger } from '../../../ui/dialog'
import { DialogHeader, DialogFooter, Dialog, DialogContent, DialogDescription, DialogTitle, DialogTrigger } from '../../../ui/dialog'
import BackendAPI from '../../../../api/backend'
import { Separator } from '../../../ui/separator'
import useCourseUnits from '../../../../hooks/useCourseUnits'
import { CourseInfo, Major } from '../../../../@types'
import { Major } from '../../../../@types'
import { Skeleton } from '../../../ui/skeleton'
import { ClearAllCoursesButton } from './course-picker/ClearAllCoursesButton'

//TODO: absolute imports with @

const CoursePicker = () => {
const [open, setOpen] = useState(false)
const { pickedCourses, setPickedCourses, checkboxedCourses, setChoosingNewCourse, setCoursesInfo } = useContext(CourseContext)
const { pickedCourses, setPickedCourses, checkboxedCourses, setChoosingNewCourse, setCoursesInfo, ucsModalOpen, setUcsModalOpen } = useContext(CourseContext)

const [selectedMajor, setSelectedMajor] = useState<Major>(StorageAPI.getSelectedMajorStorage());
const { courseUnits, loading: loadingCourseUnits } = useCourseUnits(selectedMajor ? selectedMajor.id : null);
Expand All @@ -43,33 +39,32 @@ const CoursePicker = () => {
StorageAPI.setSelectedMajorStorage(selectedMajor);
}, [selectedMajor, setCoursesInfo])

const handleOpenChange = async () => {
const handleOpenChange = () => {
setChoosingNewCourse((prev) => !prev);
setOpen(!open)
if (open === false) return
if (ucsModalOpen === false) return
setUcsModalOpen(false)
}

return (
<Dialog open={open} onOpenChange={async () => { await handleOpenChange() }}>
<Dialog open={ucsModalOpen} onOpenChange={handleOpenChange}>
<DialogTrigger asChild>
<Button variant="icon" className="flex-grow gap-2 bg-primary" title="Editar Unidades Curriculares">
<span className="hidden md:block lg:hidden xl:block">Escolher UCs</span>
<Button variant="icon" className="flex-grow gap-2 bg-primary" title="Editar Unidades Curriculares" onClick={() => setUcsModalOpen(true)}>
<span className="hidden md:block lg:hidden xl:block">Unidades Curriculares</span>
<PencilSquareIcon className="h-5 w-5 text-white" />
</Button>
</DialogTrigger>
<DialogContent className="h-fit min-w-fit">
<DialogHeader>
<DialogTitle>Seleciona as tuas Unidades Curriculares</DialogTitle>
<DialogTitle>Seleciona as tuas unidades curriculares</DialogTitle>
<DialogDescription className="mt-2">
Escolhe um curso e unidades curriculares à esquerda. À direita aparecem as unidades curriculares que
escolheste.
Pesquisa pelas tuas unidades curriculares. As disciplinas selecionadas aparecem no lado direito.
</DialogDescription>
</DialogHeader>
<MajorSearchCombobox selectedMajor={selectedMajor} setSelectedMajor={setSelectedMajor} />
<Separator />
{showContent ? (
<>
<div className="grid w-[55rem] grid-cols-[1fr_3rem_1fr]">
<div className="grid w-[60rem] grid-cols-[1fr_2.5rem_1fr]">
{!loadingCourseUnits
? <CourseYearTabs />
: <div className="flex flex-col space-y-3">
Expand All @@ -88,7 +83,7 @@ const CoursePicker = () => {
</div>
<DialogFooter className="grid grid-cols-2">
<div />
<div className="flex items-center justify-between pr-4 dark:text-white">
<div className="flex items-center justify-between dark:text-white pr-4 pb-4">
<Ects />
<div className="flex gap-2">
<ClearAllCoursesButton />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CheckIcon, TrashIcon } from "@heroicons/react/24/outline"
import { CheckCircleIcon, TrashIcon } from "@heroicons/react/24/outline"
import { useContext } from "react"
import CourseContext from "../../../../../contexts/CourseContext"
import MultipleOptionsContext from "../../../../../contexts/MultipleOptionsContext"
Expand All @@ -17,15 +17,15 @@ export const ClearAllCoursesButton = () => {
removeAllCourseOptions(multipleOptions)
}}
variant="icon"
className="gap-2 bg-lightish text-darkish"
className="bg-lightish text-darkish gap-1.5"
>
<TrashIcon className="h-5 w-5" />
<span>Limpar</span>
</Button>
<DialogClose asChild>
<Button variant="icon" className="gap-2 bg-lightish text-darkish">
<CheckIcon className="h-5 w-5" />
<span>Pronto</span>
<Button variant="icon" className="bg-primary gap-1.5">
<CheckCircleIcon className="h-5 w-5" />
<p>Está feito</p>
</Button>
</DialogClose>
</>
Expand Down
Loading

0 comments on commit ab86239

Please sign in to comment.