From b9d3d05f313521aab7b8ea3b61c4a7c97e86e139 Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 18:05:26 +0300 Subject: [PATCH 01/13] refactor: added models and introduced proper types to some components --- src/api/getCurrentDateValues.ts | 7 +++-- src/api/schedule.ts | 10 ++++-- src/common/constants/theme.ts | 6 ++-- src/common/context/groupContext.tsx | 14 ++++----- src/common/context/lecturerContext.tsx | 19 +++++++----- src/common/context/preloadedListsContext.tsx | 14 ++++++--- src/common/utils/getApiFunction.ts | 32 ++++++++++---------- src/common/utils/getValueFromTheme.ts | 2 +- src/common/utils/parsedLocalStorage.ts | 15 +++++---- src/models/CurrentTime.ts | 5 +++ src/models/EntityWithNameAndId.ts | 4 +++ src/models/Exam.ts | 12 ++++++++ src/models/Group.ts | 5 +++ src/models/Lecturer.ts | 4 +++ src/models/LecturerLesson.ts | 4 +++ src/models/LecturerPair.ts | 5 +++ src/models/Lesson.ts | 8 +++++ src/models/PagedResponse.ts | 17 +++++++++++ src/models/Pair.ts | 9 ++++++ src/models/Schedule.ts | 6 ++++ src/models/StudentLesson.ts | 4 +++ src/models/StudentPair.ts | 6 ++++ src/types/ListOption.ts | 4 +++ src/types/Theme.ts | 1 + src/types/Week.ts | 1 + 25 files changed, 162 insertions(+), 52 deletions(-) create mode 100644 src/models/CurrentTime.ts create mode 100644 src/models/EntityWithNameAndId.ts create mode 100644 src/models/Exam.ts create mode 100644 src/models/Group.ts create mode 100644 src/models/Lecturer.ts create mode 100644 src/models/LecturerLesson.ts create mode 100644 src/models/LecturerPair.ts create mode 100644 src/models/Lesson.ts create mode 100644 src/models/PagedResponse.ts create mode 100644 src/models/Pair.ts create mode 100644 src/models/Schedule.ts create mode 100644 src/models/StudentLesson.ts create mode 100644 src/models/StudentPair.ts create mode 100644 src/types/ListOption.ts create mode 100644 src/types/Theme.ts create mode 100644 src/types/Week.ts diff --git a/src/api/getCurrentDateValues.ts b/src/api/getCurrentDateValues.ts index 0dbb151..a335d3a 100644 --- a/src/api/getCurrentDateValues.ts +++ b/src/api/getCurrentDateValues.ts @@ -1,6 +1,7 @@ +import { CurrentTime } from '../models/CurrentTime'; +import { PagedResponse } from '../models/PagedResponse'; import Http from './index'; -export const getCurrentDateValues = () => { - return Http.get('/time/current') - .then(res => res.data); +export const getCurrentDateValues = (): Promise> => { + return Http.get('/time/current').then(res => res.data); }; \ No newline at end of file diff --git a/src/api/schedule.ts b/src/api/schedule.ts index 0973f4e..ca75355 100644 --- a/src/api/schedule.ts +++ b/src/api/schedule.ts @@ -1,16 +1,20 @@ +import { Exam } from '../models/Exam'; +import { LecturerLesson } from '../models/LecturerLesson'; +import { PagedResponse } from '../models/PagedResponse'; +import { StudentLesson } from '../models/StudentLesson'; import Http from './index'; -export const getScheduleByLecturer = (lecturerId: string) => { +export const getScheduleByLecturer = (lecturerId: string): Promise> => { return Http.get('/schedule/lecturer?lecturerId=' + lecturerId) .then(res => res.data); } -export const getScheduleByGroup = (groupId: string) => { +export const getScheduleByGroup = (groupId: string): Promise> => { return Http.get('/schedule/lessons?groupId=' + groupId) .then(res => res.data); } -export const getExamsByGroup = (groupName: string) => { +export const getExamsByGroup = (groupName: string): Promise> => { return Http.get('/exams/group?groupId=' + groupName) .then(res => res.data); } \ No newline at end of file diff --git a/src/common/constants/theme.ts b/src/common/constants/theme.ts index 5b99988..eac8b66 100644 --- a/src/common/constants/theme.ts +++ b/src/common/constants/theme.ts @@ -1,4 +1,6 @@ -export const theme = { +import { Theme } from '../../types/Theme'; + +export const theme: Record = { light: { bgPrimary: 'linear-gradient(90deg, #FFEFF2 0%, #DBE9FE 100%)', bgHeader: 'linear-gradient(180deg, #FFFFFF 0%, rgba(255, 255, 255, 0.5) 100%)', @@ -23,4 +25,4 @@ export const theme = { currentDayContainer: 'linear-gradient(180deg, rgba(54, 54, 55, 0) 0%, rgba(54, 54, 55, 0.5) 10.73%, #363637 55%, rgba(54, 54, 55, 0.5) 89.9%, rgba(54, 54, 55, 0.29) 100%)', svgPrimaryFilter: 'invert(100%) sepia(0%) saturate(0%) hue-rotate(46deg) brightness(100%) contrast(103%)', } -} as any; \ No newline at end of file +}; \ No newline at end of file diff --git a/src/common/context/groupContext.tsx b/src/common/context/groupContext.tsx index bea2d5e..2476dfb 100644 --- a/src/common/context/groupContext.tsx +++ b/src/common/context/groupContext.tsx @@ -1,25 +1,23 @@ import React, { createContext, useContext, useState } from "react"; +import { Group } from '../../models/Group'; interface Props { children: React.ReactNode } interface GroupContextType { - group?: any; - setGroup: React.Dispatch; + group?: Group; + setGroup: React.Dispatch>; }; - -const defaultContext: GroupContextType = { +const GroupContext = createContext({ setGroup: () => {}, -}; - -const GroupContext = createContext(defaultContext); +}); export const useGroupContext = () => useContext(GroupContext); export const GroupContextProvider: React.FC = ({ children }) => { - const [group, setGroup] = useState(); + const [group, setGroup] = useState(); const params: GroupContextType = { setGroup, group }; diff --git a/src/common/context/lecturerContext.tsx b/src/common/context/lecturerContext.tsx index 21aaf25..94826de 100644 --- a/src/common/context/lecturerContext.tsx +++ b/src/common/context/lecturerContext.tsx @@ -1,29 +1,34 @@ import React, { createContext, useContext, useState, ReactNode, FC } from 'react'; +import { Lecturer } from '../../models/Lecturer'; interface Props { children: ReactNode; } interface LecturerContextType { - lecturer: string | null; // Change this to the actual type of lecturer - setLecturer: React.Dispatch>; + lecturer?: Lecturer; + setLecturer: React.Dispatch>; } -const LecturerContext = createContext(null); +const LecturerContext = createContext({ + setLecturer: () => ({}), +}); export const useLecturerContext = () => { const context = useContext(LecturerContext); + if (context === null) { throw new Error('useLecturerContext must be used within a LecturerContextProvider'); } + return context; }; export const LecturerContextProvider: FC = ({ children }) => { - const [lecturer, setLecturer] = useState(null); - - const params = { lecturer, setLecturer }; - + const [lecturer, setLecturer] = useState(); + + const params: LecturerContextType = { lecturer, setLecturer }; + return ( {children} diff --git a/src/common/context/preloadedListsContext.tsx b/src/common/context/preloadedListsContext.tsx index ede009e..147a6a5 100644 --- a/src/common/context/preloadedListsContext.tsx +++ b/src/common/context/preloadedListsContext.tsx @@ -1,19 +1,25 @@ import React, { createContext, useContext, useEffect, useState } from "react"; import { getAllGroups, getAllLecturers } from "../../api/fullList"; +import { Group } from '../../models/Group'; +import { Lecturer } from '../../models/Lecturer'; interface Props { children: React.ReactNode; } interface ContextType { - groups: any[]; - lecturers: any[]; + groups: Group[]; + lecturers: Lecturer[]; } -const PreloadedListsContext = createContext(null); +const PreloadedListsContext = createContext({ + groups: [], + lecturers: [], +}); export const usePreloadedListContext = () => useContext(PreloadedListsContext); -// TODO add exams here + +// TODO: add exams here export const PreloadedListsContextProvider: React.FC = ({ children, }) => { diff --git a/src/common/utils/getApiFunction.ts b/src/common/utils/getApiFunction.ts index be98350..da355d4 100644 --- a/src/common/utils/getApiFunction.ts +++ b/src/common/utils/getApiFunction.ts @@ -2,22 +2,22 @@ import { routes } from '../constants/routes'; import { getScheduleByGroup, getScheduleByLecturer, getExamsByGroup } from '../../api/schedule'; import { getAllGroups, getAllLecturers } from '../../api/fullList'; -export const getScheduleApiFunction = (route: string) => { - const functions = { - [routes.GROUP]: getScheduleByGroup, - [routes.SESSION]: getExamsByGroup, - [routes.LECTURER]: getScheduleByLecturer, - }; +const ROUTE_SCHEDULE_FUNCTION = { + [routes.GROUP]: getScheduleByGroup, + [routes.SESSION]: getExamsByGroup, + [routes.LECTURER]: getScheduleByLecturer, +}; - return functions[route]; -} +const ROUTE_LIST_FUNCTION = { + [routes.GROUP]: getAllGroups, + [routes.SESSION]: getAllGroups, + [routes.LECTURER]: getAllLecturers, +}; -export const getListApiFunction = (route: string) => { - const functions = { - [routes.GROUP]: getAllGroups, - [routes.SESSION]: getAllGroups, - [routes.LECTURER]: getAllLecturers, - }; +export const getScheduleApiFunction = (route: string) => { + return ROUTE_SCHEDULE_FUNCTION[route]; +}; - return functions[route]; -} \ No newline at end of file +export const getListApiFunction = (route: string) => { + return ROUTE_LIST_FUNCTION[route]; +}; \ No newline at end of file diff --git a/src/common/utils/getValueFromTheme.ts b/src/common/utils/getValueFromTheme.ts index 9694b6d..0fd4513 100644 --- a/src/common/utils/getValueFromTheme.ts +++ b/src/common/utils/getValueFromTheme.ts @@ -1,3 +1,3 @@ -export const getValueFromTheme = (key: string) => (props: {theme: any}) => { +export const getValueFromTheme = (key: string) => (props: { theme: any }) => { return props.theme[key]; }; \ No newline at end of file diff --git a/src/common/utils/parsedLocalStorage.ts b/src/common/utils/parsedLocalStorage.ts index aebf52b..ffe24b2 100644 --- a/src/common/utils/parsedLocalStorage.ts +++ b/src/common/utils/parsedLocalStorage.ts @@ -1,13 +1,12 @@ export const setLocalStorageItem = (key: string, value: any) => { - localStorage.setItem(key, JSON.stringify(value)) + localStorage.setItem(key, JSON.stringify(value)); } export const getLocalStorageItem = (key: string) => { - try { - return JSON.parse(localStorage.getItem(key) as any) - } - catch { - // No `key` local storage item, so return undefined - return undefined - } + try { + return JSON.parse(localStorage.getItem(key) as any); + } + catch { + return undefined; + } } diff --git a/src/models/CurrentTime.ts b/src/models/CurrentTime.ts new file mode 100644 index 0000000..3595a38 --- /dev/null +++ b/src/models/CurrentTime.ts @@ -0,0 +1,5 @@ +export interface CurrentTime { + currentDay: number; + currentLesson: number; + currentWeek: number; +} \ No newline at end of file diff --git a/src/models/EntityWithNameAndId.ts b/src/models/EntityWithNameAndId.ts new file mode 100644 index 0000000..8234af1 --- /dev/null +++ b/src/models/EntityWithNameAndId.ts @@ -0,0 +1,4 @@ +export interface EntityWithNameAndId { + id: string; + name: string; +} \ No newline at end of file diff --git a/src/models/Exam.ts b/src/models/Exam.ts new file mode 100644 index 0000000..be762c9 --- /dev/null +++ b/src/models/Exam.ts @@ -0,0 +1,12 @@ +export interface Exam { + daysLeft: number; + id: string; + date: string; + lecturerName: string; + lecturerId: string; + room: string; + subjectShort: string; + subject: string; + group?: string; + genericGroupId: string; +} \ No newline at end of file diff --git a/src/models/Group.ts b/src/models/Group.ts new file mode 100644 index 0000000..4137812 --- /dev/null +++ b/src/models/Group.ts @@ -0,0 +1,5 @@ +import { EntityWithNameAndId } from './EntityWithNameAndId'; + +export interface Group extends EntityWithNameAndId { + faculty: string; +} \ No newline at end of file diff --git a/src/models/Lecturer.ts b/src/models/Lecturer.ts new file mode 100644 index 0000000..a11812b --- /dev/null +++ b/src/models/Lecturer.ts @@ -0,0 +1,4 @@ +import { EntityWithNameAndId } from './EntityWithNameAndId'; + +export interface Lecturer extends EntityWithNameAndId { +} \ No newline at end of file diff --git a/src/models/LecturerLesson.ts b/src/models/LecturerLesson.ts new file mode 100644 index 0000000..4392ea5 --- /dev/null +++ b/src/models/LecturerLesson.ts @@ -0,0 +1,4 @@ +import { LecturerPair } from './LecturerPair'; +import { Lesson } from './Lesson'; + +export interface LecturerLesson extends Lesson {} \ No newline at end of file diff --git a/src/models/LecturerPair.ts b/src/models/LecturerPair.ts new file mode 100644 index 0000000..cb2ea98 --- /dev/null +++ b/src/models/LecturerPair.ts @@ -0,0 +1,5 @@ +import { Pair } from './Pair'; + +export interface LecturerPair extends Pair { + group: string; +} \ No newline at end of file diff --git a/src/models/Lesson.ts b/src/models/Lesson.ts new file mode 100644 index 0000000..86e0397 --- /dev/null +++ b/src/models/Lesson.ts @@ -0,0 +1,8 @@ +import { Pair } from './Pair'; +import { Schedule } from './Schedule'; + +export interface Lesson { + groupCode: string; + scheduleFirstWeek: Schedule[]; + scheduleSecondWeek: Schedule[]; +} \ No newline at end of file diff --git a/src/models/PagedResponse.ts b/src/models/PagedResponse.ts new file mode 100644 index 0000000..dc12d95 --- /dev/null +++ b/src/models/PagedResponse.ts @@ -0,0 +1,17 @@ +interface Paging { + firstItemOnPage: number; + hasNextPage: boolean; + hasPreviousPage: boolean; + isFirstPage: boolean; + isLastPage: boolean; + lastItemOnPage: number; + pageCount: number; + pageNumber: number; + pageSize: number; + totalItemCount: number; +} + +export interface PagedResponse { + data: T; + paging?: Paging; +} \ No newline at end of file diff --git a/src/models/Pair.ts b/src/models/Pair.ts new file mode 100644 index 0000000..d85c0e1 --- /dev/null +++ b/src/models/Pair.ts @@ -0,0 +1,9 @@ +export interface Pair { + lecturerId: string; + name: string; + place: string; + tag: string; + teacherName: string; + time: string; + type: string; +} \ No newline at end of file diff --git a/src/models/Schedule.ts b/src/models/Schedule.ts new file mode 100644 index 0000000..7a0d602 --- /dev/null +++ b/src/models/Schedule.ts @@ -0,0 +1,6 @@ +import { Pair } from './Pair'; + +export interface Schedule { + day: number; + pairs: T[]; +} \ No newline at end of file diff --git a/src/models/StudentLesson.ts b/src/models/StudentLesson.ts new file mode 100644 index 0000000..37b8b89 --- /dev/null +++ b/src/models/StudentLesson.ts @@ -0,0 +1,4 @@ +import { Lesson } from './Lesson'; +import { StudentPair } from './StudentPair'; + +export interface StudentLesson extends Lesson {} \ No newline at end of file diff --git a/src/models/StudentPair.ts b/src/models/StudentPair.ts new file mode 100644 index 0000000..4d7fbac --- /dev/null +++ b/src/models/StudentPair.ts @@ -0,0 +1,6 @@ +import { Pair } from './Pair'; + +export interface StudentPair extends Pair { + lecturerId: string; + teacherName: string; +} \ No newline at end of file diff --git a/src/types/ListOption.ts b/src/types/ListOption.ts new file mode 100644 index 0000000..fb8e89b --- /dev/null +++ b/src/types/ListOption.ts @@ -0,0 +1,4 @@ +export interface ListOption { + value: T; + label: string; +} \ No newline at end of file diff --git a/src/types/Theme.ts b/src/types/Theme.ts new file mode 100644 index 0000000..faf98a1 --- /dev/null +++ b/src/types/Theme.ts @@ -0,0 +1 @@ +export type Theme = 'light' | 'dark'; \ No newline at end of file diff --git a/src/types/Week.ts b/src/types/Week.ts new file mode 100644 index 0000000..ea1162f --- /dev/null +++ b/src/types/Week.ts @@ -0,0 +1 @@ +export type Week = 'firstWeek' | 'secondWeek'; \ No newline at end of file From f9f497c29b21a4e471742313cf8003b0c5cc3817 Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 18:21:34 +0300 Subject: [PATCH 02/13] fix: styles of schedule items --- src/components/timeDivider/timeDivider.style.ts | 1 + src/components/timeDivider/timeDivider.tsx | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/timeDivider/timeDivider.style.ts b/src/components/timeDivider/timeDivider.style.ts index 172c4bc..4c9c01b 100644 --- a/src/components/timeDivider/timeDivider.style.ts +++ b/src/components/timeDivider/timeDivider.style.ts @@ -13,6 +13,7 @@ export const InnerContainer = styled(Flex)` right: 0; top: -17px; position: absolute; + align-items: center; ${media.extraSmallMode} { left: -44px; diff --git a/src/components/timeDivider/timeDivider.tsx b/src/components/timeDivider/timeDivider.tsx index fa6a523..08b0fa8 100644 --- a/src/components/timeDivider/timeDivider.tsx +++ b/src/components/timeDivider/timeDivider.tsx @@ -10,8 +10,6 @@ import { ReactNode } from "react"; const TimeDivider = ({ children }: { children: ReactNode }) => { return ( - {/* FIXME: */} - {/* */} {children} From 31f3734a55509e4040fa8b060e4f401f0f9b414a Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 19:11:36 +0300 Subject: [PATCH 03/13] refactor: theme switch and theme context --- src/common/context/themeContext.tsx | 61 +++++++++---------- src/components/switch/index.ts | 3 - src/components/switch/switch.tsx | 54 ---------------- .../themeSwitch.scss} | 0 src/components/themeSwitch/themeSwitch.tsx | 35 +++++++++++ src/containers/navbar/navbar.tsx | 6 +- 6 files changed, 68 insertions(+), 91 deletions(-) delete mode 100644 src/components/switch/index.ts delete mode 100644 src/components/switch/switch.tsx rename src/components/{switch/switch.scss => themeSwitch/themeSwitch.scss} (100%) create mode 100644 src/components/themeSwitch/themeSwitch.tsx diff --git a/src/common/context/themeContext.tsx b/src/common/context/themeContext.tsx index 3194b6c..0a03b7a 100644 --- a/src/common/context/themeContext.tsx +++ b/src/common/context/themeContext.tsx @@ -1,54 +1,53 @@ import { ThemeProvider } from 'styled-components'; -import React, { createContext, useContext, useEffect, useState } from 'react'; +import React, { createContext, useContext, useState } from 'react'; import { theme } from '../../common/constants/theme'; import { getLocalStorageItem, setLocalStorageItem } from '../utils/parsedLocalStorage'; +import { Theme } from '../../types/Theme'; + +const THEME_STORAGE_KEY = 'schedule-theme'; interface Props { - children: React.ReactNode, - initialValue?: 'light' | 'dark' + children: React.ReactNode; } -interface ContextType { - changeTheme: (isLightTheme: boolean) => void, +interface ThemeContext { + value?: Theme; + changeTheme: (theme: Theme) => void, } -const defaultContext: ContextType = { +const ThemeSelectorContext = createContext({ changeTheme: () => {}, -}; - -const ThemeSelectorContext = createContext(defaultContext); - +}); export const useThemeSelectorContext = () => useContext(ThemeSelectorContext); -const ThemeContextProvider: React.FC = ({ children, initialValue = 'light' }) => { - const [currentTheme, setTheme] = useState(initialValue); - - useEffect(() => { - const localStorageTheme = getLocalStorageItem("theme") +const ThemeContextProvider: React.FC = ({ children }) => { + const getTheme = () => { + const localStorageTheme = getLocalStorageItem(THEME_STORAGE_KEY) const prefersLight = window.matchMedia('(prefers-color-scheme: light)').matches; - if (localStorageTheme) { - changeTheme(localStorageTheme === 'light') - } - else { - changeTheme(prefersLight) + if (!localStorageTheme) { + return prefersLight ? 'light' : 'dark'; } - }, []) - const changeTheme = (isLightTheme: boolean) => { - const newTheme = isLightTheme ? 'light' : 'dark' - setTheme(newTheme); - setLocalStorageItem("theme", newTheme) - } - - const props = { - changeTheme + return localStorageTheme as Theme; + }; + + const [currentTheme, setTheme] = useState(getTheme()); + + const changeTheme = (theme: Theme) => { + setTheme(theme); + setLocalStorageItem(THEME_STORAGE_KEY, theme); } - + + const context: ThemeContext = { + value: currentTheme, + changeTheme, + }; + return ( - + {children} diff --git a/src/components/switch/index.ts b/src/components/switch/index.ts deleted file mode 100644 index e6e6815..0000000 --- a/src/components/switch/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Switch from './switch'; - -export default Switch; \ No newline at end of file diff --git a/src/components/switch/switch.tsx b/src/components/switch/switch.tsx deleted file mode 100644 index 7a4e3bc..0000000 --- a/src/components/switch/switch.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import "./switch.scss"; -import { useTheme } from "styled-components"; -import { useEffect, useState } from "react"; -import clsx from "clsx"; -import { getLocalStorageItem } from "../../common/utils/parsedLocalStorage"; - -const Switch = ({ onChange }: { onChange: (state: any | null) => void }) => { - const theme = useTheme(); - - const [checked, setChecked] = useState(undefined); - - useEffect(() => { - const localStorageTheme = getLocalStorageItem("theme"); - const prefersLight = window.matchMedia( - "(prefers-color-scheme: light)" - ).matches; - if (localStorageTheme) { - setChecked(localStorageTheme === "light"); - } else { - setChecked(prefersLight); - } - }, []); - - const onCheckboxChange = (event: React.ChangeEvent) => { - const newState = event.target.checked; - setChecked(event.target.checked); - - onChange(newState); - }; - - return ( - <> - - - ); -}; - -export default Switch; diff --git a/src/components/switch/switch.scss b/src/components/themeSwitch/themeSwitch.scss similarity index 100% rename from src/components/switch/switch.scss rename to src/components/themeSwitch/themeSwitch.scss diff --git a/src/components/themeSwitch/themeSwitch.tsx b/src/components/themeSwitch/themeSwitch.tsx new file mode 100644 index 0000000..1835843 --- /dev/null +++ b/src/components/themeSwitch/themeSwitch.tsx @@ -0,0 +1,35 @@ +import "./themeSwitch.scss"; +import { useTheme } from "styled-components"; +import { Theme } from '../../types/Theme'; + +interface ThemeSwitchProps { + value?: Theme; + onChange: (value: Theme) => void; +} + +const ThemeSwitch = ({ value, onChange }: ThemeSwitchProps) => { + const theme = useTheme(); + + const onCheckboxChange = (event: React.ChangeEvent) => { + onChange(event.target.checked ? 'light' : 'dark'); + }; + + return ( + <> + + + ); +}; + +export default ThemeSwitch; diff --git a/src/containers/navbar/navbar.tsx b/src/containers/navbar/navbar.tsx index c5f1ea2..5ce52b4 100644 --- a/src/containers/navbar/navbar.tsx +++ b/src/containers/navbar/navbar.tsx @@ -1,19 +1,19 @@ import { Logo } from '../../common/styles/styles'; import MainSettings from '../mainSettings'; import { NavbarInner, NavBarWrapper } from './navbar.style'; -import Switch from '../../components/switch'; +import ThemeSwitch from '../../components/themeSwitch'; import logo from '../../assets/logo.svg'; import { useThemeSelectorContext } from '../../common/context/themeContext'; const Navbar = () => { - const selectTheme = useThemeSelectorContext(); + const { currentTheme, changeTheme } = useThemeSelectorContext(); return ( - + ); From 89985f3ddc95917ebde1085156a84867170fc479 Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 20:31:03 +0300 Subject: [PATCH 04/13] refactor: lecturers and groups api calls --- src/api/fullList.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/api/fullList.ts b/src/api/fullList.ts index 3d7f731..78b8dca 100644 --- a/src/api/fullList.ts +++ b/src/api/fullList.ts @@ -1,16 +1,21 @@ +import { Group } from '../models/Group'; +import { Lecturer } from '../models/Lecturer'; +import { PagedResponse } from '../models/PagedResponse'; import Http from "./index"; -export const getAllLecturers = () => { +export const getAllLecturers = (): Promise> => { return Http.get("/schedule/lecturer/list").then(({ data }) => data); }; -export const getAllGroups = () => { - return Http.get("/schedule/groups").then(({ data }) => { - return { - data: data.data.map((row: {name: string, faculty: string, id: string}) => ({ - name: `${row.name.trim()} (${row.faculty.trim()})`, - id: row.id, - })), - }; - }); +export const getAllGroups = async (): Promise> => { + const response = await Http.get>("/schedule/groups") + + return { + ...response.data, + data: response.data.data.map(row => ({ + ...row, + name: `${row.name.trim()} (${row.faculty.trim()})`, + id: row.id, + })) + }; }; From 137bab18bdada8f2247c6519ee00d83a733b327f Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 20:31:38 +0300 Subject: [PATCH 05/13] refactor: themeContext --- src/common/context/themeContext.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/context/themeContext.tsx b/src/common/context/themeContext.tsx index 0a03b7a..bb2d19a 100644 --- a/src/common/context/themeContext.tsx +++ b/src/common/context/themeContext.tsx @@ -11,7 +11,7 @@ interface Props { } interface ThemeContext { - value?: Theme; + currentTheme?: Theme; changeTheme: (theme: Theme) => void, } @@ -41,7 +41,7 @@ const ThemeContextProvider: React.FC = ({ children }) => { } const context: ThemeContext = { - value: currentTheme, + currentTheme, changeTheme, }; From 0ab30ec8fcb154423360ece79fd7cc8b4b78155f Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 20:35:22 +0300 Subject: [PATCH 06/13] refactor: week and semester switch --- src/common/context/weekContext.tsx | 23 ++++---- .../optionMultipleToggler.tsx | 55 ++++++------------- src/components/weekSwitch/weekSwitch.tsx | 13 +++-- 3 files changed, 36 insertions(+), 55 deletions(-) diff --git a/src/common/context/weekContext.tsx b/src/common/context/weekContext.tsx index 1b45805..b0fc4e9 100644 --- a/src/common/context/weekContext.tsx +++ b/src/common/context/weekContext.tsx @@ -1,28 +1,27 @@ import React, { createContext, useContext, useState } from 'react'; +import { Week } from '../../types/Week'; interface Props { - initialValue: any, - children: React.ReactNode, + initialValue: Week; + children: React.ReactNode; } -interface ContextProps { - setCurrentWeek: React.Dispatch, - currentWeek: any, +interface WeekContextType { + setCurrentWeek: React.Dispatch>; + currentWeek: Week; } -const defaultContext: ContextProps = { +const WeekContext = createContext({ setCurrentWeek: () => {}, - currentWeek: 0, -}; - -const WeekContext = createContext(defaultContext); + currentWeek: 'firstWeek', +}); export const useWeekContext = () => useContext(WeekContext); -export const WeekContextProvider: React.FC = ({initialValue, children}) => { +export const WeekContextProvider: React.FC = ({ initialValue, children }) => { const [currentWeek, setCurrentWeek] = useState(initialValue); - const params = {setCurrentWeek, currentWeek}; + const params: WeekContextType = {setCurrentWeek, currentWeek}; return ( diff --git a/src/components/optionMultipleToggler/optionMultipleToggler.tsx b/src/components/optionMultipleToggler/optionMultipleToggler.tsx index 40684c8..0991e4f 100644 --- a/src/components/optionMultipleToggler/optionMultipleToggler.tsx +++ b/src/components/optionMultipleToggler/optionMultipleToggler.tsx @@ -1,49 +1,28 @@ +import { ListOption } from '../../types/ListOption'; import { TogglerOption, TogglerWrapper } from './optionMultipleToggler.style'; -import React, { useEffect, useState } from 'react'; -interface Props { - options: {value: string, label: string}[], - onOptionChange: (value: string | null) => void, - initialValue: string | null, +interface Props { + options: ListOption[]; + onChange: (value: T) => void; + currentValue: T; } -const OptionMultipleToggler: React.FC = ({options, onOptionChange, initialValue}) => { - const [selectedItem, selectItem] = useState(initialValue); - - useEffect(() => { - selectItem(initialValue); - - return () => onOptionChange(null); - }, [initialValue]); - - useEffect(() => { - onOptionChange(selectedItem); - }, [selectedItem]); - - const optionChangeHandler = (value: string) => () => { - selectItem(state => { - if (state !== value) { - return value; - } - - return state; - }); - +const OptionMultipleToggler = ({ options, onChange, currentValue }: Props) => { + const optionChangeHandler = (value: T) => () => { + onChange(value); }; - const togglerOptions = (options || []).map(item => { - return ( - - {item.label} - - ); - }); - return ( - {togglerOptions} + {options.map(item => ( + + {item.label} + + ))} ); }; diff --git a/src/components/weekSwitch/weekSwitch.tsx b/src/components/weekSwitch/weekSwitch.tsx index 26abfba..5a43d4a 100644 --- a/src/components/weekSwitch/weekSwitch.tsx +++ b/src/components/weekSwitch/weekSwitch.tsx @@ -1,5 +1,7 @@ import OptionMultipleToggler from "../../components/optionMultipleToggler"; import { useWeekContext } from "../../common/context/weekContext"; +import { Week } from '../../types/Week'; +import { ListOption } from '../../types/ListOption'; interface WeekSwitchProps { type: "weeks" | "semesters"; @@ -8,26 +10,27 @@ interface WeekSwitchProps { const WeekSwitch = ({ type }: WeekSwitchProps) => { const { setCurrentWeek, currentWeek } = useWeekContext()!; - const updateWeek = (value: string | null) => { + const updateWeek = (value: Week) => { if (value) { setCurrentWeek(value); } }; - const weeks = [ + const weeks: ListOption[] = [ { label: "Перший тиждень", value: "firstWeek" }, { label: "Другий тиждень", value: "secondWeek" }, ]; - const semesters = [ + const semesters: ListOption[] = [ { label: "Перший семестр", value: "firstWeek" }, { label: "Другий семестр", value: "secondWeek" }, ]; + return ( ); }; From 8e9b24913658367ce798a034523246d6674d6ef3 Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 20:35:35 +0300 Subject: [PATCH 07/13] fix: ThemeSwitch default export --- src/components/themeSwitch/index.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/components/themeSwitch/index.ts diff --git a/src/components/themeSwitch/index.ts b/src/components/themeSwitch/index.ts new file mode 100644 index 0000000..ffa82e1 --- /dev/null +++ b/src/components/themeSwitch/index.ts @@ -0,0 +1,3 @@ +import ThemeSwitch from './themeSwitch'; + +export default ThemeSwitch; \ No newline at end of file From 193721af5528335934c023dbea47e830a286b030 Mon Sep 17 00:00:00 2001 From: Andrew Izvarin Date: Wed, 14 Aug 2024 23:51:58 +0300 Subject: [PATCH 08/13] refactoring: more types, introduced lodash, use moment where necessary, refactoring of other peices of code --- package-lock.json | 39 ++++++++- package.json | 2 + src/common/constants/dayOptions.ts | 13 +-- src/common/constants/modes.ts | 6 -- src/common/context/sliceOptionsContext.tsx | 7 +- src/common/styles/styles.ts | 12 +-- src/common/utils/apiTransformers.ts | 28 ++++--- src/common/utils/getActiveTimePoint.ts | 6 +- src/common/utils/getApiFunction.ts | 23 ------ src/common/utils/getModeSize.ts | 12 --- src/common/utils/getScreenSize.ts | 12 +++ src/common/utils/unique.ts | 7 -- src/common/utils/useCurrentDateParams.ts | 9 ++- src/common/utils/useCurrentMode.ts | 12 +-- src/components/entitySearch/entitySearch.tsx | 61 ++++++++------ src/components/examComponent/exam.tsx | 70 ---------------- src/components/examComponent/index.ts | 3 - .../exam.style.ts | 0 src/components/examSchedule/examSchedule.tsx | 60 ++++++++++++++ src/components/examSchedule/index.ts | 3 + .../optionMultipleToggler.tsx | 32 +++----- .../scheduleItemContent.tsx | 79 +++++++++++-------- .../scheduleTypeTab/scheduleTypeTab.tsx | 14 ++-- src/components/timeDivider/timeDivider.tsx | 18 ++--- src/components/weekSwitch/weekSwitch.tsx | 32 ++++---- src/containers/router/scheduleRouter.tsx | 8 +- src/containers/schedule/schedule.tsx | 27 ++++--- .../scheduleDayToggler/scheduleDayToggler.tsx | 38 +++++---- .../scheduleExams/scheduleExams.tsx | 29 +++---- .../scheduleHeader/scheduleHeader.tsx | 29 +++---- src/containers/scheduleItem/scheduleItem.tsx | 12 ++- .../scheduleItemExtended.tsx | 58 +++++++------- src/containers/scheduleRow/scheduleRow.tsx | 26 +++--- .../scheduleWrapper/scheduleWrapper.tsx | 58 +++++++------- src/containers/scrollToTop/scrollToTop.tsx | 2 +- src/containers/tabs/tabs.tsx | 16 ++-- src/index.tsx | 4 + src/types/ScreenSize.ts | 6 ++ 38 files changed, 460 insertions(+), 413 deletions(-) delete mode 100644 src/common/constants/modes.ts delete mode 100644 src/common/utils/getApiFunction.ts delete mode 100644 src/common/utils/getModeSize.ts create mode 100644 src/common/utils/getScreenSize.ts delete mode 100644 src/common/utils/unique.ts delete mode 100644 src/components/examComponent/exam.tsx delete mode 100644 src/components/examComponent/index.ts rename src/components/{examComponent => examSchedule}/exam.style.ts (100%) create mode 100644 src/components/examSchedule/examSchedule.tsx create mode 100644 src/components/examSchedule/index.ts create mode 100644 src/types/ScreenSize.ts diff --git a/package-lock.json b/package-lock.json index 072d249..3b91967 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^12.1.5", "@testing-library/user-event": "^14.4.3", - "@types/jest": "^29.5.12", + "@types/lodash-es": "^4.17.12", "@types/material-ui": "^0.21.17", "@types/node": "^20.14.2", "@types/react": "^17.0.80", @@ -21,6 +21,7 @@ "@types/styled-system": "^5.1.22", "axios": "^0.27.2", "clsx": "^1.2.0", + "lodash-es": "^4.17.21", "moment": "^2.29.4", "react": "17.0.2", "react-dom": "^17.0.2", @@ -4502,6 +4503,19 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/material-ui": { "version": "0.21.17", "resolved": "https://registry.npmjs.org/@types/material-ui/-/material-ui-0.21.17.tgz", @@ -13121,6 +13135,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -23140,6 +23159,19 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, + "@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "requires": { + "@types/lodash": "*" + } + }, "@types/material-ui": { "version": "0.21.17", "resolved": "https://registry.npmjs.org/@types/material-ui/-/material-ui-0.21.17.tgz", @@ -29713,6 +29745,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", diff --git a/package.json b/package.json index f02d9d8..e01c738 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^12.1.5", "@testing-library/user-event": "^14.4.3", + "@types/lodash-es": "^4.17.12", "@types/material-ui": "^0.21.17", "@types/node": "^20.14.2", "@types/react": "^17.0.80", @@ -15,6 +16,7 @@ "@types/styled-system": "^5.1.22", "axios": "^0.27.2", "clsx": "^1.2.0", + "lodash-es": "^4.17.21", "moment": "^2.29.4", "react": "17.0.2", "react-dom": "^17.0.2", diff --git a/src/common/constants/dayOptions.ts b/src/common/constants/dayOptions.ts index af07bf6..630189b 100644 --- a/src/common/constants/dayOptions.ts +++ b/src/common/constants/dayOptions.ts @@ -1,7 +1,8 @@ -import { MODES } from './modes'; +import { ListOption } from '../../types/ListOption'; +import { ScreenSize } from '../../types/ScreenSize'; -export const DAY_OPTIONS = { - [MODES.EXTRA_SMALL]: [ +export const DAY_OPTIONS: Partial[]>> = { + [ScreenSize.ExtraSmall]: [ {label: 'ПН', value: '0-1'}, {label: 'ВТ', value: '1-2'}, {label: 'СР', value: '2-3'}, @@ -9,13 +10,13 @@ export const DAY_OPTIONS = { {label: 'ПТ', value: '4-5'}, {label: 'СБ', value: '5-6'}, ], - [MODES.SMALL]: [ + [ScreenSize.Small]: [ {label: 'ПН-ВТ', value: '0-2'}, {label: 'СР-ЧТ', value: '2-4'}, {label: 'ПТ-СБ', value: '4-6'}, ], - [MODES.MEDIUM]: [ + [ScreenSize.Medium]: [ {label: 'ПН-СР', value: '0-3'}, {label: 'ЧТ-СБ', value: '3-6'}, - ] + ], }; diff --git a/src/common/constants/modes.ts b/src/common/constants/modes.ts deleted file mode 100644 index 8c38ab9..0000000 --- a/src/common/constants/modes.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const MODES = { - EXTRA_SMALL: 'extraSmallMode', - SMALL: 'smallMode', - MEDIUM: 'mediumMode', - BIG: 'bigMode', -} as Record; \ No newline at end of file diff --git a/src/common/context/sliceOptionsContext.tsx b/src/common/context/sliceOptionsContext.tsx index 9a21fd3..26caaa0 100644 --- a/src/common/context/sliceOptionsContext.tsx +++ b/src/common/context/sliceOptionsContext.tsx @@ -1,6 +1,11 @@ import { createContext, useContext } from 'react'; -const SliceOptionsContext = createContext<{start: number, end: number} | null>(null); +export interface Slice { + start?: number; + end?: number; +} + +const SliceOptionsContext = createContext({}); export const useSliceOptionsContext = () => useContext(SliceOptionsContext); diff --git a/src/common/styles/styles.ts b/src/common/styles/styles.ts index 04a0b58..8c7c190 100644 --- a/src/common/styles/styles.ts +++ b/src/common/styles/styles.ts @@ -1,9 +1,9 @@ import styled, { css } from 'styled-components'; import { flexbox, space } from 'styled-system'; -import { MODES } from '../../common/constants/modes'; -import { getModeSize } from '../utils/getModeSize'; +import { getScreenSize } from '../utils/getScreenSize'; import { getValueFromTheme } from '../../common/utils/getValueFromTheme'; import { Link } from 'react-router-dom'; +import { ScreenSize } from '../../types/ScreenSize'; export const Flex = styled.div<{gap?: string}>` display: flex; @@ -19,10 +19,10 @@ export const Pictogram = styled.img` `; export const media = { - [MODES.EXTRA_SMALL]: `@media(max-width: ${getModeSize(MODES.EXTRA_SMALL)})`, - [MODES.SMALL]: `@media(max-width: ${getModeSize(MODES.SMALL)})`, - [MODES.MEDIUM]: `@media(max-width: ${getModeSize(MODES.MEDIUM)})`, - [MODES.BIG]: `@media(min-width: ${getModeSize(MODES.BIG)})`, + [ScreenSize.ExtraSmall]: `@media(max-width: ${getScreenSize(ScreenSize.ExtraSmall)})`, + [ScreenSize.Small]: `@media(max-width: ${getScreenSize(ScreenSize.Small)})`, + [ScreenSize.Medium]: `@media(max-width: ${getScreenSize(ScreenSize.Medium)})`, + [ScreenSize.Big]: `@media(min-width: ${getScreenSize(ScreenSize.Big)})`, }; export const Logo = styled(Pictogram)` diff --git a/src/common/utils/apiTransformers.ts b/src/common/utils/apiTransformers.ts index b68142e..c3db4bb 100644 --- a/src/common/utils/apiTransformers.ts +++ b/src/common/utils/apiTransformers.ts @@ -1,14 +1,18 @@ -import { unique } from "./unique"; +import { uniqBy } from 'lodash-es'; +import { EntityWithNameAndId } from '../../models/EntityWithNameAndId'; +import { ListOption } from '../../types/ListOption'; -export const prepareList = (list: {label: string, value: string, name: string, id: string}[]): {label: string, value: string}[] => { - return unique( - list.map((item: {name: string, id: string}) => ({ - label: item.name, - value: item.id, - })) - .filter((item: {label: string, value: string}) => item.label !== "" && item.value !== "") - .sort((a, b) => { - return a.label.localeCompare(b.label, "uk") - }), - (item => item.label)); +export const prepareList = (list: EntityWithNameAndId[]): ListOption[] => { + const items = list.reduce((acc: ListOption[], item: EntityWithNameAndId) => { + if (item.name === '' || item.id === '') { + return acc; + } + + return [ + ...acc, + { label: item.name, value: item.id } + ]; + }, []).sort((a, b) => a.label.localeCompare(b.label, 'uk')); + + return uniqBy(items, x => x.label); }; diff --git a/src/common/utils/getActiveTimePoint.ts b/src/common/utils/getActiveTimePoint.ts index 936e9b9..d180ef8 100644 --- a/src/common/utils/getActiveTimePoint.ts +++ b/src/common/utils/getActiveTimePoint.ts @@ -5,10 +5,10 @@ export const getActiveTimePoint = () => { const PAIR_DURATION_IN_MINUTES = 95; const now = moment(); - return TIME_POINTS.findIndex((timePoint, i) => { + return TIME_POINTS.findIndex((timePoint) => { const timeNumbers = timePoint.split('.').map(item => +item); - const pairStartDate = moment().set({hours: timeNumbers[0], minutes: timeNumbers[1], seconds: 0}); - const pairEndDate = moment(pairStartDate).set({minutes: timeNumbers[1] + PAIR_DURATION_IN_MINUTES}) + const pairStartDate = moment().set({ hours: timeNumbers[0], minutes: timeNumbers[1], seconds: 0 }); + const pairEndDate = moment(pairStartDate).set({ minutes: timeNumbers[1] + PAIR_DURATION_IN_MINUTES }) return now.isBetween(pairStartDate, pairEndDate); }); diff --git a/src/common/utils/getApiFunction.ts b/src/common/utils/getApiFunction.ts deleted file mode 100644 index da355d4..0000000 --- a/src/common/utils/getApiFunction.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { routes } from '../constants/routes'; -import { getScheduleByGroup, getScheduleByLecturer, getExamsByGroup } from '../../api/schedule'; -import { getAllGroups, getAllLecturers } from '../../api/fullList'; - -const ROUTE_SCHEDULE_FUNCTION = { - [routes.GROUP]: getScheduleByGroup, - [routes.SESSION]: getExamsByGroup, - [routes.LECTURER]: getScheduleByLecturer, -}; - -const ROUTE_LIST_FUNCTION = { - [routes.GROUP]: getAllGroups, - [routes.SESSION]: getAllGroups, - [routes.LECTURER]: getAllLecturers, -}; - -export const getScheduleApiFunction = (route: string) => { - return ROUTE_SCHEDULE_FUNCTION[route]; -}; - -export const getListApiFunction = (route: string) => { - return ROUTE_LIST_FUNCTION[route]; -}; \ No newline at end of file diff --git a/src/common/utils/getModeSize.ts b/src/common/utils/getModeSize.ts deleted file mode 100644 index c588d70..0000000 --- a/src/common/utils/getModeSize.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {MODES} from "../../common/constants/modes"; - -export const getModeSize = (MODE: string): string => { - const MODE_SIZES = { - [MODES.BIG]: '1441px', - [MODES.MEDIUM]: '1440px', - [MODES.SMALL]: '988px', - [MODES.EXTRA_SMALL]: '639px', - } - - return MODE_SIZES[MODE]; -} \ No newline at end of file diff --git a/src/common/utils/getScreenSize.ts b/src/common/utils/getScreenSize.ts new file mode 100644 index 0000000..bcc762d --- /dev/null +++ b/src/common/utils/getScreenSize.ts @@ -0,0 +1,12 @@ +import { ScreenSize } from '../../types/ScreenSize'; + +const SCRREN_SIZES: Record = { + [ScreenSize.Big]: '1441px', + [ScreenSize.Medium]: '1440px', + [ScreenSize.Small]: '988px', + [ScreenSize.ExtraSmall]: '639px', +}; + +export const getScreenSize = (mode: ScreenSize) => { + return SCRREN_SIZES[mode]; +} \ No newline at end of file diff --git a/src/common/utils/unique.ts b/src/common/utils/unique.ts deleted file mode 100644 index 6bc7fda..0000000 --- a/src/common/utils/unique.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const unique = (array: any[], getComparingItem = (item: any) => item) => { - const uniqueFilter = (value: string, index: number, self: any) => { - return self.map((e: any) => getComparingItem(e)).indexOf(getComparingItem(value)) === index; - } - - return [...array.filter(uniqueFilter)]; -} \ No newline at end of file diff --git a/src/common/utils/useCurrentDateParams.ts b/src/common/utils/useCurrentDateParams.ts index 46dbdd9..63d012f 100644 --- a/src/common/utils/useCurrentDateParams.ts +++ b/src/common/utils/useCurrentDateParams.ts @@ -1,12 +1,17 @@ import { useEffect, useState } from 'react'; import { getCurrentDateValues } from '../../api/getCurrentDateValues'; +import { CurrentTime } from '../../models/CurrentTime'; export const useCurrentDateParams = () => { - const [dateParams, setDateParams] = useState({currentWeek: null, currentDay: null, currentLesson: null}); + const [dateParams, setDateParams] = useState({ + currentDay: -1, + currentLesson: -1, + currentWeek: -1, + }); useEffect(() => { getCurrentDateValues() - .then(({data}) => setDateParams({...data, currentDay: data.currentDay - 1})); + .then(({ data }) => setDateParams({ ...data, currentDay: data.currentDay })); }, []); return dateParams; diff --git a/src/common/utils/useCurrentMode.ts b/src/common/utils/useCurrentMode.ts index 1c437c2..83adc12 100644 --- a/src/common/utils/useCurrentMode.ts +++ b/src/common/utils/useCurrentMode.ts @@ -1,6 +1,6 @@ -import { MODES } from "../../common/constants/modes"; -import { getModeSize } from "./getModeSize"; +import { ScreenSize } from '../../types/ScreenSize'; import { useEffect, useState } from "react"; +import { getScreenSize } from './getScreenSize'; export const useCurrentMode = () => { const [currentMode, setCurrentMode] = useState(null); @@ -13,14 +13,14 @@ export const useCurrentMode = () => { }, []); const detectCurrentMode = () => { - for (let key in MODES) { - if (window.innerWidth <= parseInt(getModeSize(MODES[key]))) { - setCurrentMode(MODES[key]); + for (let key in ScreenSize) { + if (window.innerWidth <= parseInt(getScreenSize(ScreenSize[key]))) { + setCurrentMode(ScreenSize[key]); return; } } - setCurrentMode(MODES.BIG); + setCurrentMode(ScreenSize.Big); }; return currentMode; diff --git a/src/components/entitySearch/entitySearch.tsx b/src/components/entitySearch/entitySearch.tsx index 8bc2ff0..ae693d3 100644 --- a/src/components/entitySearch/entitySearch.tsx +++ b/src/components/entitySearch/entitySearch.tsx @@ -15,75 +15,84 @@ import { routes } from "../../common/constants/routes"; import { getSelectCustomStyle } from "../../common/constants/selectOptions"; import "./entitySearch.scss"; import { getLocalStorageItem, setLocalStorageItem } from "../../common/utils/parsedLocalStorage"; +import { ListOption } from '../../types/ListOption'; +import { Lecturer } from '../../models/Lecturer'; +import { Group } from '../../models/Group'; +import { EntityWithNameAndId } from '../../models/EntityWithNameAndId'; const useQuery = () => { const { search } = useLocation(); return React.useMemo(() => new URLSearchParams(search), [search]); }; -const EntitySearch: React.FC = () => { +const EntitySearch = () => { + const [options, setOptions] = useState[]>([]); + const theme = useTheme(); const location = useLocation(); const history = useHistory(); - const [options, setOptions] = useState<{label: string, value: string}[]>([]); - const lecturerContextValue = useLecturerContext(); - - const groupContextValue = useGroupContext(); const lists = usePreloadedListContext(); + const groupContext = useGroupContext(); + const lecturerContext = useLecturerContext(); const isLecturer = location.pathname.includes(routes.LECTURER); - const list = isLecturer ? lists?.lecturers : lists?.groups; + const list: EntityWithNameAndId[] = isLecturer ? lists.lecturers : lists.groups; const query = useQuery(); useEffect(() => { if (isLecturer) { - groupContextValue?.setGroup(null); + groupContext.setGroup(undefined); } else { - lecturerContextValue?.setLecturer(null); + lecturerContext.setLecturer(undefined); } }, [isLecturer]); useEffect(() => { if (isLecturer) { - let lecturer = query.get("lecturerId"); + let lecturerId = query.get("lecturerId"); const localStorageLecturerId = getLocalStorageItem("lecturerId") - if(!lecturer && localStorageLecturerId){ - lecturer = localStorageLecturerId + if(!lecturerId && localStorageLecturerId){ + lecturerId= localStorageLecturerId; history.replace("?lecturerId=" + localStorageLecturerId); } - lecturerContextValue?.setLecturer(lecturer); - groupContextValue?.setGroup(null); + const lecturer = list.find(x => x.id === lecturerId) as Lecturer; + lecturerContext.setLecturer(lecturer); + groupContext.setGroup(undefined); } else { - let group = query.get("groupId"); + let groupId = query.get("groupId"); const localStorageLecturerId = getLocalStorageItem("groupId") - if(!group && localStorageLecturerId){ - group = localStorageLecturerId + if(!groupId && localStorageLecturerId){ + groupId = localStorageLecturerId history.replace("?groupId=" + localStorageLecturerId); } - const groupObj = list?.find((g) => g.id === group); - groupContextValue?.setGroup(groupObj); - lecturerContextValue?.setLecturer(null); + const group = list.find(x => x.id === groupId) as Group; + groupContext.setGroup(group); + lecturerContext.setLecturer(undefined); } - setOptions(prepareList(list || [])); + setOptions(prepareList(list)); }, [list, history, isLecturer, query]); - const onOptionChange = (option: {value: string, label: string}) => { - isLecturer ? lecturerContextValue?.setLecturer(option.value) : groupContextValue?.setGroup({ id : option.value, name : option.label }); - + const onOptionChange = (option: ListOption) => { if (isLecturer) { + const lecturer = list.find(x => x.id === option.value) as Lecturer; + lecturerContext.setLecturer(lecturer); history.push("?lecturerId=" + option.value); setLocalStorageItem("lecturerId", option.value) } else { + const group = list.find(x => x.id === option.value) as Group; + groupContext.setGroup(group); history.push("?groupId=" + option.value); setLocalStorageItem("groupId", option.value) } }; + const initialValue = - options.find((item: {value: string}) => - isLecturer ? item.value === lecturerContextValue?.lecturer : item.value === groupContextValue?.group?.id - ) ?? null; + options.find(item => + isLecturer ? item.value === lecturerContext.lecturer?.id : item.value === groupContext?.group?.id + ); + return (