From 8614c0a551dbf5eca40cbab5b6a89abe72644059 Mon Sep 17 00:00:00 2001 From: Semyon Okulov Date: Thu, 7 Sep 2023 16:50:33 +0700 Subject: [PATCH 1/3] =?UTF-8?q?feat(add-days-etc):=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BD=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/index-b3.3.html | 15 --- frontend/src/components/LessonCard.tsx | 32 ++++-- .../src/components/SubtitleWithBorder.tsx | 6 +- frontend/src/utils/formatLessonDate.ts | 5 + frontend/src/utils/isToday.ts | 8 ++ frontend/src/views/Schedule.tsx | 102 +++++++++++------- 6 files changed, 101 insertions(+), 67 deletions(-) delete mode 100644 frontend/index-b3.3.html create mode 100644 frontend/src/utils/isToday.ts diff --git a/frontend/index-b3.3.html b/frontend/index-b3.3.html deleted file mode 100644 index 6e2e7070..00000000 --- a/frontend/index-b3.3.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Имба дневник - - -
- - - diff --git a/frontend/src/components/LessonCard.tsx b/frontend/src/components/LessonCard.tsx index 74fe34fa..92aff687 100644 --- a/frontend/src/components/LessonCard.tsx +++ b/frontend/src/components/LessonCard.tsx @@ -1,6 +1,6 @@ -import { FC } from 'react'; +import {CSSProperties, FC} from 'react'; import { - Card, Group, Header, Placeholder, SimpleCell, + Card, Footnote, Group, Header, Placeholder, SimpleCell, } from '@vkontakte/vkui'; import { useRouteNavigator } from '@vkontakte/vk-mini-apps-router'; @@ -8,7 +8,7 @@ import { Day, Grade, Gradebook, LessonWorkType, Timetable, } from '../../../shared'; import setDefaultMark from '../utils/setDefaultMark'; -import { formatLessonDate } from '../utils/formatLessonDate'; +import { formatLessonDate, getDayOfWeek } from '../utils/formatLessonDate'; import { MODAL_PAGE_LESSON } from '../modals/ModalRoot'; @@ -17,6 +17,7 @@ import { useModal } from '../modals/ModalContext'; import SubtitleWithBorder from './SubtitleWithBorder'; import TimeRemaining from './TimeRemaining'; import Mark from './Mark'; +import {isToday} from "../utils/isToday.ts"; interface ILessonCard { lesson: Day; @@ -58,22 +59,35 @@ const LessonCard: FC = ({ lesson }) => { const lessonYear = lessonDate.getFullYear().toString(); const lessonMonth = (lessonDate.getMonth() + 1).toString().padStart(2, '0'); const lessonDay = lessonDate.getDate().toString().padStart(2, '0'); - + const lessonDayOfWeek = getDayOfWeek(lessonDate); + const isLessonToday = isToday(lessonDate); + const currentYear = currentDate.getFullYear().toString(); const currentMonth = (currentDate.getMonth() + 1).toString().padStart(2, '0'); const currentDay = currentDate.getDate().toString().padStart(2, '0'); const dayEnded = currentYear === lessonYear && currentMonth === lessonMonth && currentDay > lessonDay; - + + const displayDay = dayEnded ? ' День завершён' : isLessonToday ? 'Сегодня' : '' + const displayEndDayStyles = dayEnded && 'var(--vkui--color_icon_negative)'; + const displayCurrDayStyles = isLessonToday && 'var(--vkui--color_background_accent)'; + + const displayDayStyles: CSSProperties = { + color: displayEndDayStyles || displayCurrDayStyles || undefined, + padding: '3px 5px', + borderRadius: '5px', + border: `1px solid ${displayEndDayStyles || displayCurrDayStyles}` + } + return ( +
{displayDay}}> + {lessonDayOfWeek && `${lessonDayOfWeek}. `} {formattedLessonDate} - {dayEnded ? ' День завершён' : ''}
)} > @@ -88,9 +102,9 @@ const LessonCard: FC = ({ lesson }) => { subtitle={!name || (
-
+
{gradebook?.lessonType && ( - + {LessonWorkType[gradebook?.lessonType]} )} diff --git a/frontend/src/components/SubtitleWithBorder.tsx b/frontend/src/components/SubtitleWithBorder.tsx index a58cf2b8..e0269ff0 100644 --- a/frontend/src/components/SubtitleWithBorder.tsx +++ b/frontend/src/components/SubtitleWithBorder.tsx @@ -1,11 +1,12 @@ -import { FC, ReactNode } from 'react'; +import { CSSProperties, FC, ReactNode } from 'react'; interface ISubtitleWithBorder { children: ReactNode | string; color?: 'red' | 'green' | 'default'; + style?: CSSProperties; } -const SubtitleWithBorder: FC = ({ children, color = 'default' }) => { +const SubtitleWithBorder: FC = ({ children, color = 'default', style }) => { const getColorStyles = () => { switch (color) { case 'red': @@ -39,6 +40,7 @@ const SubtitleWithBorder: FC = ({ children, color = 'defaul display: 'inline-block', ...getColorStyles(), padding: '3px 5px', + ...style, }} > {children} diff --git a/frontend/src/utils/formatLessonDate.ts b/frontend/src/utils/formatLessonDate.ts index acb3758f..47793247 100644 --- a/frontend/src/utils/formatLessonDate.ts +++ b/frontend/src/utils/formatLessonDate.ts @@ -4,3 +4,8 @@ export const formatLessonDate = (dateString: Date | string) => { // @ts-ignore return new Date(dateString).toLocaleDateString(undefined, options); }; + +export function getDayOfWeek(date: Date) { + const daysOfWeek = ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб']; + return daysOfWeek[date.getDay()]; +} diff --git a/frontend/src/utils/isToday.ts b/frontend/src/utils/isToday.ts new file mode 100644 index 00000000..b78a94db --- /dev/null +++ b/frontend/src/utils/isToday.ts @@ -0,0 +1,8 @@ +export const isToday = (date: Date) => { + const today = new Date(); + return ( + date.getDate() === today.getDate() && + date.getMonth() === today.getMonth() && + date.getFullYear() === today.getFullYear() + ); +} diff --git a/frontend/src/views/Schedule.tsx b/frontend/src/views/Schedule.tsx index 75ae1db3..b8a60f3d 100644 --- a/frontend/src/views/Schedule.tsx +++ b/frontend/src/views/Schedule.tsx @@ -14,6 +14,7 @@ import { } from '@vkontakte/icons'; import { endOfWeek, startOfWeek } from '@vkontakte/vkui/dist/lib/date'; +import { debounce } from '@vkontakte/vkui/dist/lib/utils'; import { Day } from '../../../shared'; import { getLessons } from '../methods'; @@ -37,6 +38,8 @@ const Schedule: FC<{ id: string }> = ({ id }) => { 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; @@ -46,8 +49,8 @@ const Schedule: FC<{ id: string }> = ({ id }) => { }; const handleReloadData = async () => { - setIsError(false); setIsLoading(true); + setIsError(false); const newEndDate = new Date(endDate); newEndDate.setDate(newEndDate.getDate() + 7); @@ -73,6 +76,8 @@ const Schedule: FC<{ id: string }> = ({ id }) => { onActionClick: handleReloadData, }); console.error(error); + } finally { + setIsLoading(false); } }; @@ -136,6 +141,7 @@ const Schedule: FC<{ id: string }> = ({ id }) => { gettedLessons(); }, []); const sendToServerIfValid = async (start: Date, end: Date) => { + setIsLoading(true); if (start <= end) { const differenceInDays = (end.getTime() - start.getTime()) / (1000 * 3600 * 24); if (differenceInDays <= 14) { @@ -194,6 +200,7 @@ const Schedule: FC<{ id: string }> = ({ id }) => { localStorage.setItem('savedLessons', JSON.stringify(data)); } } + setIsLoading(false); }; const handleStartDateChange = (newStartDate: Date) => { @@ -212,36 +219,49 @@ const Schedule: FC<{ id: string }> = ({ id }) => { sendToServerIfValid(startDate, newEndDate); }; - const [lastClickTime, setLastClickTime] = useState(null); + const debouncedChangeWeek = debounce((direction: 'prev' | 'next') => { + const newStartDate = new Date(startDate); + const newEndDate = new Date(endDate); - const debouncedChangeWeek = (direction: 'prev' | 'next') => { - if (lastClickTime && Date.now() - lastClickTime <= 500) { - setTimeout(() => { - debouncedChangeWeek(direction); - }, 800); - } else { - setLastClickTime(Date.now()); - const newStartDate = new Date(startDate); - const newEndDate = new Date(endDate); - if (direction === 'prev') { - newStartDate.setDate(newStartDate.getDate() - 7); - newEndDate.setDate(newEndDate.getDate() - 7); - } else if (direction === 'next') { - newStartDate.setDate(newStartDate.getDate() + 7); - newEndDate.setDate(newEndDate.getDate() + 7); - } - setStartDate(newStartDate); - setEndDate(newEndDate); - sendToServerIfValid(newStartDate, newEndDate); + if (clickCount > 0) { + const weekDifference = clickCount * 7; + newStartDate.setDate(newStartDate.getDate() + weekDifference); + newEndDate.setDate(newEndDate.getDate() + weekDifference); + setClickCount(0); + } else if (direction === 'prev') { + newStartDate.setDate(newStartDate.getDate() - 7); + newEndDate.setDate(newEndDate.getDate() - 7); + } else if (direction === 'next') { + newStartDate.setDate(newStartDate.getDate() + 7); + newEndDate.setDate(newEndDate.getDate() + 7); + } + + setStartDate(newStartDate); + setEndDate(newEndDate); + + sendToServerIfValid(newStartDate, newEndDate); + }, 1); + + const handleButtonClick = (direction: 'prev' | 'next') => { + setClickCount((prevCount) => prevCount + 1); + + if (timeoutId) { + clearTimeout(timeoutId); } + + const newTimeoutId = setTimeout(() => { + debouncedChangeWeek(direction); + }, 1000); + + setTimeoutId(newTimeoutId); }; const Buttons = ( - - debouncedChangeWeek('prev')}> + + handleButtonClick('prev')}> - debouncedChangeWeek('next')}> + handleButtonClick('next')}> @@ -277,24 +297,24 @@ const Schedule: FC<{ id: string }> = ({ id }) => { onDateChange={handleEndDateChange} /> - {isLoading ? : ( - - - Период - {' '} - {weekString} - - )} - > + + + Период + {' '} + {weekString} + + )} + > + {isLoading ? : ( - - - )} + )} + + {isError && ( Date: Thu, 7 Sep 2023 16:52:18 +0700 Subject: [PATCH 2/3] feat(add-days-etc): codestyle --- frontend/src/modals/ModalRoot.tsx | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/src/modals/ModalRoot.tsx b/frontend/src/modals/ModalRoot.tsx index ad0c2110..624a99b7 100644 --- a/frontend/src/modals/ModalRoot.tsx +++ b/frontend/src/modals/ModalRoot.tsx @@ -142,24 +142,24 @@ const ModalRoot = () => { - {((lessonData.gradebook?.absenceType && lessonData.gradebook.absenceType === 'IsAbsent') || - (lessonData.gradebook?.tasks?.length && lessonData.gradebook.tasks.length > 0)) + {((lessonData.gradebook?.absenceType && lessonData.gradebook.absenceType === 'IsAbsent') + || (lessonData.gradebook?.tasks?.length && lessonData.gradebook.tasks.length > 0)) ? ( - Успеваемость}> - {lessonData.gradebook?.tasks?.map((tasks, index) => ( - (tasks.isRequired || (Grade[setDefaultMark(tasks)] !== 'Д')) && ( + Успеваемость}> + {lessonData.gradebook?.tasks?.map((tasks, index) => ( + (tasks.isRequired || (Grade[setDefaultMark(tasks)] !== 'Д')) && ( }> {LessonType[tasks.type]} - ) - ))} - {lessonData.gradebook?.absenceType === 'IsAbsent' && ( + ) + ))} + {lessonData.gradebook?.absenceType === 'IsAbsent' && ( }> Опоздание - )} - - ) : null} + )} + + ) : null} ); From b770133f2d2a6a29e38528a08627b78eb21a668f Mon Sep 17 00:00:00 2001 From: Semyon Okulov Date: Thu, 7 Sep 2023 16:56:29 +0700 Subject: [PATCH 3/3] =?UTF-8?q?feat(add-days-etc):=20=D0=BD=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=B8=D1=88=D0=B5=D0=BC=20=D0=BF=D0=B5=D1=80=D0=B8=D0=BE=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/Schedule.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/views/Schedule.tsx b/frontend/src/views/Schedule.tsx index b8a60f3d..fb386423 100644 --- a/frontend/src/views/Schedule.tsx +++ b/frontend/src/views/Schedule.tsx @@ -304,8 +304,6 @@ const Schedule: FC<{ id: string }> = ({ id }) => { aside={Buttons} mode='secondary' > - Период - {' '} {weekString} )}