feat(proj): init
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { api, type StyleItem } from "../../api";
|
||||
import { Button, Flash, PageHeader, Section } from "../../components/ui";
|
||||
import { AppSelect, AppTextField } from "../../ui";
|
||||
|
||||
export function StylesPage() {
|
||||
const navigate = useNavigate();
|
||||
const [items, setItems] = useState<StyleItem[]>([]);
|
||||
const [name, setName] = useState("");
|
||||
const [from, setFrom] = useState("osm-bright");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const reload = () =>
|
||||
api
|
||||
.styles()
|
||||
.then(setItems)
|
||||
.catch((err: unknown) => setError(err instanceof Error ? err.message : "Не удалось загрузить стили"));
|
||||
|
||||
useEffect(() => {
|
||||
void reload();
|
||||
}, []);
|
||||
|
||||
const presets = items.filter((item) => item.isPreset);
|
||||
const cloneFrom = presets.length > 0 ? from : "osm-bright";
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
eyebrow="Стили"
|
||||
title="Карта"
|
||||
description="Клонируйте пресет и откройте визуальный редактор: слои, карта и свойства."
|
||||
/>
|
||||
<Section title="Клонировать пресет">
|
||||
<div className="form-row">
|
||||
<AppTextField id="style-name" label="Имя копии" value={name} onChange={(e) => setName(e.target.value)} placeholder="my-bright" />
|
||||
<AppSelect
|
||||
id="style-from"
|
||||
label="Пресет"
|
||||
value={cloneFrom}
|
||||
onChange={(e) => setFrom(e.target.value)}
|
||||
>
|
||||
{(presets.length > 0 ? presets : [{ name: "osm-bright" }]).map((item) => (
|
||||
<option key={item.name} value={item.name}>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
</AppSelect>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
setError(null);
|
||||
void api
|
||||
.cloneStyle(name, cloneFrom)
|
||||
.then((created) => navigate(`/styles/${created.name}`))
|
||||
.catch((err: unknown) => setError(err instanceof Error ? err.message : "Не удалось клонировать"));
|
||||
}}
|
||||
>
|
||||
Клонировать
|
||||
</Button>
|
||||
</div>
|
||||
<Flash error={error} />
|
||||
</Section>
|
||||
<Section title="Список">
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Имя</th>
|
||||
<th>Источник</th>
|
||||
<th>Тип</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{items.map((item) => (
|
||||
<tr key={item.name}>
|
||||
<td>
|
||||
<Link to={`/styles/${item.name}`}>{item.name}</Link>
|
||||
</td>
|
||||
<td>{item.createdFrom ?? "—"}</td>
|
||||
<td>{item.isPreset ? "пресет" : "мой"}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</Section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user