From 7269afcd4e9cc9f99e1ceed558a2330d23554bbb Mon Sep 17 00:00:00 2001 From: NotBigGhost Date: Fri, 26 Jun 2026 16:57:35 +0300 Subject: [PATCH] =?UTF-8?q?UI:=20=D0=BF=D0=BE=D0=B4=D1=82=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=20=D0=BE=D1=82=D0=BC=D0=B5=D0=BD=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B7=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D1=91=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D0=B8=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=D0=BC=20=D1=81=D1=8B=D0=B3=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D0=BF=D0=B0=D1=80=D1=82=D0=B8=D0=B8=20(?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B0=D0=BB=D0=BA=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- frontend/src/components/ConfirmDialog.tsx | 41 +++++++++++++++++++++++ frontend/src/pages/MatchDetailPage.tsx | 26 +++++++++++++- frontend/src/styles/global.css | 25 ++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/ConfirmDialog.tsx diff --git a/frontend/src/components/ConfirmDialog.tsx b/frontend/src/components/ConfirmDialog.tsx new file mode 100644 index 0000000..bddc2c8 --- /dev/null +++ b/frontend/src/components/ConfirmDialog.tsx @@ -0,0 +1,41 @@ +/** Переиспользуемое модальное подтверждение (без нативного confirm()). */ +export function ConfirmDialog({ + open, + title, + message, + confirmLabel = "Подтвердить", + cancelLabel = "Отмена", + danger = false, + onConfirm, + onCancel, +}: { + open: boolean; + title: string; + message?: string; + confirmLabel?: string; + cancelLabel?: string; + danger?: boolean; + onConfirm: () => void; + onCancel: () => void; +}) { + if (!open) return null; + return ( +
+
e.stopPropagation()}> +
{title}
+ {message &&

{message}

} +
+ + +
+
+
+ ); +} diff --git a/frontend/src/pages/MatchDetailPage.tsx b/frontend/src/pages/MatchDetailPage.tsx index 32323a9..d68ec50 100644 --- a/frontend/src/pages/MatchDetailPage.tsx +++ b/frontend/src/pages/MatchDetailPage.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useNavigate, useParams } from "react-router-dom"; import { ApiError } from "../api/client"; +import { ConfirmDialog } from "../components/ConfirmDialog"; import { MatchMedia } from "../components/MatchMedia"; import { Spinner } from "../components/Spinner"; import { formatDuration, formatTime } from "../domain/format"; @@ -39,6 +40,7 @@ export function MatchDetailPage() { const [winReason, setWinReason] = useState("objectives"); const [overall, setOverall] = useState(""); const [error, setError] = useState(null); + const [confirmRemove, setConfirmRemove] = useState(false); if (isLoading) return ; if (!match) return
Партия не найдена.
; @@ -271,10 +273,32 @@ export function MatchDetailPage() { )} {canModify && ( - )} + + setConfirmRemove(false)} + onConfirm={() => { + setConfirmRemove(false); + remove(); + }} + /> ); } diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 6bfb96a..b40c8f3 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -68,6 +68,7 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent); } .btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; } .btn-ghost { background: transparent; } .btn-danger { background: transparent; color: var(--danger); border-color: var(--danger); } +.btn-danger-solid { background: var(--danger); border-color: var(--danger); color: #fff; } .btn[disabled] { opacity: 0.5; pointer-events: none; } .row { display: flex; align-items: center; gap: 10px; } @@ -92,6 +93,30 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent); } .error-text { color: var(--danger); font-size: 13px; } +/* Модальное окно подтверждения */ +.modal-overlay { + position: fixed; + inset: 0; + z-index: 300; + background: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + padding: 24px; +} +.modal { + width: 100%; + max-width: 360px; + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 18px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); +} +.modal-title { font-weight: 700; font-size: 16px; margin-bottom: 8px; } +.modal-msg { color: var(--text-muted); font-size: 14px; margin: 0 0 16px; } +.modal-actions { display: flex; justify-content: flex-end; gap: 8px; } + /* «Барабан» рандома фракции — мелькающее название вместо select */ .faction-spin { display: flex;