163 lines
5.3 KiB
TypeScript
163 lines
5.3 KiB
TypeScript
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<ImproveTextModalProps> = ({
|
||
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 (
|
||
<div className="modal" style={{ display: "block" }} onClick={onClose}>
|
||
<div
|
||
className="modal-content"
|
||
style={{ maxWidth: "800px" }}
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
<div className="modal-header">
|
||
<h3>Улучшенный текст</h3>
|
||
<span className="modal-close" onClick={onClose}>
|
||
×
|
||
</span>
|
||
</div>
|
||
<div className="modal-body" style={{ maxHeight: "70vh", overflowY: "auto" }}>
|
||
{isLoading ? (
|
||
<div style={{ textAlign: "center", padding: "40px 20px" }}>
|
||
<div className="loading-spinner" style={{ margin: "0 auto 20px" }}></div>
|
||
<p>Улучшаю текст через ИИ...</p>
|
||
</div>
|
||
) : hasError ? (
|
||
<div style={{ textAlign: "center", padding: "40px 20px" }}>
|
||
<Icon
|
||
icon="mdi:alert-circle"
|
||
style={{ fontSize: "48px", color: "#dc3545", marginBottom: "15px" }}
|
||
/>
|
||
<p style={{ color: "#dc3545", marginBottom: "10px", fontSize: "18px" }}>
|
||
Не удалось улучшить текст
|
||
</p>
|
||
<p style={{ fontSize: "14px", color: "#666" }}>
|
||
{errorMessage || "Произошла ошибка при улучшении текста. Проверьте настройки AI или попробуйте еще раз."}
|
||
</p>
|
||
</div>
|
||
) : (
|
||
<>
|
||
<div style={{ marginBottom: "20px" }}>
|
||
<h4 style={{ margin: "0 0 10px 0", fontSize: "16px", color: "#666" }}>
|
||
Оригинальный текст:
|
||
</h4>
|
||
<div
|
||
style={{
|
||
padding: "15px",
|
||
border: "1px solid var(--border-color)",
|
||
borderRadius: "8px",
|
||
backgroundColor: "var(--bg-secondary)",
|
||
maxHeight: "200px",
|
||
overflowY: "auto",
|
||
whiteSpace: "pre-wrap",
|
||
wordWrap: "break-word",
|
||
fontSize: "14px",
|
||
lineHeight: "1.6",
|
||
}}
|
||
>
|
||
{originalText || "(пусто)"}
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<h4 style={{ margin: "0 0 10px 0", fontSize: "16px" }}>
|
||
Улучшенный текст:
|
||
</h4>
|
||
<textarea
|
||
value={localImprovedText}
|
||
onChange={(e) => setLocalImprovedText(e.target.value)}
|
||
style={{
|
||
width: "100%",
|
||
minHeight: "200px",
|
||
maxHeight: "400px",
|
||
padding: "15px",
|
||
border: "1px solid var(--border-color)",
|
||
borderRadius: "8px",
|
||
backgroundColor: "var(--bg-primary)",
|
||
color: "var(--text-primary)",
|
||
fontSize: "14px",
|
||
lineHeight: "1.6",
|
||
fontFamily: "inherit",
|
||
resize: "vertical",
|
||
whiteSpace: "pre-wrap",
|
||
wordWrap: "break-word",
|
||
overflowY: "auto",
|
||
}}
|
||
placeholder="Улучшенный текст появится здесь..."
|
||
/>
|
||
<p style={{ fontSize: "12px", color: "#666", marginTop: "8px" }}>
|
||
Вы можете отредактировать улучшенный текст перед применением
|
||
</p>
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
<div className="modal-footer">
|
||
<button
|
||
className="btn-primary"
|
||
onClick={handleApply}
|
||
disabled={isLoading || hasError || !localImprovedText.trim()}
|
||
>
|
||
Применить
|
||
</button>
|
||
<button className="btn-secondary" onClick={onClose}>
|
||
Отмена
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|