doom and eyes fixes
This commit is contained in:
@@ -1,8 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Terminal, Send, Loader2, ShieldCheck } from "lucide-react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import {
|
||||
Terminal,
|
||||
Send,
|
||||
Loader2,
|
||||
ShieldCheck,
|
||||
ShieldAlert,
|
||||
} from "lucide-react";
|
||||
import { pb } from "@/lib/pb";
|
||||
import { Dictionary } from "@/lib/IDict";
|
||||
|
||||
@@ -10,6 +16,7 @@ export function TerminalClient({ dict }: { dict: Dictionary["terminal"] }) {
|
||||
const [messages, setMessages] = useState<any[]>([]);
|
||||
const [nickname, setNickname] = useState("");
|
||||
const [inputMsg, setInputMsg] = useState("");
|
||||
const [errorText, setErrorText] = useState<string | null>(null);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
@@ -103,15 +110,14 @@ export function TerminalClient({ dict }: { dict: Dictionary["terminal"] }) {
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setErrorText(null);
|
||||
|
||||
if (!nickname.trim() || !inputMsg.trim() || cooldown > 0 || isSubmitting)
|
||||
return;
|
||||
|
||||
try {
|
||||
setIsSubmitting(true);
|
||||
const proxyUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/api/proxy"
|
||||
: "http://localhost:3001";
|
||||
const proxyUrl = "/api/proxy";
|
||||
|
||||
const res = await fetch(`${proxyUrl}/api/comments`, {
|
||||
method: "POST",
|
||||
@@ -122,14 +128,36 @@ export function TerminalClient({ dict }: { dict: Dictionary["terminal"] }) {
|
||||
}),
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
setInputMsg("");
|
||||
setCooldown(60);
|
||||
localStorage.setItem("last_comment_time", Date.now().toString());
|
||||
setTimeout(scrollToBottom, 50);
|
||||
if (!res.ok) {
|
||||
if (res.status === 406) {
|
||||
throw new Error("FILTER_VIOLATION");
|
||||
}
|
||||
throw new Error("SERVER_ERROR");
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
// Успешная отправка
|
||||
setInputMsg("");
|
||||
setCooldown(60);
|
||||
localStorage.setItem("last_comment_time", Date.now().toString());
|
||||
setTimeout(scrollToBottom, 50);
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
|
||||
// Выдаем разные ошибки в зависимости от ответа сервера
|
||||
if (err.message === "FILTER_VIOLATION") {
|
||||
setErrorText(
|
||||
(dict as any).statusErrorFilter ||
|
||||
"⛔ Сообщение отклонено ИИ-фильтром (нарушение политики: мат, спам или токсичность).",
|
||||
);
|
||||
} else {
|
||||
setErrorText(
|
||||
(dict as any).statusErrorOffline ||
|
||||
"⚠️ Ошибка связи с сервером. Попробуйте повторить запрос позже.",
|
||||
);
|
||||
}
|
||||
|
||||
// Убираем ошибку через 8 секунд
|
||||
setTimeout(() => setErrorText(null), 8000);
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
@@ -231,7 +259,22 @@ export function TerminalClient({ dict }: { dict: Dictionary["terminal"] }) {
|
||||
</div>
|
||||
|
||||
{/* Input Panel */}
|
||||
<div className="p-4 bg-muted/20 border-t border-border/50">
|
||||
<div className="p-4 bg-muted/20 border-t border-border/50 relative">
|
||||
{/* Блок вывода ошибок */}
|
||||
<AnimatePresence>
|
||||
{errorText && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10, scale: 0.95 }}
|
||||
animate={{ opacity: 1, y: 0, scale: 1 }}
|
||||
exit={{ opacity: 0, y: 10, scale: 0.95 }}
|
||||
className="absolute bottom-full left-4 right-4 mb-4 p-3 rounded-xl border bg-destructive/10 border-destructive/20 text-destructive text-xs font-mono flex items-start gap-3 backdrop-blur-md shadow-lg"
|
||||
>
|
||||
<ShieldAlert className="size-4 shrink-0 mt-0.5" />
|
||||
<span className="leading-relaxed">{errorText}</span>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-col sm:flex-row gap-3"
|
||||
|
||||
Reference in New Issue
Block a user