diff --git a/locales/en.json b/locales/en.json index 349ec5f..e196c3e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -11,7 +11,6 @@ "journal.pl.common.edit": "Edit", "journal.pl.common.delete": "Delete", "journal.pl.common.save": "Save", - "journal.pl.common.cancel": "Cancel", "journal.pl.common.students": "students", "journal.pl.common.teachers": "teachers", "journal.pl.common.date": "Date", @@ -31,7 +30,7 @@ "journal.pl.common.cancel": "Cancel", "journal.pl.common.journal": "Journal", "journal.pl.common.course": "Course", - "journal.pl.common.lesson": "Lesson", + "journal.pl.common.lesson": "Lessons", "journal.pl.common.marked": "Marked", "journal.pl.common.people": "people", "journal.pl.common.success": "Success", @@ -75,6 +74,11 @@ "journal.pl.lesson.action": "Actions", "journal.pl.lesson.expand": "Expand lesson list", "journal.pl.lesson.collapse": "Collapse lesson list", + "journal.pl.lesson.aiSuggested": "AI Suggested Lessons", + "journal.pl.lesson.aiSuggestedDescription": "These lessons were automatically generated based on your course schedule", + "journal.pl.lesson.createFromSuggestion": "Create", + "journal.pl.lesson.aiGenerated": "AI generated content", + "journal.pl.lesson.generatingAiSuggestions": "Generating AI lesson suggestions...", "journal.pl.exam.title": "Exam", "journal.pl.exam.startExam": "Start exam", diff --git a/locales/ru.json b/locales/ru.json index 21a246b..8df1162 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -27,7 +27,7 @@ "journal.pl.common.cancel": "Отмена", "journal.pl.common.journal": "Журнал", "journal.pl.common.course": "Курс", - "journal.pl.common.lesson": "Лекция", + "journal.pl.common.lesson": "Лекций", "journal.pl.common.marked": "Отмечено", "journal.pl.common.people": "человек", "journal.pl.common.success": "Успешно", @@ -71,6 +71,11 @@ "journal.pl.lesson.action": "Действия", "journal.pl.lesson.expand": "Развернуть список занятий", "journal.pl.lesson.collapse": "Свернуть список занятий", + "journal.pl.lesson.aiSuggested": "Рекомендации ИИ", + "journal.pl.lesson.aiSuggestedDescription": "Эти занятия были автоматически сгенерированы на основе вашего расписания курса", + "journal.pl.lesson.createFromSuggestion": "Создать", + "journal.pl.lesson.aiGenerated": "Сгенерировано ИИ", + "journal.pl.lesson.generatingAiSuggestions": "Генерация рекомендаций ИИ...", "journal.pl.exam.title": "Экзамен", "journal.pl.exam.startExam": "Начать экзамен", diff --git a/src/__data__/api/api.ts b/src/__data__/api/api.ts index 2319861..d64f3f2 100644 --- a/src/__data__/api/api.ts +++ b/src/__data__/api/api.ts @@ -68,6 +68,11 @@ export const api = createApi({ query: (courseId) => `/lesson/list/${courseId}`, providesTags: ['LessonList'], }), + + generateLessons: builder.mutation, string>({ + query: (courseId) => `/lesson/${courseId}/ai/generate-lessons`, + }), + createLesson: builder.mutation< BaseResponse, Partial & Pick & { courseId: string } diff --git a/src/components/xl-spinner/xl-spinner.tsx b/src/components/xl-spinner/xl-spinner.tsx index f800665..9ba8964 100644 --- a/src/components/xl-spinner/xl-spinner.tsx +++ b/src/components/xl-spinner/xl-spinner.tsx @@ -6,18 +6,22 @@ import { useColorMode } from '@chakra-ui/react' -export const XlSpinner = () => { +interface XlSpinnerProps { + size?: string; +} + +export const XlSpinner: React.FC = ({ size = 'xl' }) => { const { colorMode } = useColorMode(); return ( -
+
diff --git a/src/pages/lesson-list/components/lessons-form.tsx b/src/pages/lesson-list/components/lessons-form.tsx index 55bde17..a5261bf 100644 --- a/src/pages/lesson-list/components/lessons-form.tsx +++ b/src/pages/lesson-list/components/lessons-form.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { useForm, Controller } from 'react-hook-form' import { Box, @@ -14,9 +14,22 @@ import { FormHelperText, FormErrorMessage, Input, + Flex, + Icon, + Text, + Badge, + useColorModeValue, + HStack, + Divider, + SimpleGrid, + Skeleton, + SkeletonText, + useStyleConfig } from '@chakra-ui/react' -import { AddIcon } from '@chakra-ui/icons' +import { AddIcon, CheckIcon } from '@chakra-ui/icons' import { useTranslation } from 'react-i18next' +import { FaRobot } from 'react-icons/fa' +import dayjs from 'dayjs' import { dateToCalendarFormat } from '../../../utils/time' import { Lesson } from '../../../__data__/model' @@ -28,13 +41,17 @@ interface NewLessonForm { } interface LessonFormProps { - lesson?: Partial + lesson?: Partial | any // Разрешаем передавать как Lesson, так и AI-сгенерированный урок isLoading: boolean onCancel: () => void onSubmit: (lesson: Lesson) => void error?: string title: string nameButton: string + aiSuggestions?: any[] // Список предложений от ИИ + isLoadingAiSuggestions?: boolean // Индикатор загрузки предложений + onSelectAiSuggestion?: (suggestion: any) => void // Обработчик выбора предложения + selectedAiSuggestion?: any // Выбранное предложение } export const LessonForm = ({ @@ -45,8 +62,18 @@ export const LessonForm = ({ error, title, nameButton, + aiSuggestions = [], + isLoadingAiSuggestions = false, + onSelectAiSuggestion = () => {}, + selectedAiSuggestion }: LessonFormProps) => { const { t } = useTranslation() + const isAiSuggested = lesson && !lesson._id && !lesson.id + const aiHighlightColor = useColorModeValue('blue.100', 'blue.800') + const suggestionBgColor = useColorModeValue('blue.50', 'blue.900') + const suggestionHoverBgColor = useColorModeValue('blue.100', 'blue.800') + const borderColor = useColorModeValue('blue.200', 'blue.700') + const textSecondaryColor = useColorModeValue('gray.600', 'gray.400') const getNearestTimeSlot = () => { const now = new Date(); @@ -68,6 +95,7 @@ export const LessonForm = ({ control, handleSubmit, reset, + setValue, formState: { errors }, } = useForm({ defaultValues: (lesson && { @@ -79,12 +107,41 @@ export const LessonForm = ({ }, }) + // Рендерим скелетон для предложений ИИ + const renderSkeletons = () => { + return ( + + + + {[1, 2, 3, 4, 5].map(idx => ( + + ))} + + + ) + } + + // Применяем выбранное предложение к форме + const handleSelectSuggestion = (suggestion) => { + setValue('name', suggestion.name) + setValue('date', dateToCalendarFormat(suggestion.date)) + onSelectAiSuggestion(suggestion) + } + return ( - + - - {title} - + + + {title} + + {isAiSuggested && ( + + + {t('journal.pl.lesson.aiGenerated')} + + )} + { @@ -142,8 +199,8 @@ export const LessonForm = ({