From 5ba8c5db5ec5a1e88c8eec41200a5a1f21f79a19 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jul 2026 19:16:12 +0900 Subject: [PATCH] feat: allow admin delete from dashboard --- frontend/src/pages/DashboardPage.tsx | 63 ++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/DashboardPage.tsx b/frontend/src/pages/DashboardPage.tsx index eafd479..2a3c102 100644 --- a/frontend/src/pages/DashboardPage.tsx +++ b/frontend/src/pages/DashboardPage.tsx @@ -1,9 +1,11 @@ import React, { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; -import { getStatsSummary, listInside, listTodayAccess, listVisitRequests } from '../api'; +import { deleteVisitRequest, getStatsSummary, listInside, listTodayAccess, listVisitRequests } from '../api'; import { StatsSummary, VisitRequestView } from '../types'; import { STATUS_CLASS, STATUS_LABEL, formatDateTime } from '../status'; import { VisitRequestDetailDialog } from '../components/VisitRequestDetailDialog'; +import { Dialog } from '../components/Dialog'; +import { useAuth } from '../auth/AuthContext'; export const DashboardPage: React.FC = () => { const [items, setItems] = useState([]); @@ -12,12 +14,14 @@ export const DashboardPage: React.FC = () => { const [exitedIds, setExitedIds] = useState>(new Set()); const [checkOutById, setCheckOutById] = useState>(new Map()); const [detailId, setDetailId] = useState(null); + const [deleting, setDeleting] = useState(null); const [error, setError] = useState(null); + const [notice, setNotice] = useState(null); const [loading, setLoading] = useState(true); + const { hasRole } = useAuth(); - useEffect(() => { + const loadDashboard = () => { getStatsSummary().then(setStats).catch(() => setStats(null)); - // currently-inside visits → show "재실중" instead of the plain approved status listInside() .then((rows) => setInsideIds(new Set(rows.map((r) => r.visitRequestId)))) .catch(() => setInsideIds(new Set())); @@ -38,8 +42,32 @@ export const DashboardPage: React.FC = () => { .then(setItems) .catch((e) => setError(e instanceof Error ? e.message : '조회 실패')) .finally(() => setLoading(false)); + }; + + useEffect(() => { + loadDashboard(); }, []); + const confirmDelete = async (text?: string) => { + const target = deleting; + if (!target) return; + if (text !== '삭제') { + setDeleting(null); + setError('삭제하려면 확인 입력란에 "삭제"를 입력하세요.'); + return; + } + setDeleting(null); + setError(null); + setNotice(null); + try { + await deleteVisitRequest(target.id); + setNotice(`${target.visitorName} 신청을 삭제했습니다.`); + loadDashboard(); + } catch (e) { + setError(e instanceof Error ? e.message : '삭제 실패'); + } + }; + return (
@@ -48,6 +76,7 @@ export const DashboardPage: React.FC = () => {
{error &&
{error}
} + {notice &&
{notice}
}
@@ -67,7 +96,7 @@ export const DashboardPage: React.FC = () => { - + @@ -98,6 +127,19 @@ export const DashboardPage: React.FC = () => { {STATUS_LABEL[r.status]} )} + ))} @@ -108,6 +150,19 @@ export const DashboardPage: React.FC = () => { {detailId != null && ( setDetailId(null)} /> )} + + {deleting != null && ( + setDeleting(null)} + /> + )} ); };
방문자회사출입구역출입 일시퇴장 일시상태방문자회사출입구역출입 일시퇴장 일시상태
+ {hasRole('ADMIN') && ( + + )} +