- service.api.ts: deleteService API 함수 추가 (POST /v1/in/service/delete) - ServiceHeaderCard: 수정하기 버튼 옆 삭제하기 버튼 추가 - ServiceDetailPage: 삭제 확인 모달 및 핸들러 추가 (삭제 후 목록으로 이동) Closes #49
140 lines
5.3 KiB
TypeScript
140 lines
5.3 KiB
TypeScript
import { Link } from "react-router-dom";
|
|
import StatusBadge from "@/components/common/StatusBadge";
|
|
import CopyButton from "@/components/common/CopyButton";
|
|
import PlatformStatusIndicator from "./PlatformStatusIndicator";
|
|
import { formatNumber } from "@/utils/format";
|
|
import type { ServiceDetail } from "../types";
|
|
import { SERVICE_STATUS } from "../types";
|
|
|
|
interface ServiceHeaderCardProps {
|
|
service: ServiceDetail;
|
|
onShowApiKey: () => void;
|
|
onDelete: () => void;
|
|
}
|
|
|
|
export default function ServiceHeaderCard({
|
|
service,
|
|
onShowApiKey,
|
|
onDelete,
|
|
}: ServiceHeaderCardProps) {
|
|
return (
|
|
<div className="bg-white border border-gray-200 rounded-lg shadow-sm p-6 mb-6">
|
|
{/* 상단 행 */}
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-4">
|
|
<div className="size-14 rounded-xl bg-[#2563EB]/10 flex items-center justify-center">
|
|
<span className="material-symbols-outlined text-[#2563EB] text-3xl">
|
|
{service.serviceIcon || "hub"}
|
|
</span>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<div className="flex items-center gap-3">
|
|
<h2 className="text-2xl font-bold text-[#0f172a]">
|
|
{service.serviceName}
|
|
</h2>
|
|
<StatusBadge
|
|
variant={
|
|
service.status === SERVICE_STATUS.ACTIVE ? "success" : "error"
|
|
}
|
|
label={
|
|
service.status === SERVICE_STATUS.ACTIVE ? "활성" : "비활성"
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-4 mt-1.5">
|
|
<div className="inline-flex items-center gap-1.5">
|
|
<span className="text-sm text-[#64748b] font-mono">
|
|
{service.serviceCode}
|
|
</span>
|
|
<CopyButton text={service.serviceCode} />
|
|
</div>
|
|
<span className="text-gray-300">|</span>
|
|
<button
|
|
onClick={onShowApiKey}
|
|
className="flex items-center gap-1 text-sm text-[#2563EB] hover:text-[#1d4ed8] transition-colors cursor-pointer"
|
|
>
|
|
<span
|
|
className="material-symbols-outlined"
|
|
style={{ fontSize: "14px" }}
|
|
>
|
|
vpn_key
|
|
</span>
|
|
<span className="font-medium">API 키 확인</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={onDelete}
|
|
className="border border-red-200 text-red-500 hover:bg-red-50 px-5 py-2.5 rounded text-sm font-medium transition flex items-center gap-2"
|
|
>
|
|
<span className="material-symbols-outlined text-base">delete</span>
|
|
<span>삭제하기</span>
|
|
</button>
|
|
<Link
|
|
to={`/services/${service.serviceCode}/edit`}
|
|
className="bg-[#2563EB] hover:bg-[#1d4ed8] text-white px-5 py-2.5 rounded text-sm font-medium transition shadow-sm flex items-center gap-2"
|
|
>
|
|
<span className="material-symbols-outlined text-base">edit</span>
|
|
<span>수정하기</span>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 메타 정보 */}
|
|
<div className="mt-6 pt-5 border-t border-gray-100 grid grid-cols-2 sm:grid-cols-4 gap-6">
|
|
<div className="flex flex-col">
|
|
<p className="text-xs text-[#64748b] font-semibold uppercase tracking-wide">
|
|
플랫폼
|
|
</p>
|
|
<div className="flex items-center gap-2.5 mt-1.5">
|
|
{service.platforms ? (
|
|
<>
|
|
<PlatformStatusIndicator
|
|
platform="android"
|
|
credential={service.platforms.android}
|
|
/>
|
|
<PlatformStatusIndicator
|
|
platform="ios"
|
|
credential={service.platforms.ios}
|
|
/>
|
|
{!service.platforms?.android?.registered &&
|
|
!service.platforms?.ios?.registered && (
|
|
<span className="text-xs text-gray-400">없음</span>
|
|
)}
|
|
</>
|
|
) : (
|
|
<span className="text-xs text-gray-400">없음</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<p className="text-xs text-[#64748b] font-semibold uppercase tracking-wide">
|
|
등록 기기
|
|
</p>
|
|
<p className="text-sm font-semibold text-[#0f172a] mt-1.5">
|
|
{formatNumber(service.deviceCount)}대
|
|
</p>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<p className="text-xs text-[#64748b] font-semibold uppercase tracking-wide">
|
|
생성일
|
|
</p>
|
|
<p className="text-sm font-semibold text-[#0f172a] mt-1.5">
|
|
{service.createdAt?.slice(0, 10)}
|
|
</p>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<p className="text-xs text-[#64748b] font-semibold uppercase tracking-wide">
|
|
마지막 업데이트
|
|
</p>
|
|
<p className="text-sm font-semibold text-[#0f172a] mt-1.5">
|
|
{service.updatedAt?.slice(0, 10) ?? "-"}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|