/
sweetebin
/
hackaton_26
Обзор
Документация
Войти
/
sweetebin
/
hackaton_26
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
web-form-project/src/components/AnalysisProgress.jsx
70 строк
3 KB
sweetebin
качество обработки под GigaCode/Qwen35B + N/A-тип + UX-тултипы; архив первого прогона
28 июл 2026, 14:44
28 июл 2026, 14:44
f397b39
Код
Авторство
О чём код?
import { useEffect, useState } from 'react'; import { CircularProgress, LinearProgress, Paper, Stack, Tooltip, Typography } from '@mui/material'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; const STAGES = [ ['extract', 'Извлечение JTBD-сигналов', 'LLM читает каждое интервью и обращение и извлекает потребности с дословными цитатами.'], ['embed', 'Эмбеддинги', 'Сигналы переводятся в векторы для сравнения по смыслу.'], ['match', 'Кластеризация в потребности', 'Похожие сигналы из разных источников склеиваются в потребности.'], ['score', 'Приоритизация', 'Частота × эмоция × охват сегментов — по формуле кейса.'], ['stories', 'User Stories', 'User Story и критерии приёмки для топ-потребностей.'], ['audit', 'Аудит бэклога', 'Проверка: какие задачи бэклога закрывают найденные потребности.'], ['report', 'Итоговый список', 'Сборка 10–15 приоритетных задач с трассировкой до цитат.'], ]; // Живой прогресс переанализа: поллим /api/progress, пока родитель нас рендерит. export default function AnalysisProgress() { const [progress, setProgress] = useState(null); useEffect(() => { let timer = null; let cancelled = false; const load = () => fetch('/api/progress') .then((r) => (r.ok ? r.json() : null)) .then((p) => { if (cancelled) return; setProgress(p); timer = setTimeout(load, 1500); }) .catch(() => { if (!cancelled) timer = setTimeout(load, 3000); }); load(); return () => { cancelled = true; if (timer) clearTimeout(timer); }; }, []); return ( <Paper elevation={0} variant="outlined" sx={{ p: 4, maxWidth: 720, mx: 'auto' }}> <Stack direction="row" spacing={1.5} alignItems="center" sx={{ mb: 2 }}> <CircularProgress size={22} /> <Typography variant="h6">Анализируем пул данных…</Typography> </Stack> {STAGES.map(([key, label, hint]) => { const s = progress?.[key]; const running = s?.status === 'running'; const done = s?.status?.startsWith('done'); return ( <Stack key={key} direction="row" spacing={1} alignItems="center" sx={{ py: 0.6 }}> <CheckCircleIcon sx={{ fontSize: 18 }} color={done ? 'success' : 'disabled'} /> <Tooltip title={hint} placement="left"> <Typography variant="body2" sx={{ width: 240, fontWeight: running ? 600 : 400, cursor: 'help' }} > {label} </Typography> </Tooltip> <Typography variant="caption" color="text.secondary" sx={{ width: 140 }}> {s ? `${s.done}/${s.total} ${s.message || ''}` : ''} </Typography> {running && <LinearProgress sx={{ flexGrow: 1 }} />} </Stack> ); })} </Paper> ); }