From cb40f032d247ca44359e14d2b5b1004fe8308700 Mon Sep 17 00:00:00 2001 From: Fovway Date: Fri, 7 Nov 2025 16:29:00 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20=D1=83=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D1=82=D0=B0=20=D0=B2=20NoteEditor=20=D1=81=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=B5=D0=B9=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=BC=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BE=D0=BA=D0=BD=D0=B0?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8=20=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=B1=D0=BE=D0=BA=20=D0=B8=20=D0=BE=D1=82=D0=BE=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=83=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D1=88=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82=D0=B0.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D1=83=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BC=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC=20=D0=BE=D0=BA=D0=BD=D0=BE?= =?UTF-8?q?=D0=BC=20=D0=B8=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=D0=BC=20=D1=82=D0=B5=D0=BA=D1=81=D1=82=D0=B0,=20?= =?UTF-8?q?=D1=87=D1=82=D0=BE=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B4=D0=B5=D0=B9?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F=20=D1=81=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D0=BA=D0=B0=D0=BC=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/notes/ImproveTextModal.tsx | 162 ++++++++++++++++++++++ src/components/notes/NoteEditor.tsx | 47 ++++++- 2 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 src/components/notes/ImproveTextModal.tsx diff --git a/src/components/notes/ImproveTextModal.tsx b/src/components/notes/ImproveTextModal.tsx new file mode 100644 index 0000000..3850689 --- /dev/null +++ b/src/components/notes/ImproveTextModal.tsx @@ -0,0 +1,162 @@ +import React, { useState, useEffect } from "react"; +import { Icon } from "@iconify/react"; + +interface ImproveTextModalProps { + isOpen: boolean; + onClose: () => void; + onApply: (improvedText: string) => void; + originalText: string; + improvedText: string; + isLoading?: boolean; + hasError?: boolean; + errorMessage?: string; +} + +export const ImproveTextModal: React.FC = ({ + isOpen, + onClose, + onApply, + originalText, + improvedText, + isLoading = false, + hasError = false, + errorMessage, +}) => { + const [localImprovedText, setLocalImprovedText] = useState(improvedText); + + useEffect(() => { + if (isOpen) { + setLocalImprovedText(improvedText); + } + }, [isOpen, improvedText]); + + const handleApply = () => { + if (!localImprovedText.trim()) { + return; + } + onApply(localImprovedText); + onClose(); + }; + + useEffect(() => { + const handleEscape = (e: KeyboardEvent) => { + if (e.key === "Escape" && isOpen) { + onClose(); + } + }; + + if (isOpen) { + document.addEventListener("keydown", handleEscape); + } + + return () => document.removeEventListener("keydown", handleEscape); + }, [isOpen, onClose]); + + if (!isOpen) return null; + + return ( +
+
e.stopPropagation()} + > +
+

Улучшенный текст

+ + × + +
+
+ {isLoading ? ( +
+
+

Улучшаю текст через ИИ...

+
+ ) : hasError ? ( +
+ +

+ Не удалось улучшить текст +

+

+ {errorMessage || "Произошла ошибка при улучшении текста. Проверьте настройки AI или попробуйте еще раз."} +

+
+ ) : ( + <> +
+

+ Оригинальный текст: +

+
+ {originalText || "(пусто)"} +
+
+ +
+

+ Улучшенный текст: +

+