From 32e49602f806c9a8dfc8418a0f6f9aa634512cf6 Mon Sep 17 00:00:00 2001 From: Semyon Okulov Date: Fri, 8 Sep 2023 18:22:07 +0700 Subject: [PATCH 1/3] feat(marks-by-day): updates --- frontend/src/components/MarksByGroup.tsx | 8 +-- frontend/src/components/UI/CalendarRange.tsx | 4 +- frontend/src/components/UI/Mark/index.css | 0 .../UI/{Mark.tsx => Mark/index.tsx} | 20 ++++-- .../src/components/UI/MarksByDay/index.css | 4 ++ .../src/components/UI/MarksByDay/index.tsx | 66 +++++++++++++++++++ frontend/src/methods/index.ts | 4 +- frontend/src/methods/server/getMarks.ts | 48 +++++++------- frontend/src/utils/calculateAverageMark.ts | 4 +- frontend/src/views/Schedule.tsx | 50 ++++++++++---- shared/index.ts | 2 +- 11 files changed, 157 insertions(+), 53 deletions(-) create mode 100644 frontend/src/components/UI/Mark/index.css rename frontend/src/components/UI/{Mark.tsx => Mark/index.tsx} (67%) create mode 100644 frontend/src/components/UI/MarksByDay/index.css create mode 100644 frontend/src/components/UI/MarksByDay/index.tsx diff --git a/frontend/src/components/MarksByGroup.tsx b/frontend/src/components/MarksByGroup.tsx index eae1ac95..c959c884 100644 --- a/frontend/src/components/MarksByGroup.tsx +++ b/frontend/src/components/MarksByGroup.tsx @@ -23,11 +23,11 @@ import { AbsenceType, Grade, PerformanceCurrent, TextMark, TMark, } from '../../../shared'; import { getPerformance } from '../methods'; - -import Mark from './UI/Mark'; import calculateAverageMark from '../utils/calculateAverageMark'; import { useSnackbar } from '../hooks'; +import Mark from './UI/Mark'; + const THIRD_SEC = 30 * 1000; const MarksByGroup = () => { @@ -84,7 +84,7 @@ const MarksByGroup = () => { subjectMarksMap[subjectName] = []; } - daysWithMarks.forEach((dayWithMark) => { + daysWithMarks?.forEach((dayWithMark) => { subjectMarksMap[subjectName].push({ date: new Date(dayWithMark.day).toLocaleDateString(), marks: dayWithMark.markValues, @@ -120,7 +120,7 @@ const MarksByGroup = () => { before={} style={{ marginTop: 5 }} after={calculateAverageMark( - marksForSubject.daysWithMarksForSubject[i].daysWithMarks.reduce( + marksForSubject?.daysWithMarksForSubject[i]?.daysWithMarks.reduce( (allMarks, day) => [...allMarks, ...day.markValues], [] as TextMark[], ), diff --git a/frontend/src/components/UI/CalendarRange.tsx b/frontend/src/components/UI/CalendarRange.tsx index 4617e38d..23a2ad2b 100644 --- a/frontend/src/components/UI/CalendarRange.tsx +++ b/frontend/src/components/UI/CalendarRange.tsx @@ -1,5 +1,5 @@ import React, { - FC, useRef, useState, useEffect, + FC, useRef, useState, useEffect, ReactNode, } from 'react'; import { Button, @@ -14,7 +14,7 @@ import { import PropTypes from 'prop-types'; interface CalendarRangeProps { - label: string; + label: string | ReactNode; onDateChange?: (newDate: Date) => void; value?: Date; } diff --git a/frontend/src/components/UI/Mark/index.css b/frontend/src/components/UI/Mark/index.css new file mode 100644 index 00000000..e69de29b diff --git a/frontend/src/components/UI/Mark.tsx b/frontend/src/components/UI/Mark/index.tsx similarity index 67% rename from frontend/src/components/UI/Mark.tsx rename to frontend/src/components/UI/Mark/index.tsx index 36e1fdae..a67146bb 100644 --- a/frontend/src/components/UI/Mark.tsx +++ b/frontend/src/components/UI/Mark/index.tsx @@ -1,13 +1,16 @@ import { CSSProperties, FC } from 'react'; -import { TMark } from '../../../../shared'; +import { Footnote } from '@vkontakte/vkui'; +import { TMark } from '../../../../../shared'; type Sizes = 'l' | 's'; interface IMark { mark: TMark; size?: Sizes; + bottom?: string; useMargin?: boolean; + style?: CSSProperties; } const getBackgroundColor = (score: TMark) => { @@ -19,7 +22,9 @@ const getBackgroundColor = (score: TMark) => { return '#DA0A35'; }; -const Mark: FC = ({ mark, size = 'l', useMargin = true }) => { +const Mark: FC = ({ + mark, size = 'l', useMargin = true, bottom, style, +}) => { const getSize = (size: Sizes) => { if (size === 's') { return '1rem'; @@ -39,8 +44,15 @@ const Mark: FC = ({ mark, size = 'l', useMargin = true }) => { display: 'inline-block', }; return ( -
- {mark} +
+
+ {mark} +
+ {bottom && ( + + {bottom} + + )}
); }; diff --git a/frontend/src/components/UI/MarksByDay/index.css b/frontend/src/components/UI/MarksByDay/index.css new file mode 100644 index 00000000..25a6e86d --- /dev/null +++ b/frontend/src/components/UI/MarksByDay/index.css @@ -0,0 +1,4 @@ +.marksByName { + display: flex; + margin-left: 10px; +} diff --git a/frontend/src/components/UI/MarksByDay/index.tsx b/frontend/src/components/UI/MarksByDay/index.tsx new file mode 100644 index 00000000..401cc977 --- /dev/null +++ b/frontend/src/components/UI/MarksByDay/index.tsx @@ -0,0 +1,66 @@ +import { FC } from 'react'; +import { + Group, Header, HorizontalCell, HorizontalScroll, +} from '@vkontakte/vkui'; + +import { Grade, PerformanceCurrent } from '../../../../../shared'; + +import Mark from '../Mark'; + +import './index.css'; + +interface YourComponentProps { + performanceData: PerformanceCurrent | null; +} + +const truncateString = (str: string, maxLength: number) => { + if (str.length > maxLength) { + return `${str.substring(0, maxLength)}...`; + } + return str; +}; + +const MarksByDay: FC = ({ performanceData }) => { + const marksByDay: { [key: string]: { grades: Grade[]; lessonName: string } } = {}; + + performanceData?.daysWithMarksForSubject.forEach((subject) => { + subject?.daysWithMarks?.forEach((dayWithMarks) => { + const day = new Date(dayWithMarks.day).toLocaleDateString(); + const grades = dayWithMarks.markValues.map((gradeText) => Grade[gradeText]); + const lessonName = subject.subjectName; + if (!marksByDay[day]) { + marksByDay[day] = { grades: [], lessonName: '' }; + } + + marksByDay[day].grades = [...marksByDay[day].grades, ...grades]; + marksByDay[day].lessonName = lessonName; + }); + }); + + return ( + i - 120} + getScrollToRight={(i) => i + 120} + > + Недавние оценки}> +
+ {Object.entries(marksByDay).map(([day, { grades, lessonName }], index) => ( +
+
{day}
+
+ {grades.map((grade, gradeIndex) => ( + + + + ))} +
+
+ ))} +
+
+
+ ); +}; + +export default MarksByDay; diff --git a/frontend/src/methods/index.ts b/frontend/src/methods/index.ts index 33ed7fac..92885cf4 100644 --- a/frontend/src/methods/index.ts +++ b/frontend/src/methods/index.ts @@ -6,8 +6,8 @@ import { getUserId } from './bridge/getUserId'; import { getPerformance } from './server/getPerformance.ts'; import { getLessons } from './server/getLessons'; -import { getMarks } from './server/getMarks'; +// import { getMarks } from './server/getMarks'; export { - getCookie, getMarks, getUserId, getLessons, appStorageSet, getPerformance, getVkStorageData, getVkStorageKeys, + getCookie, getUserId, getLessons, appStorageSet, getPerformance, getVkStorageData, getVkStorageKeys, }; diff --git a/frontend/src/methods/server/getMarks.ts b/frontend/src/methods/server/getMarks.ts index 88e11554..5b0a59a0 100644 --- a/frontend/src/methods/server/getMarks.ts +++ b/frontend/src/methods/server/getMarks.ts @@ -1,24 +1,24 @@ -import { IMark } from '../../../../shared'; - -import { getCookie } from '../bridge/getCookie'; -import { getUserId } from '../bridge/getUserId'; - -// TODO: возможно придётся удалить -export const getMarks = async (): Promise => { - const cookie = await getCookie(); - const id = await getUserId(); - - const response = await fetch(`${import.meta.env.VITE_SERVER_URL}/dashboard/${id}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json;charset=UTF-8', - secret: cookie as string, - }, - }); - - if (!response.ok) { - throw new Error('Failed to fetch lessons'); - } - - return await response.json() as IMark; -}; +// import { IMark } from '../../../../shared'; +// +// import { getCookie } from '../bridge/getCookie'; +// import { getUserId } from '../bridge/getUserId'; +// +// // TODO: возможно придётся удалить +// export const getMarks = async (): Promise => { +// const cookie = await getCookie(); +// const id = await getUserId(); +// +// const response = await fetch(`${import.meta.env.VITE_SERVER_URL}/dashboard/${id}`, { +// method: 'POST', +// headers: { +// 'Content-Type': 'application/json;charset=UTF-8', +// secret: cookie as string, +// }, +// }); +// +// if (!response.ok) { +// throw new Error('Failed to fetch lessons'); +// } +// +// return await response.json() as IMark; +// }; diff --git a/frontend/src/utils/calculateAverageMark.ts b/frontend/src/utils/calculateAverageMark.ts index aa295d4e..9102455b 100644 --- a/frontend/src/utils/calculateAverageMark.ts +++ b/frontend/src/utils/calculateAverageMark.ts @@ -1,7 +1,7 @@ import { Grade, TextMark } from '../../../shared'; -const calculateAverageMark = (marks: TextMark[]): number | null => { - if (marks.length === 0) { +const calculateAverageMark = (marks: TextMark[] | undefined): number | null => { + if (!marks || marks.length === 0) { return null; } diff --git a/frontend/src/views/Schedule.tsx b/frontend/src/views/Schedule.tsx index b89f442a..f4edf96a 100644 --- a/frontend/src/views/Schedule.tsx +++ b/frontend/src/views/Schedule.tsx @@ -13,8 +13,8 @@ import { } from '@vkontakte/icons'; import { addDays, endOfWeek, startOfWeek } from '@vkontakte/vkui/dist/lib/date'; -import { Day } from '../../../shared'; -import { getLessons } from '../methods'; +import { Day, PerformanceCurrent } from '../../../shared'; +import { getLessons, getPerformance } from '../methods'; import PanelHeaderWithBack from '../components/UI/PanelHeaderWithBack'; import Suspense from '../components/UI/Suspense'; @@ -22,11 +22,27 @@ import Suspense from '../components/UI/Suspense'; import { useSnackbar, useRateLimitExceeded } from '../hooks'; import ExplanationTooltip from '../components/UI/ExplanationTooltip'; +import MarksByDay from '../components/UI/MarksByDay'; const CalendarRange = lazy(() => import('../components/UI/CalendarRange')); const ScheduleGroup = lazy(() => import('../components/ScheduleGroup')); const Schedule: FC<{ id: string }> = ({ id }) => { + const [marksData, setMarksData] = useState(null); // State to hold marks data + + const fetchMarksData = async () => { + try { + const marks = await getPerformance(); + setMarksData(marks); + } catch (error) { + console.error(error); + } + }; + + useEffect(() => { + fetchMarksData(); + }, []); + const currentDate = new Date(); const [rateSnackbar, handleRateLimitExceeded] = useRateLimitExceeded(); @@ -365,18 +381,24 @@ const Schedule: FC<{ id: string }> = ({ id }) => { > - - - - + + Выбор даты} + description='Разница между датами не может быть больше 14-и дней' + > + + } + value={startDate} + onDateChange={handleStartDateChange} + /> + } + value={endDate} + onDateChange={handleEndDateChange} + /> + + Date: Fri, 8 Sep 2023 20:05:49 +0700 Subject: [PATCH 2/3] =?UTF-8?q?feat(marks-by-day):=20=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=20?= =?UTF-8?q?=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/index.ts | 2 +- frontend/src/components/LessonCard.tsx | 2 +- frontend/src/components/MarksByGroup.tsx | 20 +-- frontend/src/components/UI/Mark/index.tsx | 2 +- .../src/components/UI/MarksByDay/index.tsx | 6 +- frontend/src/components/UI/Sidebar.tsx | 6 +- frontend/src/components/UI/Tabbar.tsx | 6 +- frontend/src/methods/server/getPerformance.ts | 7 +- frontend/src/views/Schedule.tsx | 130 ++++++++++++------ 9 files changed, 118 insertions(+), 63 deletions(-) diff --git a/backend/index.ts b/backend/index.ts index 88e1b757..43cac2f5 100644 --- a/backend/index.ts +++ b/backend/index.ts @@ -22,7 +22,7 @@ app.use(express.json()) const limiter = rateLimit({ windowMs: FIFTEEN_MINS_IN_MS, - max: 60, + max: 80, statusCode: 429, skipFailedRequests: true, message: 'LIMIT' diff --git a/frontend/src/components/LessonCard.tsx b/frontend/src/components/LessonCard.tsx index 5a8ebbbc..4d433755 100644 --- a/frontend/src/components/LessonCard.tsx +++ b/frontend/src/components/LessonCard.tsx @@ -135,7 +135,7 @@ const LessonCard: FC = ({ lesson }) => { {timetable.teacher?.middleName[0]} .
-
+
{gradebook?.tasks?.map((task, index) => ( (task.isRequired || (Grade[setDefaultMark(task)] !== 'Д')) && ( { if (!lastFetchTime || Date.now() - Number(lastFetchTime) >= THIRD_SEC || isHandle) { const marks = await getPerformance(); - localStorage.setItem('marks', JSON.stringify(marks)); + localStorage.setItem('savedMarks', JSON.stringify(marks)); localStorage.setItem('lastFetchTime', String(Date.now())); - setMarksForSubject(marks); + setMarksForSubject(marks as PerformanceCurrent); } else { showSnackbar({ title: 'Оценки взяты из кеша', @@ -54,10 +54,6 @@ const MarksByGroup = () => { action: 'Загрузить новые', icon: , }); - const cachedMarks = localStorage.getItem('marks'); - if (cachedMarks) { - setMarksForSubject(JSON.parse(cachedMarks)); - } } setIsLoading(false); @@ -74,7 +70,15 @@ const MarksByGroup = () => { }; useEffect(() => { - fetchMarks(); + const cachedMarks = localStorage.getItem('savedMarks'); + + if (cachedMarks) { + if (cachedMarks) { + setMarksForSubject(JSON.parse(cachedMarks)); + } + } else { + fetchMarks(); + } }, []); const subjectMarksMap: Record = {}; @@ -120,7 +124,7 @@ const MarksByGroup = () => { before={} style={{ marginTop: 5 }} after={calculateAverageMark( - marksForSubject?.daysWithMarksForSubject[i]?.daysWithMarks.reduce( + marksForSubject.daysWithMarksForSubject[i].daysWithMarks?.reduce( (allMarks, day) => [...allMarks, ...day.markValues], [] as TextMark[], ), diff --git a/frontend/src/components/UI/Mark/index.tsx b/frontend/src/components/UI/Mark/index.tsx index a67146bb..116fbd08 100644 --- a/frontend/src/components/UI/Mark/index.tsx +++ b/frontend/src/components/UI/Mark/index.tsx @@ -49,7 +49,7 @@ const Mark: FC = ({ {mark}
{bottom && ( - + {bottom} )} diff --git a/frontend/src/components/UI/MarksByDay/index.tsx b/frontend/src/components/UI/MarksByDay/index.tsx index 401cc977..9e065b85 100644 --- a/frontend/src/components/UI/MarksByDay/index.tsx +++ b/frontend/src/components/UI/MarksByDay/index.tsx @@ -9,7 +9,7 @@ import Mark from '../Mark'; import './index.css'; -interface YourComponentProps { +interface IPerformanceCurrent { performanceData: PerformanceCurrent | null; } @@ -20,10 +20,10 @@ const truncateString = (str: string, maxLength: number) => { return str; }; -const MarksByDay: FC = ({ performanceData }) => { +const MarksByDay: FC = ({ performanceData }) => { const marksByDay: { [key: string]: { grades: Grade[]; lessonName: string } } = {}; - performanceData?.daysWithMarksForSubject.forEach((subject) => { + performanceData?.daysWithMarksForSubject?.length !== undefined && performanceData?.daysWithMarksForSubject?.length > 0 && performanceData?.daysWithMarksForSubject.forEach((subject) => { subject?.daysWithMarks?.forEach((dayWithMarks) => { const day = new Date(dayWithMarks.day).toLocaleDateString(); const grades = dayWithMarks.markValues.map((gradeText) => Grade[gradeText]); diff --git a/frontend/src/components/UI/Sidebar.tsx b/frontend/src/components/UI/Sidebar.tsx index f284ed9e..fb6dcc36 100644 --- a/frontend/src/components/UI/Sidebar.tsx +++ b/frontend/src/components/UI/Sidebar.tsx @@ -5,7 +5,7 @@ import { import { Icon28GraphOutline, Icon28SettingsOutline, - Icon28BookSpreadOutline, + Icon28HomeOutline, Icon28HelpOutline, } from '@vkontakte/icons'; @@ -31,9 +31,9 @@ const Sidebar: FC = ({ activeView, onStoryChange }) => ( disabled={activeView === VIEW_SCHEDULE} onClick={() => onStoryChange(VIEW_SCHEDULE)} style={activeView === VIEW_SCHEDULE ? activeStoryStyles : undefined} - before={} + before={} > - Расписание + Главная = ({ onStoryChange, activeView }) => { onClick={() => onStoryChange(VIEW_SCHEDULE)} selected={activeView === VIEW_SCHEDULE} data-story={VIEW_SCHEDULE} - text='Расписание' + text='Главная' > - + onStoryChange(VIEW_MARKS)} diff --git a/frontend/src/methods/server/getPerformance.ts b/frontend/src/methods/server/getPerformance.ts index d63d0f27..b1c6e88a 100644 --- a/frontend/src/methods/server/getPerformance.ts +++ b/frontend/src/methods/server/getPerformance.ts @@ -2,7 +2,7 @@ import { PerformanceCurrent } from '../../../../shared'; import { getCookie } from '../bridge/getCookie'; import { getUserId } from '../bridge/getUserId'; -export const getPerformance = async (): Promise => { +export const getPerformance = async (): Promise => { const cookie = await getCookie(); const id = await getUserId(); console.log('getUserId', id); @@ -15,6 +15,11 @@ export const getPerformance = async (): Promise => { }, }); + if (response.status === 429) { + console.log(response.status); + return response.status; + } + if (!response.ok) { throw new Error('Failed to fetch lessons'); } diff --git a/frontend/src/views/Schedule.tsx b/frontend/src/views/Schedule.tsx index f4edf96a..f538ec73 100644 --- a/frontend/src/views/Schedule.tsx +++ b/frontend/src/views/Schedule.tsx @@ -2,14 +2,13 @@ import { FC, lazy, useEffect, useState, } from 'react'; import { - Button, - ButtonGroup, Group, Header, IconButton, Link, - Panel, PanelSpinner, Placeholder, View, + Button, ButtonGroup, Group, Header, IconButton, Link, Panel, PanelSpinner, Placeholder, View, } from '@vkontakte/vkui'; import { useActiveVkuiLocation, useRouteNavigator } from '@vkontakte/vk-mini-apps-router'; import { Icon16ArrowRightOutline, Icon16ArrowLeftOutline, + Icon28ErrorCircleOutline, } from '@vkontakte/icons'; import { addDays, endOfWeek, startOfWeek } from '@vkontakte/vkui/dist/lib/date'; @@ -28,23 +27,10 @@ const CalendarRange = lazy(() => import('../components/UI/CalendarRange')); const ScheduleGroup = lazy(() => import('../components/ScheduleGroup')); const Schedule: FC<{ id: string }> = ({ id }) => { - const [marksData, setMarksData] = useState(null); // State to hold marks data - - const fetchMarksData = async () => { - try { - const marks = await getPerformance(); - setMarksData(marks); - } catch (error) { - console.error(error); - } - }; - - useEffect(() => { - fetchMarksData(); - }, []); - const currentDate = new Date(); + const [marksData, setMarksData] = useState(null); + const [isMarksLoading, setIsMarksLoading] = useState(false); const [rateSnackbar, handleRateLimitExceeded] = useRateLimitExceeded(); const [snackbar, showSnackbar] = useSnackbar(); const [isCurrent, setIsCurrent] = useState(() => { @@ -77,6 +63,7 @@ const Schedule: FC<{ id: string }> = ({ id }) => { const handleReloadData = async () => { setIsLoading(true); + setIsMarksLoading(true); setIsError(false); localStorage.setItem('isCurrent', JSON.stringify(true)); setIsCurrent(true); @@ -85,64 +72,77 @@ const Schedule: FC<{ id: string }> = ({ id }) => { try { const data = await getLessons(startDate, newEndDate); - + const marks = await getPerformance(); + console.log(marks); if (data === 429) { handleRateLimitExceeded(); setIsLoading(false); return; } + if (marks === 429) { + handleRateLimitExceeded(); + setIsMarksLoading(false); + return; + } + + setMarksData(marks as PerformanceCurrent); setLessons(data as Day[]); updateDatesFromData(data as Day[]); localStorage.setItem('savedLessons', JSON.stringify(data)); + localStorage.setItem('savedMarks', JSON.stringify(marks)); } catch (error) { setIsError(true); showSnackbar({ - title: 'Ошибка при попытке получить расписание', + title: 'Ошибка при попытке получить новые данные', action: 'Повторить', onActionClick: handleReloadData, }); console.error(error); } finally { setIsLoading(false); + setIsMarksLoading(false); } }; useEffect(() => { const savedLessons = localStorage.getItem('savedLessons'); + const savedMarks = localStorage.getItem('savedMarks'); const getLastRequestTime = localStorage.getItem('lastRequestTime'); const currentTime = Date.now(); const lastRequestTime = getLastRequestTime ? parseInt(getLastRequestTime, 10) : 0; const timeSinceLastRequest = currentTime - lastRequestTime; - + console.log('savedMarks', savedMarks); const gettedLessons = async () => { setIsLoading(true); setIsError(false); + + if (savedLessons || timeSinceLastRequest < 30000) { + showSnackbar({ + layout: 'vertical', + action: 'Загрузить новые', + onActionClick: handleReloadData, + title: 'Данные взяты из кеша', + }); + setIsLoading(false); + return; + } + try { - if (!savedLessons || timeSinceLastRequest > 30000) { - const data = await getLessons(startDate, endDate); + const data = await getLessons(startDate, endDate); - if (data === 429) { - handleRateLimitExceeded(); - setIsLoading(false); - return; - } + if (data === 429) { + handleRateLimitExceeded(); + setIsLoading(false); + return; + } - setLessons(data as Day[]); + setLessons(data as Day[]); - localStorage.setItem('savedLessons', JSON.stringify(data)); - localStorage.setItem('lastRequestTime', currentTime.toString()); + localStorage.setItem('lastRequestTime', currentTime.toString()); - updateDatesFromData(data as Day[]); - } else { - showSnackbar({ - layout: 'vertical', - action: 'Загрузить новые', - onActionClick: handleReloadData, - title: 'Данные взяты из кеша', - }); - } + updateDatesFromData(data as Day[]); } catch (error) { setIsError(true); getError(); @@ -162,8 +162,52 @@ const Schedule: FC<{ id: string }> = ({ id }) => { setEndDate(endOfWeek(lastLessonDate)); } + if (savedMarks) { + setMarksData(JSON.parse(savedMarks)); + setIsMarksLoading(false); + } + + const fetchMarksData = async () => { + setIsMarksLoading(true); + + if (savedMarks) { + showSnackbar({ + layout: 'vertical', + action: 'Загрузить новые', + onActionClick: handleReloadData, + title: 'Данные взяты из кеша', + }); + setIsMarksLoading(false); + return; + } + + try { + const marks = await getPerformance(); + if (marks === 429) { + handleRateLimitExceeded(); + setIsLoading(false); + return; + } + + setMarksData(marks as PerformanceCurrent); + localStorage.setItem('savedMarks', JSON.stringify(marks)); + } catch (error) { + console.error(error); + showSnackbar({ + title: 'Ошибка при попытке получить оценки', + action: 'Повторить', + icon: , + onActionClick: fetchMarksData, + }); + } finally { + setIsMarksLoading(false); + } + }; + gettedLessons(); + fetchMarksData(); }, []); + const sendToServerIfValid = async (start: Date, end: Date) => { setIsLoading(true); setIsCurrent(false); @@ -380,8 +424,10 @@ const Schedule: FC<{ id: string }> = ({ id }) => { onSwipeBack={() => routeNavigator.back()} > - - + + + {isMarksLoading ? : } + Выбор даты} description='Разница между датами не может быть больше 14-и дней' From 82eb73fb19a998f2f7d21b471fc748ed0ecd8375 Mon Sep 17 00:00:00 2001 From: Semyon Okulov Date: Fri, 8 Sep 2023 20:08:24 +0700 Subject: [PATCH 3/3] feat(marks-by-day): updates --- frontend/src/views/Schedule.tsx | 46 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/frontend/src/views/Schedule.tsx b/frontend/src/views/Schedule.tsx index f538ec73..520f9b14 100644 --- a/frontend/src/views/Schedule.tsx +++ b/frontend/src/views/Schedule.tsx @@ -38,29 +38,6 @@ const Schedule: FC<{ id: string }> = ({ id }) => { return storedIsCurrent ? JSON.parse(storedIsCurrent) : true; }); - const getError = () => showSnackbar({ - title: 'Ошибка при попытке получить расписание', - action: 'Повторить', - onActionClick: handleReloadData, - }); - - const { panel: activePanel, panelsHistory } = useActiveVkuiLocation(); - const routeNavigator = useRouteNavigator(); - const [lessonsState, setLessons] = useState(); - const [startDate, setStartDate] = useState(startOfWeek(currentDate)); - const [endDate, setEndDate] = useState(endOfWeek(currentDate)); - const [isLoading, setIsLoading] = useState(false); - const [isError, setIsError] = useState(false); - const [clickCount, setClickCount] = useState(0); - const [timeoutId, setTimeoutId] = useState(null); - - const updateDatesFromData = (data: Day[]) => { - const firstLessonDate = data && data.length > 0 ? new Date(data[0].date) : startDate; - const lastLessonDate = data && data.length > 0 ? new Date(data[data.length - 1].date) : endDate; - setStartDate(startOfWeek(firstLessonDate)); - setEndDate(endOfWeek(lastLessonDate)); - }; - const handleReloadData = async () => { setIsLoading(true); setIsMarksLoading(true); @@ -106,6 +83,29 @@ const Schedule: FC<{ id: string }> = ({ id }) => { } }; + const getError = () => showSnackbar({ + title: 'Ошибка при попытке получить расписание', + action: 'Повторить', + onActionClick: handleReloadData, + }); + + const { panel: activePanel, panelsHistory } = useActiveVkuiLocation(); + const routeNavigator = useRouteNavigator(); + const [lessonsState, setLessons] = useState(); + const [startDate, setStartDate] = useState(startOfWeek(currentDate)); + const [endDate, setEndDate] = useState(endOfWeek(currentDate)); + const [isLoading, setIsLoading] = useState(false); + const [isError, setIsError] = useState(false); + const [clickCount, setClickCount] = useState(0); + const [timeoutId, setTimeoutId] = useState(null); + + const updateDatesFromData = (data: Day[]) => { + const firstLessonDate = data && data.length > 0 ? new Date(data[0].date) : startDate; + const lastLessonDate = data && data.length > 0 ? new Date(data[data.length - 1].date) : endDate; + setStartDate(startOfWeek(firstLessonDate)); + setEndDate(endOfWeek(lastLessonDate)); + }; + useEffect(() => { const savedLessons = localStorage.getItem('savedLessons'); const savedMarks = localStorage.getItem('savedMarks');