/
PashigorevAY
/
TestFastAPI
Обзор
Документация
Войти
/
PashigorevAY
/
TestFastAPI
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
frontend/src/components/PathsList.tsx
174 строки
6 KB
Pashigorev
Initial commit
05 июл 2026, 21:43
05 июл 2026, 21:43
19770a6
Код
Авторство
О чём код?
import { useState, useEffect } from 'react'; import { api } from '../api'; interface PathsListProps { onSelectPath: (name: string) => void; onBack: () => void; } export function PathsList({ onSelectPath, onBack }: PathsListProps) { const [paths, setPaths] = useState<Record<string, any>>({}); const [showCreate, setShowCreate] = useState(false); const [newPathName, setNewPathName] = useState(''); const [selectedGroup, setSelectedGroup] = useState(''); const [groups, setGroups] = useState<string[]>([]); const [error, setError] = useState(''); useEffect(() => { loadData(); }, []); async function loadData() { const [pathsData, groupsData] = await Promise.all([ api.getPaths(), api.getTasksGroups(), ]); setPaths(pathsData.paths || {}); setGroups(groupsData.groups); if (groupsData.groups.length > 0 && !selectedGroup) { setSelectedGroup(groupsData.groups[0]); } } async function handleCreatePath() { try { setError(''); if (!newPathName.trim() || !selectedGroup) { setError('Заполните все поля'); return; } await api.createPath(newPathName.trim(), selectedGroup); setNewPathName(''); setShowCreate(false); loadData(); } catch (err) { setError(err instanceof Error ? err.message : 'Ошибка'); } } async function handleDeletePath(name: string, e: React.MouseEvent) { e.stopPropagation(); if (confirm('Удалить путь?')) { await api.deletePath(name); loadData(); } } return ( <div style={{ padding: '20px' }}> <div style={{ marginBottom: '20px', display: 'flex', gap: '10px', alignItems: 'center' }}> <button onClick={onBack} style={{ backgroundColor: '#e0e0e0' }}>← Назад</button> <h2 style={{ flex: 1 }}>Пути принятия решений</h2> <button onClick={() => setShowCreate(true)} style={{ backgroundColor: '#4CAF50', color: 'white' }}> Добавить путь </button> </div> <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: '20px' }}> {Object.entries(paths).map(([name, data]) => ( <div key={name} onClick={() => onSelectPath(name)} style={{ padding: '20px', border: '1px solid #ddd', borderRadius: '8px', cursor: 'pointer', transition: 'box-shadow 0.2s', position: 'relative', }} onMouseEnter={(e) => e.currentTarget.style.boxShadow = '0 4px 8px rgba(0,0,0,0.1)'} onMouseLeave={(e) => e.currentTarget.style.boxShadow = 'none'} > <button onClick={(e) => handleDeletePath(name, e)} style={{ position: 'absolute', top: '8px', right: '8px', background: '#F44336', color: 'white', border: 'none', borderRadius: '4px', padding: '2px 8px', cursor: 'pointer', fontSize: '12px', }} > × </button> <h3>{name}</h3> <p style={{ color: '#666', marginTop: '8px', fontSize: '13px' }}> Группа: {data.tasks_group} </p> <p style={{ color: '#999', fontSize: '12px', marginTop: '4px' }}> Шагов: {data.path?.length || 0} </p> </div> ))} </div> {Object.keys(paths).length === 0 && ( <div style={{ textAlign: 'center', color: '#999', padding: '40px' }}> <p>Пути не найдены</p> </div> )} {showCreate && ( <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000, }}> <div style={{ background: 'white', padding: '24px', borderRadius: '8px', minWidth: '400px', }}> <h3>Создать путь</h3> {error && <p style={{ color: 'red', margin: '8px 0' }}>{error}</p>} <div style={{ marginTop: '16px', display: 'flex', flexDirection: 'column', gap: '12px' }}> <div> <label style={{ display: 'block', marginBottom: '4px' }}>Название пути</label> <input value={newPathName} onChange={(e) => setNewPathName(e.target.value)} placeholder="Введите название" style={{ width: '100%', padding: '8px' }} /> </div> <div> <label style={{ display: 'block', marginBottom: '4px' }}>Группа задач</label> <select value={selectedGroup} onChange={(e) => setSelectedGroup(e.target.value)} style={{ width: '100%', padding: '8px' }} > {groups.map((g) => ( <option key={g} value={g}>{g}</option> ))} </select> </div> </div> <div style={{ marginTop: '20px', display: 'flex', gap: '10px', justifyContent: 'flex-end' }}> <button onClick={() => setShowCreate(false)} style={{ backgroundColor: '#e0e0e0' }}> Отмена </button> <button onClick={handleCreatePath} style={{ backgroundColor: '#4CAF50', color: 'white' }}> Создать </button> </div> </div> </div> )} </div> ); }