From c872985f96f6d98d5ba6706af39319201586f0e8 Mon Sep 17 00:00:00 2001 From: SEAN Date: Wed, 18 Mar 2026 12:58:14 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#49)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - service.api.ts: deleteService API 함수 추가 (POST /v1/in/service/delete) - ServiceHeaderCard: 수정하기 버튼 옆 삭제하기 버튼 추가 - ServiceDetailPage: 삭제 확인 모달 및 핸들러 추가 (삭제 후 목록으로 이동) Closes #49 --- react/src/api/service.api.ts | 7 ++ .../service/components/ServiceHeaderCard.tsx | 25 +++++-- .../service/pages/ServiceDetailPage.tsx | 75 ++++++++++++++++++- 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/react/src/api/service.api.ts b/react/src/api/service.api.ts index 2c397ef..8943de6 100644 --- a/react/src/api/service.api.ts +++ b/react/src/api/service.api.ts @@ -79,3 +79,10 @@ export function deleteApns(serviceCode: string) { `/v1/in/service/${serviceCode}/apns/delete`, ); } + +/** 서비스 삭제 */ +export function deleteService(serviceCode: string) { + return apiClient.post>("/v1/in/service/delete", { + service_code: serviceCode, + }); +} diff --git a/react/src/features/service/components/ServiceHeaderCard.tsx b/react/src/features/service/components/ServiceHeaderCard.tsx index 87f9351..d1b0fac 100644 --- a/react/src/features/service/components/ServiceHeaderCard.tsx +++ b/react/src/features/service/components/ServiceHeaderCard.tsx @@ -9,11 +9,13 @@ import { SERVICE_STATUS } from "../types"; interface ServiceHeaderCardProps { service: ServiceDetail; onShowApiKey: () => void; + onDelete: () => void; } export default function ServiceHeaderCard({ service, onShowApiKey, + onDelete, }: ServiceHeaderCardProps) { return (
@@ -62,13 +64,22 @@ export default function ServiceHeaderCard({
- - edit - 수정하기 - +
+ + + edit + 수정하기 + +
{/* 메타 정보 */} diff --git a/react/src/features/service/pages/ServiceDetailPage.tsx b/react/src/features/service/pages/ServiceDetailPage.tsx index f817d1b..4341f89 100644 --- a/react/src/features/service/pages/ServiceDetailPage.tsx +++ b/react/src/features/service/pages/ServiceDetailPage.tsx @@ -1,17 +1,19 @@ import { useState, useEffect, useCallback } from "react"; -import { useParams } from "react-router-dom"; +import { useParams, useNavigate } from "react-router-dom"; +import { toast } from "sonner"; import PageHeader from "@/components/common/PageHeader"; import CopyButton from "@/components/common/CopyButton"; import ServiceHeaderCard from "../components/ServiceHeaderCard"; import ServiceStatsCards from "../components/ServiceStatsCards"; import PlatformManagement from "../components/PlatformManagement"; -import { fetchServiceDetail, fetchApiKey } from "@/api/service.api"; +import { fetchServiceDetail, fetchApiKey, deleteService } from "@/api/service.api"; import { fetchDashboard } from "@/api/dashboard.api"; import type { ServiceDetail } from "../types"; import type { DashboardKpi } from "@/features/dashboard/types"; export default function ServiceDetailPage() { const { id } = useParams<{ id: string }>(); + const navigate = useNavigate(); // 데이터 상태 const [service, setService] = useState(null); @@ -26,6 +28,10 @@ export default function ServiceDetailPage() { const [fullApiKey, setFullApiKey] = useState(null); const [apiKeyLoading, setApiKeyLoading] = useState(false); + // 삭제 모달 상태 + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [deleting, setDeleting] = useState(false); + // 서비스 상세 + 통계 로드 const loadData = useCallback(async (serviceCode: string) => { setLoading(true); @@ -105,6 +111,21 @@ export default function ServiceDetailPage() { setFullApiKey(null); }; + // 서비스 삭제 + const handleDelete = async () => { + if (!id) return; + setDeleting(true); + try { + await deleteService(id); + toast.success("서비스가 삭제되었습니다."); + navigate("/services"); + } catch { + toast.error("서비스 삭제에 실패했습니다."); + } finally { + setDeleting(false); + } + }; + // 로딩 스켈레톤 if (loading) { return ( @@ -168,6 +189,7 @@ export default function ServiceDetailPage() { setShowDeleteConfirm(true)} /> + {/* 삭제 확인 모달 */} + {showDeleteConfirm && ( +
+
setShowDeleteConfirm(false)} + /> +
+
+
+ + warning + +
+

서비스 삭제

+
+

+ {service.serviceName} 서비스를 삭제하시겠습니까? +

+
+
+ info + 삭제된 서비스는 복구할 수 없습니다. +
+
+ info + 해당 서비스의 모든 기기 및 발송 이력이 비활성화됩니다. +
+
+
+ + +
+
+
+ )} + {/* API 키 확인 모달 */} {showApiKey && (
-- 2.45.1