fix(requests): confirm destructive actions and align surfaces

This commit is contained in:
lizerk 2026-04-12 07:19:12 +03:00
parent b7b09740cb
commit 1552bbe84b
4 changed files with 33 additions and 4 deletions

View File

@ -514,7 +514,7 @@ class RequestViewSet(viewsets.ModelViewSet):
req_obj = self.get_object()
# Получаем чат для этой заявки
chat = comments_helpers.get_or_create_comments_chat(req_obj)[0]
chat = comments_helpers.get_or_create_comments_chat(req_obj)
# Находим комментарий
try:

View File

@ -386,6 +386,32 @@ def test_comments_allowed_for_admin_and_manager(
assert post_r.status_code == 201, "Получатель должен уметь создавать комментарий"
def test_comment_author_can_delete_own_comment(
auth_client,
regular_user: models.Model,
make_request,
) -> None:
"""Автор комментария может удалить свой комментарий без 500."""
req = make_request(employee=regular_user)
client = auth_client(regular_user)
post_resp = client.post(
f"{API_BASE}{req.id}/comments/",
data={"text": "удаляемый комментарий"},
format="json",
)
assert post_resp.status_code == 201
comment_id = post_resp.json()["id"]
delete_resp = client.delete(f"{API_BASE}{req.id}/comments/{comment_id}/")
assert delete_resp.status_code == 204
list_resp = client.get(f"{API_BASE}{req.id}/comments/")
assert list_resp.status_code == 200
ids = {item["id"] for item in _results(list_resp.json())}
assert comment_id not in ids
# ------------------------------------------------------------------------------
# 8) ФИЛЬТРЫ
# ------------------------------------------------------------------------------
@ -434,4 +460,4 @@ def test_invalid_filter_does_not_crash(auth_client, admin_user: models.Model) ->
"""Странные значения фильтров не приводят к 500."""
client = auth_client(admin_user)
resp = client.get(f"{API_BASE}?type=__sql__' OR 1=1 --&status=")
assert resp.status_code == 200
assert resp.status_code == 200

View File

@ -235,7 +235,7 @@ function RequestsPageContent() {
const summary = item.comment || item.description;
return (
<article key={item.id} className="app-surface overflow-hidden rounded-xl transition hover:border-[var(--border-strong)]">
<article key={item.id} className="app-surface-muted overflow-hidden rounded-xl transition hover:border-[var(--border-strong)]">
<div className="p-4">
<div className="flex items-start gap-3">
<button type="button" onClick={() => h.toggleRow(item.id)} className="app-action-secondary mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg transition"><ChevronDown size={15} className={`transition ${rowOpen ? "rotate-180" : ""}`} /></button>
@ -271,7 +271,7 @@ function RequestsPageContent() {
</div>
{(rowOpen || commentsOpen) && (
<div className="app-surface-muted mt-4 rounded-xl p-4">
<div className="app-surface-elevated mt-4 rounded-xl p-4">
{rowOpen && (
<div className="space-y-3 text-xs">
<div className="grid grid-cols-1 gap-x-4 gap-y-2 sm:grid-cols-2">

View File

@ -320,6 +320,9 @@ export function useRequestsPage(_userId: number | null | undefined) {
};
const handleDelete = async (id: number) => {
if (!window.confirm("Удалить заявление? Это действие нельзя отменить.")) {
return;
}
try { setBusyKey(`delete-${id}`); setActionError(null); await apiClient.deleteRequest(id); setRequests((p) => p.filter((r) => r.id !== id)); }
catch (e: unknown) { setActionError(String((e as Error)?.message || "Не удалось удалить")); }
finally { setBusyKey(null); }