UI: рандом фракции — убрана подпись «случайная», добавлена анимация-барабан названий в строке
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,8 @@ export function CreateMatchPage() {
|
||||
|
||||
const [rows, setRows] = useState<Draft[]>([emptyDraft(), emptyDraft()]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
// Анимация-«барабан» рандома: для крутящейся строки — текущее мелькающее название.
|
||||
const [spin, setSpin] = useState<Record<number, string | null>>({});
|
||||
|
||||
if (lm || lf) return <Spinner />;
|
||||
if (!groupId) return <div className="muted">Нет активной группы.</div>;
|
||||
@@ -51,13 +53,25 @@ export function CreateMatchPage() {
|
||||
const removeRow = (idx: number) => setRows((rs) => rs.filter((_, i) => i !== idx));
|
||||
|
||||
const randomizeRow = async (idx: number) => {
|
||||
const pool = factions ?? [];
|
||||
if (pool.length === 0) return;
|
||||
// Запускаем «барабан»: быстро мелькаем названиями фракций.
|
||||
const ticker = setInterval(() => {
|
||||
const name = pool[Math.floor(Math.random() * pool.length)].name_ru;
|
||||
setSpin((s) => ({ ...s, [idx]: name }));
|
||||
}, 60);
|
||||
try {
|
||||
const faction = await randomize.mutateAsync({
|
||||
group_id: groupId,
|
||||
exclude_faction_ids: takenFactionIds(idx),
|
||||
});
|
||||
await new Promise((r) => setTimeout(r, 700)); // даём барабану покрутиться
|
||||
clearInterval(ticker);
|
||||
setSpin((s) => ({ ...s, [idx]: null }));
|
||||
update(idx, { faction_id: faction.id, was_random: true });
|
||||
} catch (e) {
|
||||
clearInterval(ticker);
|
||||
setSpin((s) => ({ ...s, [idx]: null }));
|
||||
toast.show(e instanceof ApiError ? e.message : "Ошибка рандома");
|
||||
}
|
||||
};
|
||||
@@ -137,6 +151,9 @@ export function CreateMatchPage() {
|
||||
</select>
|
||||
|
||||
<div className="row">
|
||||
{spin[idx] != null ? (
|
||||
<div className="faction-spin" style={{ flex: 1 }}>{spin[idx]}</div>
|
||||
) : (
|
||||
<select
|
||||
value={row.faction_id}
|
||||
onChange={(e) =>
|
||||
@@ -154,11 +171,16 @@ export function CreateMatchPage() {
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button className="btn" onClick={() => randomizeRow(idx)} title="Случайная фракция">
|
||||
)}
|
||||
<button
|
||||
className="btn"
|
||||
onClick={() => randomizeRow(idx)}
|
||||
disabled={spin[idx] != null}
|
||||
title="Случайная фракция"
|
||||
>
|
||||
<Dices size={18} />
|
||||
</button>
|
||||
</div>
|
||||
{row.was_random && row.faction_id !== "" && <span className="badge">🎲 случайная</span>}
|
||||
</div>
|
||||
))}
|
||||
|
||||
|
||||
@@ -92,6 +92,27 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent); }
|
||||
|
||||
.error-text { color: var(--danger); font-size: 13px; }
|
||||
|
||||
/* «Барабан» рандома фракции — мелькающее название вместо select */
|
||||
.faction-spin {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--accent);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--surface-2);
|
||||
color: var(--text);
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
animation: faction-roll 0.45s ease-in-out infinite;
|
||||
}
|
||||
@keyframes faction-roll {
|
||||
0% { opacity: 0.5; transform: translateY(-3px); }
|
||||
50% { opacity: 1; transform: translateY(0); }
|
||||
100% { opacity: 0.5; transform: translateY(3px); }
|
||||
}
|
||||
|
||||
/* Тумблер-переключатель (вкл/выкл) */
|
||||
.switch { position: relative; display: inline-block; width: 44px; height: 26px; flex: 0 0 auto; }
|
||||
.switch input {
|
||||
|
||||
Reference in New Issue
Block a user