diff --git a/src/app.tsx b/src/app.tsx index 6087672..82cb40d 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -2,16 +2,13 @@ import React from 'react'; import { Helmet } from 'react-helmet'; import { Global } from '@emotion/react' import { BrowserRouter } from 'react-router-dom'; -import ruLocale from 'dayjs/locale/ru'; -import dayjs from 'dayjs'; +import dayjs from './utils/dayjs-config'; import { useTranslation } from 'react-i18next'; import { ChakraProvider, ColorModeScript, extendTheme } from '@chakra-ui/react' import { Dashboard } from './dashboard'; import { globalStyles } from './global.styles'; -dayjs.locale('ru', ruLocale); - // Расширяем тему Chakra UI const theme = extendTheme({ config: { diff --git a/src/pages/attendance/components/AddDataDialog.tsx b/src/pages/attendance/components/AddDataDialog.tsx index 6bc23b0..1a4152a 100644 --- a/src/pages/attendance/components/AddDataDialog.tsx +++ b/src/pages/attendance/components/AddDataDialog.tsx @@ -21,7 +21,8 @@ import { useColorMode, } from "@chakra-ui/react"; import { useTranslation } from 'react-i18next'; -import dayjs from 'dayjs'; +import dayjs from "../../../utils/dayjs-config"; +import { formatDate } from "../../../utils/dayjs-config"; import UserSelect from "../../../components/user-select"; interface AttendanceEntry { @@ -41,7 +42,7 @@ const AddDataDialog = ({ isOpen, onClose, onAddData }: AddDataDialogProps) => { const { colorMode } = useColorMode(); const { t } = useTranslation(); const [name, setName] = useState(""); - const [date, setDate] = useState(dayjs().format('YYYY-MM-DD')); + const [date, setDate] = useState(formatDate(dayjs().toDate(), 'YYYY-MM-DD')); const [selectedStudents, setSelectedStudents] = useState([]); const [selectedTeachers, setSelectedTeachers] = useState([]); @@ -60,7 +61,7 @@ const AddDataDialog = ({ isOpen, onClose, onAddData }: AddDataDialogProps) => { const resetForm = () => { setName(""); - setDate(dayjs().format('YYYY-MM-DD')); + setDate(formatDate(dayjs().toDate(), 'YYYY-MM-DD')); setSelectedStudents([]); setSelectedTeachers([]); }; diff --git a/src/pages/attendance/components/AttendanceTable.tsx b/src/pages/attendance/components/AttendanceTable.tsx index a3206d0..eb690ec 100644 --- a/src/pages/attendance/components/AttendanceTable.tsx +++ b/src/pages/attendance/components/AttendanceTable.tsx @@ -33,6 +33,7 @@ import { useTranslation } from 'react-i18next' import { getGravatarURL } from '../../../utils/gravatar' import { ShortText } from './ShortText' import { AttendanceData } from '../hooks' +import { formatDate } from '../../../utils/dayjs-config' interface AttendanceTableProps { data: AttendanceData @@ -120,7 +121,7 @@ export const AttendanceTable: React.FC = ({ data }) => { }) // Добавляем дату - row.push(dayjs(lesson.date).format('DD.MM.YYYY')) + row.push(formatDate(lesson.date, 'DD.MM.YYYY')) // Добавляем полное название занятия (без сокращений) row.push(lesson.name) @@ -230,7 +231,7 @@ export const AttendanceTable: React.FC = ({ data }) => { ) })} - {dayjs(lesson.date).format('DD.MM.YYYY')} + {formatDate(lesson.date, 'DD.MM.YYYY')} {data.students.map((st) => { diff --git a/src/pages/course-list/course-card.tsx b/src/pages/course-list/course-card.tsx index dc5f952..14a9519 100644 --- a/src/pages/course-list/course-card.tsx +++ b/src/pages/course-list/course-card.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useState, useMemo } from 'react' +import { formatDate } from '../../utils/dayjs-config' import dayjs from 'dayjs' import { Link as ConnectedLink, generatePath } from 'react-router-dom' import { getNavigationValue } from '@brojs/cli' @@ -231,7 +232,7 @@ export const CourseCard = ({ course }: { course: Course }) => { - {dayjs(course.startDt).format('DD.MM.YYYY')} + {formatDate(course.startDt, 'DD.MM.YYYY')} @@ -243,7 +244,7 @@ export const CourseCard = ({ course }: { course: Course }) => { - {dayjs(course.startDt).format('DD.MM.YYYY')} + {formatDate(course.startDt, 'DD.MM.YYYY')} @@ -311,10 +312,12 @@ export const CourseCard = ({ course }: { course: Course }) => { {populatedCourse.data?.lessons .filter(lesson => dayjs(lesson.date).isAfter(dayjs())) .sort((a, b) => dayjs(a.date).valueOf() - dayjs(b.date).valueOf())[0]?.date - ? dayjs(populatedCourse.data?.lessons - .filter(lesson => dayjs(lesson.date).isAfter(dayjs())) - .sort((a, b) => dayjs(a.date).valueOf() - dayjs(b.date).valueOf())[0]?.date) - .format('DD.MM.YYYY') + ? formatDate( + populatedCourse.data?.lessons + .filter(lesson => dayjs(lesson.date).isAfter(dayjs())) + .sort((a, b) => dayjs(a.date).valueOf() - dayjs(b.date).valueOf())[0]?.date, + 'DD.MM.YYYY' + ) : t('journal.pl.common.noData') } @@ -455,7 +458,7 @@ export const CourseCard = ({ course }: { course: Course }) => { - {dayjs(lesson.date).format('DD.MM.YYYY')} + {formatDate(lesson.date, 'DD.MM.YYYY')} {isPast && lessonAttendance && ( void) => { getValues, } = useForm({ defaultValues: { - startDt: dayjs().format('YYYY-MM-DD'), + startDt: formatDate(dayjs().toDate(), 'YYYY-MM-DD'), name: t('journal.pl.course.defaultName'), }, }) diff --git a/src/pages/course-list/hooks/useGroupedCourses.ts b/src/pages/course-list/hooks/useGroupedCourses.ts index c5098ab..6329b72 100644 --- a/src/pages/course-list/hooks/useGroupedCourses.ts +++ b/src/pages/course-list/hooks/useGroupedCourses.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react' -import dayjs from 'dayjs' +import dayjs, { formatDate } from '../../../utils/dayjs-config' import { Course } from '../../../__data__/model' /** @@ -20,7 +20,7 @@ export const useGroupedCourses = (courses?: Course[]) => { // Группируем по годам sortedCourses.forEach(course => { - const year = dayjs(course.startDt).format('YYYY') + const year = formatDate(course.startDt, 'YYYY') if (!grouped[year]) { grouped[year] = [] } diff --git a/src/pages/lesson-details.tsx b/src/pages/lesson-details.tsx index 5699f00..25196c2 100644 --- a/src/pages/lesson-details.tsx +++ b/src/pages/lesson-details.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useRef, useMemo } from 'react' import { useParams, Link } from 'react-router-dom' -import dayjs from 'dayjs' import QRCode from 'qrcode' import { sha256 } from 'js-sha256' import { getConfigValue, getNavigationValue } from '@brojs/cli' @@ -21,6 +20,7 @@ import { useTranslation } from 'react-i18next' import { api } from '../__data__/api/api' import { User } from '../__data__/model' import { UserCard } from '../components/user-card' +import { formatDate } from '../utils/dayjs-config' import { QRCanvas, @@ -209,8 +209,8 @@ const LessonDetail = () => { borderRadius="xl" bg={colorMode === "light" ? "gray.50" : "gray.700"} boxShadow="md" - > - {dayjs(accessCode?.body?.lesson?.date).format(t('journal.pl.lesson.dateFormat'))}{' '} + > + {formatDate(accessCode?.body?.lesson?.date, t('journal.pl.lesson.dateFormat'))}{' '} {t('journal.pl.common.marked')} - {accessCode?.body?.lesson?.students?.length}{' '} {AllStudents.isSuccess ? `/ ${AllStudents?.data?.body?.length}` diff --git a/src/pages/lesson-list/components/item.tsx b/src/pages/lesson-list/components/item.tsx index 58fa5ee..df92be0 100644 --- a/src/pages/lesson-list/components/item.tsx +++ b/src/pages/lesson-list/components/item.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react' -import dayjs from 'dayjs' +import { formatDate } from '../../../utils/dayjs-config' import { Link } from 'react-router-dom' import { getNavigationValue, getFeatures } from '@brojs/cli' import { @@ -133,7 +133,7 @@ export const Item: React.FC = ({ <> {name} - {dayjs(date).format(groupByDate ? 'HH:mm' : 'HH:mm DD.MM.YY')} + {formatDate(date, groupByDate ? 'HH:mm' : 'HH:mm DD.MM.YY')} @@ -193,7 +193,7 @@ export const Item: React.FC = ({ )} - {dayjs(date).format(groupByDate ? 'HH:mm' : 'HH:mm DD.MM.YY')} + {formatDate(date, groupByDate ? 'HH:mm' : 'HH:mm DD.MM.YY')} {name} {isTeacher && ( diff --git a/src/pages/lesson-list/components/lesson-items.tsx b/src/pages/lesson-list/components/lesson-items.tsx index 109918f..ee9bca0 100644 --- a/src/pages/lesson-list/components/lesson-items.tsx +++ b/src/pages/lesson-list/components/lesson-items.tsx @@ -1,5 +1,5 @@ import React from 'react' -import dayjs from 'dayjs' +import { formatDate } from '../../../utils/dayjs-config' import { Tr, Td, @@ -45,7 +45,7 @@ export const LessonItems: React.FC = ({ borderRadius="md" _dark={{ bg: "gray.700" }} > - {dayjs(date).format('DD MMMM YYYY')} + {formatDate(date, 'DD MMMM YYYY')} )} {lessons.map((lesson) => ( @@ -78,7 +78,7 @@ export const LessonItems: React.FC = ({ {date && ( - {dayjs(date).format('DD MMMM YYYY')} + {formatDate(date, 'DD MMMM YYYY')} )} diff --git a/src/pages/lesson-list/components/lessons-form.tsx b/src/pages/lesson-list/components/lessons-form.tsx index c5a877c..acdf034 100644 --- a/src/pages/lesson-list/components/lessons-form.tsx +++ b/src/pages/lesson-list/components/lessons-form.tsx @@ -30,6 +30,7 @@ import { AddIcon, CheckIcon, WarningIcon, RepeatIcon } from '@chakra-ui/icons' import { useTranslation } from 'react-i18next' import { FaRobot } from 'react-icons/fa' import dayjs from 'dayjs' +import { formatDate } from '../../../utils/dayjs-config' import { dateToCalendarFormat } from '../../../utils/time' import { Lesson } from '../../../__data__/model' @@ -294,7 +295,7 @@ export const LessonForm = ({ {isSelected && } - {dayjs(suggestion.date).format('DD.MM.YYYY HH:mm')} + {formatDate(suggestion.date, 'DD.MM.YYYY HH:mm')} ); diff --git a/src/pages/lesson-list/components/statistics.tsx b/src/pages/lesson-list/components/statistics.tsx index 8b11bf1..d606f09 100644 --- a/src/pages/lesson-list/components/statistics.tsx +++ b/src/pages/lesson-list/components/statistics.tsx @@ -1,5 +1,6 @@ import React, { useMemo } from 'react' import dayjs from 'dayjs' +import { formatDate } from '../../../utils/dayjs-config' import { Box, Heading, @@ -45,7 +46,7 @@ export const CourseStatistics: React.FC = ({ lessons = [] // Вычисляем статистику курса const stats = useMemo(() => { - if (!lessons.length) { + if (!lessons || lessons.length === 0) { return { totalLessons: 0, completedLessons: 0, @@ -215,10 +216,10 @@ export const CourseStatistics: React.FC = ({ lessons = [] {stats.attendanceTrend !== 0 && ( 0 ? 'increase' : 'decrease'} + type={Number(stats.attendanceTrend) > 0 ? 'increase' : 'decrease'} /> - {Math.abs(Math.round(stats.attendanceTrend))}% + {Math.abs(Math.round(Number(stats.attendanceTrend)))}% )} @@ -261,7 +262,7 @@ export const CourseStatistics: React.FC = ({ lessons = [] {stats.nextLessonDate - ? dayjs(stats.nextLessonDate).format('DD.MM.YYYY') + ? formatDate(stats.nextLessonDate, 'DD.MM.YYYY') : t('journal.pl.statistics.noUpcoming') } diff --git a/src/pages/lesson-list/lesson-list.tsx b/src/pages/lesson-list/lesson-list.tsx index 8a00576..6b69c85 100644 --- a/src/pages/lesson-list/lesson-list.tsx +++ b/src/pages/lesson-list/lesson-list.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useMemo, useRef, useState } from 'react' -import dayjs from 'dayjs' +import dayjs, { formatDate } from '../../utils/dayjs-config' import { generatePath, Link, useParams } from 'react-router-dom' import { getNavigationValue, getFeatures } from '@brojs/cli' import { @@ -277,7 +277,7 @@ const LessonList = () => { - {t('journal.pl.lesson.deleteConfirm', { date: dayjs(lessonToDelete?.date).format('DD.MM.YY') })} + {t('journal.pl.lesson.deleteConfirm', { date: formatDate(lessonToDelete?.date, 'DD.MM.YY') })} diff --git a/src/pages/user-page.tsx b/src/pages/user-page.tsx index ebddd0e..ccdfbf6 100644 --- a/src/pages/user-page.tsx +++ b/src/pages/user-page.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import { motion, AnimatePresence } from 'framer-motion' import { api } from '../__data__/api/api' -import dayjs from 'dayjs' +import { formatDate } from '../utils/dayjs-config' import { Alert, AlertIcon, @@ -145,7 +145,7 @@ const UserPage = () => { - {dayjs(ls.data?.body?.date).format(t('journal.pl.lesson.dateFormat'))} + {formatDate(ls.data?.body?.date, t('journal.pl.lesson.dateFormat'))} diff --git a/src/utils/dayjs-config.ts b/src/utils/dayjs-config.ts new file mode 100644 index 0000000..7392238 --- /dev/null +++ b/src/utils/dayjs-config.ts @@ -0,0 +1,30 @@ +import dayjs from 'dayjs'; +import 'dayjs/locale/ru'; +import 'dayjs/locale/en'; +import i18next from 'i18next'; + +// Функция для обновления локали dayjs при изменении языка в i18next +export const updateDayjsLocale = () => { + const currentLocale = i18next.language; + + // Убедимся, что локаль поддерживается, иначе используем 'en' + const locale = ['ru', 'en'].includes(currentLocale) ? currentLocale : 'en'; + + // Установим локаль для dayjs + dayjs.locale(locale); +}; + +// Слушаем изменения языка и обновляем локаль dayjs +i18next.on('languageChanged', () => { + updateDayjsLocale(); +}); + +// Вызываем функцию инициализации при импорте +updateDayjsLocale(); + +// Хелпер для форматирования даты с учетом текущей локали +export const formatDate = (date: string | Date | number, format = 'DD.MM.YYYY') => { + return dayjs(date).format(format); +}; + +export default dayjs; \ No newline at end of file diff --git a/src/utils/time.ts b/src/utils/time.ts index 5806637..21c84c8 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -1,3 +1,3 @@ -import dayjs from "dayjs"; +import dayjs, { formatDate } from "./dayjs-config"; -export const dateToCalendarFormat = (date?: string) => dayjs(date).format('YYYY-MM-DDTHH:mm') +export const dateToCalendarFormat = (date?: string) => formatDate(date, 'YYYY-MM-DDTHH:mm')