112 lines
3.1 KiB
React
112 lines
3.1 KiB
React
import { useEffect, useState } from "react";
|
|
import { Link } from "react-router-dom";
|
|
import { api } from "../api/client";
|
|
|
|
export default function ProjectsPage() {
|
|
const [projects, setProjects] = useState([]);
|
|
const [name, setName] = useState("");
|
|
const [error, setError] = useState("");
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
async function load() {
|
|
setLoading(true);
|
|
setError("");
|
|
try {
|
|
setProjects(await api.listProjects());
|
|
} catch (e) {
|
|
setError(e.message);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
load();
|
|
}, []);
|
|
|
|
async function create() {
|
|
if (!name.trim()) return;
|
|
try {
|
|
const p = await api.createProject(name.trim());
|
|
setName("");
|
|
window.location.href = `/projects/${p.id}`;
|
|
} catch (e) {
|
|
setError(e.message);
|
|
}
|
|
}
|
|
|
|
async function remove(id) {
|
|
if (!confirm("Удалить проект?")) return;
|
|
try {
|
|
await api.deleteProject(id);
|
|
load();
|
|
} catch (e) {
|
|
setError(e.message);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="stack">
|
|
<div className="card stack">
|
|
<h2 style={{ margin: 0 }}>Проекты</h2>
|
|
<div className="row">
|
|
<input
|
|
placeholder="Название проекта"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
onKeyDown={(e) => e.key === "Enter" && create()}
|
|
/>
|
|
<button onClick={create}>Создать</button>
|
|
<button className="secondary" onClick={load}>
|
|
Обновить
|
|
</button>
|
|
</div>
|
|
{error && <div className="error">{error}</div>}
|
|
</div>
|
|
|
|
<div className="card">
|
|
{loading ? (
|
|
<div className="muted">Загрузка…</div>
|
|
) : projects.length === 0 ? (
|
|
<div className="muted">Пока нет проектов</div>
|
|
) : (
|
|
<div className="table-wrap">
|
|
<table className="data">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Название</th>
|
|
<th>Статус</th>
|
|
<th>Компоненты</th>
|
|
<th>Слои</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{projects.map((p) => (
|
|
<tr key={p.id}>
|
|
<td>{p.id}</td>
|
|
<td>
|
|
<Link to={`/projects/${p.id}`}>{p.name}</Link>
|
|
</td>
|
|
<td>
|
|
<span className={`status ${p.status}`}>{p.status}</span>
|
|
</td>
|
|
<td>{p.component_count}</td>
|
|
<td>{p.layer_count}</td>
|
|
<td>
|
|
<button className="danger" onClick={() => remove(p.id)}>
|
|
Удалить
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|