Add confirmation modal for project deletion
All checks were successful
ci/woodpecker/push/build Pipeline was successful

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-03-19 15:44:38 +03:00
parent ea8463e8bc
commit 1f25b9c104
2 changed files with 99 additions and 4 deletions

View File

@@ -176,6 +176,60 @@ h2 {
background: #e74c3c;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
}
.modal {
background: white;
border-radius: 8px;
padding: 1.5rem 2rem;
min-width: 300px;
text-align: center;
}
.modal p {
font-size: 1.1rem;
margin-bottom: 1.5rem;
}
.modal-actions {
display: flex;
gap: 0.75rem;
justify-content: center;
}
.modal-actions button {
padding: 0.5rem 1.25rem;
font-size: 1rem;
cursor: pointer;
border: 1px solid #ccc;
border-radius: 4px;
background: #333;
color: white;
}
.modal-actions button:hover {
background: #555;
}
.modal-actions button.danger {
background: #c0392b;
}
.modal-actions button.danger:hover {
background: #e74c3c;
}
.vpn-block {
display: flex;
justify-content: center;

View File

@@ -11,6 +11,28 @@ import {
} from "./api";
import "./App.css";
function ConfirmModal({
message,
onConfirm,
onCancel,
}: {
message: string;
onConfirm: () => void;
onCancel: () => void;
}) {
return (
<div className="modal-overlay" onClick={onCancel}>
<div className="modal" onClick={(e) => e.stopPropagation()}>
<p>{message}</p>
<div className="modal-actions">
<button onClick={onCancel}>Отмена</button>
<button className="danger" onClick={onConfirm}>Удалить</button>
</div>
</div>
</div>
);
}
function ProjectList({
onSelect,
}: {
@@ -18,6 +40,7 @@ function ProjectList({
}) {
const [projects, setProjects] = useState<ProjectMeta[]>([]);
const [name, setName] = useState("");
const [deleteId, setDeleteId] = useState<number | null>(null);
const load = async () => {
setProjects(await fetchProjects());
@@ -56,10 +79,9 @@ function ProjectList({
</span>
<button
className="project-delete"
onClick={async (e) => {
onClick={(e) => {
e.stopPropagation();
await deleteProject(p.id);
await load();
setDeleteId(p.id);
}}
>
X
@@ -67,6 +89,17 @@ function ProjectList({
</div>
))}
</div>
{deleteId !== null && (
<ConfirmModal
message="Удалить проект?"
onCancel={() => setDeleteId(null)}
onConfirm={async () => {
await deleteProject(deleteId);
setDeleteId(null);
await load();
}}
/>
)}
</>
);
}
@@ -84,6 +117,7 @@ function ProjectPage({
const [content, setContent] = useState("");
const [file, setFile] = useState<File | null>(null);
const [saving, setSaving] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
@@ -184,8 +218,15 @@ function ProjectPage({
{project.file_name && (
<button onClick={handleDownload}>Download file</button>
)}
<button className="danger" onClick={handleDelete}>Delete</button>
<button className="danger" onClick={() => setShowDeleteModal(true)}>Delete</button>
</div>
{showDeleteModal && (
<ConfirmModal
message="Удалить проект?"
onCancel={() => setShowDeleteModal(false)}
onConfirm={handleDelete}
/>
)}
</>
);
}