'use client'; import { useState } from 'react'; import { PlagiatData, HighlightSegment, SemanticMetrics } from '../lib/types'; import TextAnalysis from './components/TextAnalysis'; import ActionButtons from './components/actionbuttons'; import HighlightedText from './components/HighlightedText'; import SourcesList from './components/SourcesList'; import GaugeWithBars from './components/GaugewithBars'; import TopMetrics from './components/TopMetrics'; import HumanAiBar from './components/HumanAiBar'; import Header from './components/Header'; import CertificateCard from './components/SertificateCard'; import SemanticModal from './components/SemanticModal'; import Divider from './components/Divider'; import { blue } from '../lib/constant'; import { useQuery } from '@tanstack/react-query'; import { apiRequest } from '@/shared/request/apiRequest'; import { links } from '@/shared/request/links'; // ─── Helpers ────────────────────────────────────────────────────────────────── function parseHighlightedText(textRes: string): HighlightSegment[] { const segments: HighlightSegment[] = []; const parts = textRes.split(/([\s\S]*?<\/sel>)/g); for (const part of parts) { if (part.startsWith('')) { segments.push({ text: part.replace(/<\/?sel>/g, ''), plagiarized: true }); } else if (part) { segments.push({ text: part, plagiarized: false }); } } return segments; } function parseAnalyzeText(a: Record): SemanticMetrics { const bool = (v: unknown) => v === 'Да'; return { totalWords: Number(a['Общее количество слов'] ?? 0), uniqueWords: Number(a['Уникальных слов'] ?? 0), lexicalUniqueness: Number(a['Лексическая уникальность (%)'] ?? 0), avgWordLength: Number(a['Средняя длина слов'] ?? 0), geoAvgWordLength: Number(a['Геометрическая средняя длина слов'] ?? 0), minWordLength: Number(a['Мин. длина слова'] ?? 0), maxWordLength: Number(a['Макс. длина слова'] ?? 0), sentences: Number(a['Количество предложений'] ?? 0), avgWordsPerSentence: Number( a['Среднее количество слов в предложении'] ?? 0, ), polysyllabicWords: Number(a['Полисиллабических слов'] ?? 0), polysyllabicPercent: Number(a['Доля полисиллабических слов (%)'] ?? 0), totalChars: Number(a['Символов всего'] ?? 0), charsNoSpaces: Number(a['Без пробелов'] ?? 0), vowels: Number(a['Гласных'] ?? 0), consonants: Number(a['Согласных'] ?? 0), punctuation: Number(a['Знаков препинания'] ?? 0), uppercase: Number(a['Заглавных букв'] ?? 0), lowercase: Number(a['Строчных букв'] ?? 0), digits: Number(a['Цифр'] ?? 0), capsLockWords: Number(a['Слов в CAPSLOCK'] ?? 0), stopWords: Number(a['Стоп-слов'] ?? 0), stopWordsPercent: Number(a['Доля стоп-слов (%)'] ?? 0), junkWords: Number(a['Мусорные слова (шт)'] ?? 0), junkPercent: Number(a['Доля мусора (%)'] ?? 0), maxConsecutiveRepeats: Number(a['Макс. подряд повторов слова'] ?? 0), top5Words: String(a['ТОП-5 слов'] ?? ''), spamRatio: Number(a['Заспамленность (max/total)'] ?? 0), hasHtml: bool(a['Наличие HTML-тегов']), hasEmail: bool(a['Email найден']), hasUrl: bool(a['URL найден']), hasDate: bool(a['Дата найдена']), hasPhone: bool(a['Телефон найден']), startsEqualsEnd: bool(a['Начало = Конец']), isPalindrome: bool(a['Палиндром']), hasQuestion: bool(a['Вопросительный знак']), hasExclamation: bool(a['Восклицательный знак']), paragraphs: Number(a['Количество абзацев'] ?? 0), lines: Number(a['Количество строк'] ?? 0), latinPercent: Number(a['Доля латиницы (%)'] ?? 0), cyrillicPercent: Number(a['Доля кириллицы (%)'] ?? 0), longWords16plus: Number(a['Слов длиной 16+ символов'] ?? 0), }; } // eslint-disable-next-line @typescript-eslint/no-explicit-any function transformResponse(raw: any): PlagiatData { const result = raw?.results?.[0]; const resultJson = result?.result_json; const res = resultJson?.res ?? {}; const analyze = resultJson?.analyze_text ?? {}; const textRes = resultJson?.text_res ?? ''; const nameParts = (raw?.text ?? '').trim().split(/\s+/); const initials = nameParts .slice(0, 2) .map((n: string) => n[0]?.toUpperCase() ?? '') .join(''); return { name: raw?.text ?? '', initials: initials ?? '', email: '', location: '', fileName: raw?.file?.split('/').pop() ?? '', checkedAt: raw?.created_at?.slice(0, 10) ?? '', aiPercent: res?.ai ?? 0, humanPercent: res?.ai !== null ? 100 - res.ai : 0, plagiarismPercent: res?.plagiarism ?? 0, originalityPercent: res?.originality ?? 0, citationPercent: res?.citation ?? 0, highlightedText: textRes ? parseHighlightedText(textRes) : [], sources: [], semantic: Object.keys(analyze).length ? parseAnalyzeText(analyze) : null, certificate: null, }; } // ─── Not found state ────────────────────────────────────────────────────────── function NotFound({ label }: { label: string }) { return (

{label} — ma'lumot mavjud emas

); } // ─── Loading skeleton ───────────────────────────────────────────────────────── function Skeleton() { return (
{[100, 60, 80, 40, 90, 55].map((w, i) => (
))}
); } // ─── Component ──────────────────────────────────────────────────────────────── export default function PlagiatResult({ id }: { id: number }) { const [showSemantic, setShowSemantic] = useState(false); const [saving, setSaving] = useState(false); const { data: rawData, isLoading, isError, } = useQuery({ queryKey: ['detail', id], queryFn: async () => { const res = await apiRequest('GET', links.detail(id)); return res; }, enabled: !!id, staleTime: 1000 * 60 * 5, }); if (isLoading) return ; if (isError || !rawData) return (

Ma'lumot topilmadi

Ushbu tekshiruv mavjud emas yoki o'chirilgan

); const data: PlagiatData = transformResponse(rawData); const handleSave = () => { setSaving(true); setTimeout(() => setSaving(false), 1500); }; const handleRecheck = () => { alert('Yangi fayl yuklash sahifasiga yo'naltirish...'); }; return ( <> {showSemantic && data.semantic && ( setShowSemantic(false)} /> )}
{/* Certificate */} {data.certificate ? ( ) : null} {/* Header */} {data.name ? (
) : ( )} {/* Human / AI bar */} {/* Score cards */} {/* Gauge */} {/* Sources */} {/* Highlighted text */} {data.highlightedText.length > 0 ? ( ) : ( )} {/* Buttons */} setShowSemantic(true)} onRecheck={handleRecheck} /> {/* Semantic analysis */} {data.semantic ? ( ) : ( )}
); }