Skip to content

Commit

Permalink
Merge pull request #60 from DevKor-github/fix/timetable-ux
Browse files Browse the repository at this point in the history
Fix/timetable ux
  • Loading branch information
halionaz authored Sep 23, 2024
2 parents a2a6bb1 + 805ccca commit 420cc6c
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 50 deletions.
15 changes: 9 additions & 6 deletions src/api/hooks/timetable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,18 @@ export const useGetUserTimetableList = () => {
return useQuery({
queryKey: ['timetableList'],
queryFn: getTimetableByUser,
initialData: [],
})
}

const INITIAL_TIMETABLE: GetTimetableByTimetableIdResponse = {
courses: [],
schedules: [],
color: 'Red',
}

const getTimetableByID = async ({ timetableId }: GetTimetableByTimetableIdRequest) => {
if (timetableId === -1) return INITIAL_TIMETABLE

const response = await apiInterface.get<GetTimetableByTimetableIdResponse>(`/timetable/${timetableId}`)
return response.data
}
Expand All @@ -42,11 +49,7 @@ export const useGetTimetable = ({ timetableId }: GetTimetableByTimetableIdReques
return useQuery({
queryKey: ['timetable', timetableId],
queryFn: () => getTimetableByID({ timetableId }),
initialData: {
courses: [],
schedules: [],
color: 'Red',
},
initialData: INITIAL_TIMETABLE,
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/home/Announcement/InsituteProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const InstituteProfile = ({ img, name, url }: InstituteProfileProps) => {
})}
onMouseEnter={() => setOnMouse(true)}
onMouseLeave={() => setOnMouse(false)}
onClick={() => window.open(url, '_blank')}
onClick={() => window.open(url, '_blank', 'noopener,noreferrer')}
>
<img
src={img}
Expand Down
20 changes: 10 additions & 10 deletions src/components/timetable/Button/CreateTimetableBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@ import { css } from '@styled-system/css'
import { Plus } from 'lucide-react'

interface CreateTimetableBtnProps {
createTimetable: () => void
handleCreate: () => void
}
const CreateTimetableBtn = ({ createTimetable }: CreateTimetableBtnProps) => {
const CreateTimetableBtn = ({ handleCreate }: CreateTimetableBtnProps) => {
return (
<button
onClick={createTimetable}
onClick={handleCreate}
className={css({
h: 9,
w: 9,
cursor: 'pointer',
bgColor: 'red.2',
display: { base: 'flex', mdDown: 'none' },
justifyContent: 'center',
alignItems: 'center',
rounded: 10,
color: 'white',
overflow: 'hidden',
position: 'relative',
transition: 'box-shadow 0.256s',
transition: 'box-shadow 0.2s',
h: '30px',
w: '30px',
bgColor: 'lightGray.1',
rounded: 'full',
_hover: {
boxShadow: '0px 0px 4px rgba(231, 0, 0, 0.70)',
boxShadow: '0px 2px 6px 0px rgba(0, 0, 0, 0.25) inset',
},
})}
>
Expand All @@ -36,7 +36,7 @@ const CreateTimetableBtn = ({ createTimetable }: CreateTimetableBtnProps) => {
zIndex: 1,
})}
/>
<Plus className={css({ zIndex: 2 })} />
<Plus className={css({ zIndex: 2 })} size={16} strokeWidth={3} />
</button>
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/timetable/Grid/LectureSticker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const LectureSticker = ({ timetableId, data, bgColor, isMine }: LectureStickerPr
const { mutate: deleteSchedule } = useDeleteSchedule()

const handleCoursePlanClick = useCallback(() => {
window.open(syllabus!, 'rel=noopener noreferrer')
window.open(syllabus!, '_blank', 'noopener,noreferrer')
setIsModalOpen(false)
setIsSheetOpened(true)
}, [syllabus, setIsSheetOpened])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ interface ClassSelectModalProps {
category: 'All Class' | 'Major' | 'General Studies' | 'Academic Foundations'
handleMajorBtn: (classification: string) => void
handleQuitModal: () => void
curClassification: string | null
}
const ClassSelectModal = ({ category, handleMajorBtn, handleQuitModal }: ClassSelectModalProps) => {
const ClassSelectModal = ({ category, handleMajorBtn, handleQuitModal, curClassification }: ClassSelectModalProps) => {
return (
<div // eslint-disable-line
className={css({
Expand Down Expand Up @@ -50,6 +51,7 @@ const ClassSelectModal = ({ category, handleMajorBtn, handleQuitModal }: ClassSe
majors={majors}
handleMajorBtn={handleMajorBtn}
isAcademicFoundation={category === 'Academic Foundations'}
curClassification={curClassification}
/>
))}
</ul>
Expand Down
27 changes: 20 additions & 7 deletions src/components/timetable/LectureBottomSheet/AddClass/MajorList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { css, cva } from '@styled-system/css'
import { motion, Variants } from 'framer-motion'
import { ChevronRight } from 'lucide-react'
import { ChevronRight, Dot } from 'lucide-react'
import { useState } from 'react'

const CollegeCategoryStyle = cva({
Expand All @@ -16,13 +16,24 @@ const CollegeCategoryStyle = cva({
fontSize: 16,
fontWeight: 500,
cursor: 'pointer',
transition: 'background 0.256s, color 0.256s',
transition: 'background 0.2s, color 0.2s, border 0.2s',
},
variants: {
isOpen: {
true: {
bgColor: 'lightGray.1',
color: 'bg.gray',
bgColor: 'lightGray.2',
},
},
childCategory: {
true: {
bgColor: 'white',
},
},
isSelected: {
true: {
bgColor: 'darkGray.2',
borderColor: 'darkGray.2',
color: 'white',
},
},
},
Expand All @@ -42,16 +53,17 @@ interface MajorListProps {
majors: string[]
handleMajorBtn: (classification: string) => void
isAcademicFoundation: boolean
curClassification: string | null
}

const MajorList = ({ college, majors, handleMajorBtn, isAcademicFoundation }: MajorListProps) => {
const MajorList = ({ college, majors, handleMajorBtn, isAcademicFoundation, curClassification }: MajorListProps) => {
const [isOpen, setIsOpen] = useState(false)

return (
<>
<button
key={college}
className={CollegeCategoryStyle({ isOpen })}
className={CollegeCategoryStyle({ isOpen, isSelected: isAcademicFoundation && curClassification === college })}
onClick={event => {
event.stopPropagation()
if (isAcademicFoundation) {
Expand Down Expand Up @@ -84,7 +96,7 @@ const MajorList = ({ college, majors, handleMajorBtn, isAcademicFoundation }: Ma
// 모션 좀 손보기
<motion.button
key={ind}
className={CollegeCategoryStyle()}
className={CollegeCategoryStyle({ childCategory: true, isSelected: curClassification === major })}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
onClick={event => {
Expand All @@ -99,6 +111,7 @@ const MajorList = ({ college, majors, handleMajorBtn, isAcademicFoundation }: Ma
overflow: 'hidden',
})}
>
<Dot />
{major}
</span>
</motion.button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ const AddClass = ({ timetableId }: AddClassProps) => {

const handleDropdown = useCallback(
(toIndex: number) => {
setCurClassification(null)
setCurCategory(toIndex)
if (toIndex === 1 || toIndex === 3) {
// Major or Academic Foundation
setIsModalOpen(true)
} else {
setCurClassification(null)
setIsSearchAvailable(true)
if (toIndex === 0) {
// All
Expand Down Expand Up @@ -252,6 +252,7 @@ const AddClass = ({ timetableId }: AddClassProps) => {
category={categoryList[curCategory]}
handleMajorBtn={handleMajorBtn}
handleQuitModal={handleQuitModal}
curClassification={curClassification}
/>,
document.body,
)}
Expand Down
1 change: 1 addition & 0 deletions src/components/timetable/LectureBottomSheet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface LectureBottomSheetProps {
const LectureBottomSheet = ({ timetableId, visible }: LectureBottomSheetProps) => {
const [isOpen, setIsOpen] = useState(false)
const [sheetState, setSheetState] = useState<'class' | 'schedule' | null>(null)

const { mutate: postSchedule } = usePostSchedule()

const handleDrawer = useCallback(
Expand Down
6 changes: 3 additions & 3 deletions src/components/timetable/StatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const StatusBar = ({ curSemester, curIndex, setCurIndex }: StatusBarProps) => {

const curSemesterTimetableLen = curSemester.timetables.length

const handleCreateTimetableBtn = useCallback(() => {
const handleCreateTimetable = useCallback(() => {
createTimetable(
{
timetableName: `timetable ${curSemesterTimetableLen + 1}`,
Expand All @@ -46,8 +46,7 @@ const StatusBar = ({ curSemester, curIndex, setCurIndex }: StatusBarProps) => {
})}
>
<div className={css({ display: 'flex', flexDir: 'row', gap: 5, alignItems: 'center' })}>
<CreateTimetableBtn createTimetable={handleCreateTimetableBtn} />
<div className={css({ display: 'flex', flexDir: 'row', gap: 2.5 })}>
<div className={css({ display: 'flex', flexDir: 'row', gap: 2.5, alignItems: 'center' })}>
{curSemester.timetables.map((timetable, index) => {
return (
<SelectTimetableBtn
Expand All @@ -59,6 +58,7 @@ const StatusBar = ({ curSemester, curIndex, setCurIndex }: StatusBarProps) => {
/>
)
})}
<CreateTimetableBtn handleCreate={handleCreateTimetable} />
</div>
</div>
<MainPinBtn
Expand Down
7 changes: 2 additions & 5 deletions src/components/timetable/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { css, cva } from '@styled-system/css'
import { useAtom } from 'jotai/react'
import { useSetAtom } from 'jotai/react'
import { Ellipsis } from 'lucide-react'
import { forwardRef, useCallback, useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'

import TimetableLayout from '@/components/timetable/Grid/TimetableLayout'
import LectureBottomSheet from '@/components/timetable/LectureBottomSheet'
import OptionModal from '@/components/timetable/Modal/OptionModal'
import { isBottomSheetVisible } from '@/lib/store/bottomSheet'
import { GlobalModalStateType, TimetableInfo } from '@/types/timetable'
Expand Down Expand Up @@ -38,7 +36,7 @@ interface TimetableProps {
const Timetable = forwardRef<HTMLDivElement, TimetableProps>(
({ timetable: { timetableId, timetableName, year, semester }, deleteTimetableHandler }, ref) => {
const [isModalOpen, setIsModalOpen] = useState(false)
const [isSheetVisible, setIsSheetVisible] = useAtom(isBottomSheetVisible)
const setIsSheetVisible = useSetAtom(isBottomSheetVisible)
const [globalModalState, setGlobalModalState] = useState<GlobalModalStateType>(null)
const modalRef = useRef<HTMLDivElement>(null)

Expand Down Expand Up @@ -155,7 +153,6 @@ const Timetable = forwardRef<HTMLDivElement, TimetableProps>(
deleteTimetableHandler={deleteTimetableHandler}
timetableName={timetableName}
/>
{createPortal(<LectureBottomSheet timetableId={timetableId} visible={isSheetVisible} />, document.body)}
</div>
)
},
Expand Down
48 changes: 34 additions & 14 deletions src/pages/TimetablePage/MyTimetablePage.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { css } from '@styled-system/css'
import { useCallback, useRef, useState } from 'react'
import { useAtomValue } from 'jotai'
import { useCallback, useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'

import { useDeleteTimetable, useGetUserTimetableList } from '@/api/hooks/timetable'
import { useDeleteTimetable, useGetUserTimetableList, usePostTimetable } from '@/api/hooks/timetable'
import Timetable from '@/components/timetable'
import ShareBtn from '@/components/timetable/Button/ShareBtn'
import Dropdown from '@/components/timetable/Dropdown'
import NullTimetable from '@/components/timetable/NullTimetable'
import LectureBottomSheet from '@/components/timetable/LectureBottomSheet'
import StatusBar from '@/components/timetable/StatusBar'
import { isBottomSheetVisible } from '@/lib/store/bottomSheet'
import { convertHtmlToImage, makeSemesterDropdownList, timetablePreprocess } from '@/util/timetableUtil'

const MyTimetablePage = () => {
const { data: timetableList } = useGetUserTimetableList()
const { data: timetableList, isLoading } = useGetUserTimetableList()
const { mutate: deleteTimetable } = useDeleteTimetable()
const { mutate: createTimetable } = usePostTimetable()
const isCreating = useRef(false)

const imgRef = useRef<HTMLDivElement>(null)
const [curSemester, setCurSemester] = useState(2)
const [curIndex, setCurIndex] = useState(0)

const isSheetVisible = useAtomValue(isBottomSheetVisible)

const semesterList = timetablePreprocess(timetableList)

const setSemesterIndex = useCallback(
Expand All @@ -42,6 +49,20 @@ const MyTimetablePage = () => {
[setCurIndex, deleteTimetable, curIndex],
)

useEffect(() => {
if (!isLoading && semesterList[curSemester].isSkeleton && !isCreating.current) {
isCreating.current = true
createTimetable({
timetableName: 'timetable 1',
semester: semesterList[curSemester].semester,
year: semesterList[curSemester].year,
})
}
if (!semesterList[curSemester].isSkeleton) {
isCreating.current = false
}
}, [isLoading, createTimetable, semesterList, curSemester])

return (
<>
<div className={css({ display: 'flex', flexDir: 'row', justifyContent: 'space-between', my: 11 })}>
Expand All @@ -60,21 +81,20 @@ const MyTimetablePage = () => {
</div>
</div>
<StatusBar curSemester={semesterList[curSemester]} curIndex={curIndex} setCurIndex={setTimetableIndex} />
{semesterList[curSemester].timetables.length === 0 ? (
<NullTimetable
children={
<>
There is no set timetable <br /> Press the plus button to create a timetable!
</>
}
/>
) : (
<>
<Timetable
ref={imgRef}
timetable={semesterList[curSemester].timetables[curIndex]}
deleteTimetableHandler={deleteTimetableHandler}
/>
)}
{createPortal(
<LectureBottomSheet
timetableId={semesterList[curSemester].timetables[curIndex].timetableId}
visible={isSheetVisible}
/>,
document.body,
)}
</>
</>
)
}
Expand Down
20 changes: 19 additions & 1 deletion src/util/timetableUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,25 @@ export const timetablePreprocess = (data: TimetableInfo[] | undefined) => {
}
})

return ret
return ret.map(semester => {
if (semester.timetables.length === 0) {
// Skeleton
return {
...semester,
timetables: [
{
timetableId: -1,
semester: semester.semester,
year: semester.year,
mainTimetable: true,
timetableName: 'timetable 1',
},
],
isSkeleton: true,
}
}
return { ...semester, isSkeleton: false }
})
}

/**
Expand Down

0 comments on commit 420cc6c

Please sign in to comment.