From da1f43aa1ce29f81ae0064f5922430d6590784c5 Mon Sep 17 00:00:00 2001 From: konard Date: Wed, 10 Sep 2025 21:32:09 +0300 Subject: [PATCH 1/3] Initial commit with task details for issue #25 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/deep-assistant/GPTutor/issues/25 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..685d8be1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/deep-assistant/GPTutor/issues/25 +Your prepared branch: issue-25-78891373 +Your prepared working directory: /tmp/gh-issue-solver-1757529106947 + +Proceed. \ No newline at end of file From d1c98b1e6814d0c34a3f0bad751badefeae45039 Mon Sep 17 00:00:00 2001 From: konard Date: Wed, 10 Sep 2025 21:32:27 +0300 Subject: [PATCH 2/3] Remove CLAUDE.md - PR created successfully --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 685d8be1..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/deep-assistant/GPTutor/issues/25 -Your prepared branch: issue-25-78891373 -Your prepared working directory: /tmp/gh-issue-solver-1757529106947 - -Proceed. \ No newline at end of file From 6e3b403d1f74562421f7c2025476688aa4946e6e Mon Sep 17 00:00:00 2001 From: konard Date: Wed, 10 Sep 2025 21:38:21 +0300 Subject: [PATCH 3/3] =?UTF-8?q?#25=20:=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6?= =?UTF-8?q?=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D1=80=D0=B5=D0=B4=D0=BB?= =?UTF-8?q?=D0=BE=D0=B6=D0=B8=D1=82=D1=8C=20=D0=B4=D0=B5=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B8=D0=B5=20=D0=B2=20=D1=83=D1=80=D0=BE=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Создан класс ActionSuggestion для предложений действий - Расширен класс LessonItem для поддержки предложений действий - Создан компонент ChatLessonActionSuggestions для отображения предложений - Интегрированы предложения действий в интерфейс урока - Добавлены примеры предложений действий в уроки JavaScript 🤖 Generated with Claude Code Co-Authored-By: Claude --- GPTutor-Frontend/build.log | 5 ++ .../src/entity/lessons/ActionSuggestion.ts | 9 +++ .../src/entity/lessons/LessonItem.ts | 4 +- GPTutor-Frontend/src/entity/lessons/index.ts | 1 + .../entity/lessons/lessonsItem/javascript.ts | 15 +++++ .../src/panels/ChatLesson/ChatLesson.tsx | 26 ++++++--- .../ChatLessonActionSuggestions.module.css | 10 ++++ .../ChatLessonActionSuggestions.tsx | 56 +++++++++++++++++++ .../ChatLessonActionSuggestions/index.ts | 1 + GPTutor-Frontend/typecheck.log | 9 +++ 10 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 GPTutor-Frontend/build.log create mode 100644 GPTutor-Frontend/src/entity/lessons/ActionSuggestion.ts create mode 100644 GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.module.css create mode 100644 GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.tsx create mode 100644 GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/index.ts create mode 100644 GPTutor-Frontend/typecheck.log diff --git a/GPTutor-Frontend/build.log b/GPTutor-Frontend/build.log new file mode 100644 index 00000000..bd5eb2da --- /dev/null +++ b/GPTutor-Frontend/build.log @@ -0,0 +1,5 @@ + +> chat@0.0.0 build +> cross-env GENERATE_SOURCEMAP=false craco build + +sh: 1: cross-env: not found diff --git a/GPTutor-Frontend/src/entity/lessons/ActionSuggestion.ts b/GPTutor-Frontend/src/entity/lessons/ActionSuggestion.ts new file mode 100644 index 00000000..f41186f6 --- /dev/null +++ b/GPTutor-Frontend/src/entity/lessons/ActionSuggestion.ts @@ -0,0 +1,9 @@ +export class ActionSuggestion { + text: string; + name: string; + + constructor(text: string, name?: string) { + this.text = text; + this.name = name || text; + } +} \ No newline at end of file diff --git a/GPTutor-Frontend/src/entity/lessons/LessonItem.ts b/GPTutor-Frontend/src/entity/lessons/LessonItem.ts index 9e47f50e..6142657a 100644 --- a/GPTutor-Frontend/src/entity/lessons/LessonItem.ts +++ b/GPTutor-Frontend/src/entity/lessons/LessonItem.ts @@ -1,6 +1,7 @@ import { v4 as uuid } from "uuid"; import { LessonRequest } from "./LessonRequest"; +import { ActionSuggestion } from "./ActionSuggestion"; import { UUID_V4 } from "../common"; export class LessonItem { @@ -10,7 +11,8 @@ export class LessonItem { public name: string, public paragraph: string, public initialRequest: LessonRequest, - public additionalRequests: LessonRequest[] + public additionalRequests: LessonRequest[], + public actionSuggestions: ActionSuggestion[] = [] ) { this.id = uuid(); initialRequest.name = "Стартовый вопрос"; diff --git a/GPTutor-Frontend/src/entity/lessons/index.ts b/GPTutor-Frontend/src/entity/lessons/index.ts index d9c34274..5b433c57 100644 --- a/GPTutor-Frontend/src/entity/lessons/index.ts +++ b/GPTutor-Frontend/src/entity/lessons/index.ts @@ -14,6 +14,7 @@ export * from "./ChapterItem"; export * from "./modeType"; export * from "./LessonItem"; export * from "./LessonRequest"; +export * from "./ActionSuggestion"; export * from "./lessonsItem/javascript"; export * from "./lessonsItem/html"; export * from "./lessonsItem/git"; diff --git a/GPTutor-Frontend/src/entity/lessons/lessonsItem/javascript.ts b/GPTutor-Frontend/src/entity/lessons/lessonsItem/javascript.ts index 92b3a44e..2b2a34a3 100644 --- a/GPTutor-Frontend/src/entity/lessons/lessonsItem/javascript.ts +++ b/GPTutor-Frontend/src/entity/lessons/lessonsItem/javascript.ts @@ -1,5 +1,6 @@ import { LessonItem } from "../LessonItem"; import { LessonRequest } from "../LessonRequest"; +import { ActionSuggestion } from "../ActionSuggestion"; const BasedJS = "Основы JavaScript"; const AdvancedJS = "Продвинутый JavaScript"; @@ -20,6 +21,11 @@ const lessonJS1 = new LessonItem( new LessonRequest("Объясни подробнее var, укажи примеры", "Переменные var"), new LessonRequest("В чем отличия let от var?"), new LessonRequest("Когда лучше использовать let, const, var?"), + ], + [ + new ActionSuggestion("Дай мне задание на переменные для практики", "Практическое задание"), + new ActionSuggestion("Покажи пример реального использования переменных", "Реальный пример"), + new ActionSuggestion("Объясни частые ошибки при работе с переменными", "Частые ошибки"), ] ); @@ -37,6 +43,10 @@ const lessonJS2 = new LessonItem( new LessonRequest("Объясни null в js", "null"), new LessonRequest("Объясни undefined в js", "undefined"), new LessonRequest("Объясни оператор typeof", "Оператор typeof"), + ], + [ + new ActionSuggestion("Покажи как проверить тип переменной в разных случаях", "Проверка типов"), + new ActionSuggestion("Дай упражнения на приведение типов", "Упражнения на типы"), ] ); @@ -152,6 +162,11 @@ const lessonJS9 = new LessonItem( "Стрелочные функции" ), new LessonRequest("Объясни контекст функции в js", "Контекст"), + ], + [ + new ActionSuggestion("Дай мне задачу написать функцию", "Написать функцию"), + new ActionSuggestion("Покажи примеры использования колбэков", "Примеры колбэков"), + new ActionSuggestion("Объясни как работает замыкание в функциях", "Замыкания"), ] ); diff --git a/GPTutor-Frontend/src/panels/ChatLesson/ChatLesson.tsx b/GPTutor-Frontend/src/panels/ChatLesson/ChatLesson.tsx index 6235026c..f2ad26d2 100644 --- a/GPTutor-Frontend/src/panels/ChatLesson/ChatLesson.tsx +++ b/GPTutor-Frontend/src/panels/ChatLesson/ChatLesson.tsx @@ -8,6 +8,7 @@ import { lessonsController } from "$/entity/lessons"; import { ChatLessonWriteBarBefore } from "./ChatLessonWriteBarBefore"; import { ChatLessonAdditionalRequests } from "./ChatLessonAdditionalRequests"; +import { ChatLessonActionSuggestions } from "./ChatLessonActionSuggestions"; interface IProps { id: string; @@ -15,6 +16,7 @@ interface IProps { function ChatLesson({ id }: IProps) { const [isAdditionalOpen, setAdditionsOpen] = useState(true); + const [isActionSuggestionsOpen, setActionSuggestionsOpen] = useState(true); const onClickAdditional = useCallback( () => setAdditionsOpen((prev) => !prev), @@ -33,6 +35,7 @@ function ChatLesson({ id }: IProps) { }; const additionalRequests = currentLesson?.additionalRequests || []; + const actionSuggestions = currentLesson?.actionSuggestions || []; const isStopped = chatGpt.chatGptLesson.timer.isStopped$.get(); const isTyping = chatGpt.chatGptLesson.sendCompletions$.loading.get(); const isBlockActions = chatGpt.chatGptLesson.isBlockActions$.get(); @@ -51,13 +54,22 @@ function ChatLesson({ id }: IProps) { /> } additionalRequest={(handleSend) => ( - + <> + + + )} onStartChat={onStartChat} chatGpt={chatGpt.chatGptLesson} diff --git a/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.module.css b/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.module.css new file mode 100644 index 00000000..28221e39 --- /dev/null +++ b/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.module.css @@ -0,0 +1,10 @@ +.actionSuggestions { + display: grid; + gap: 8px; + padding: 0 12px; +} + +.button { + display: flex; + align-items: center; +} \ No newline at end of file diff --git a/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.tsx b/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.tsx new file mode 100644 index 00000000..956ac2ea --- /dev/null +++ b/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/ChatLessonActionSuggestions.tsx @@ -0,0 +1,56 @@ +import React, { memo } from "react"; +import { Button, Div, HorizontalScroll, Separator } from "@vkontakte/vkui"; + +import { ActionSuggestion } from "$/entity/lessons"; + +import classes from "./ChatLessonActionSuggestions.module.css"; + +interface IProps { + actionSuggestions: ActionSuggestion[]; + isTyping: boolean; + handleSend: (value: string) => void; + isActionSuggestionsOpen: boolean; + isStopped: boolean; +} + +function ChatLessonActionSuggestions({ + actionSuggestions, + isActionSuggestionsOpen, + isTyping, + isStopped, + handleSend, +}: IProps) { + if (!actionSuggestions?.length || !isActionSuggestionsOpen) return null; + + return ( + <> + + +
+ {actionSuggestions.map((suggestion, index) => ( +
+ +
+ ))} +
+
+ + ); +} + +export default memo(ChatLessonActionSuggestions); \ No newline at end of file diff --git a/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/index.ts b/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/index.ts new file mode 100644 index 00000000..27209007 --- /dev/null +++ b/GPTutor-Frontend/src/panels/ChatLesson/ChatLessonActionSuggestions/index.ts @@ -0,0 +1 @@ +export { default as ChatLessonActionSuggestions } from "./ChatLessonActionSuggestions"; \ No newline at end of file diff --git a/GPTutor-Frontend/typecheck.log b/GPTutor-Frontend/typecheck.log new file mode 100644 index 00000000..babd1b6d --- /dev/null +++ b/GPTutor-Frontend/typecheck.log @@ -0,0 +1,9 @@ + +  + This is not the tsc command you are looking for  +  + +To get access to the TypeScript compiler, tsc, from the command line either: + +- Use npm install typescript to first add TypeScript to your project before using npx +- Use yarn to avoid accidentally running code from un-installed packages