import { useState, useEffect, useCallback } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import type { ServiceCatalog, ServiceApiItem } from '../../types/apihub'; import { getServiceCatalog } from '../../services/apiHubService'; const METHOD_COLORS: Record = { GET: 'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300', POST: 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300', PUT: 'bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300', PATCH: 'bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300', DELETE: 'bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300', }; const HEALTH_DOT: Record = { UP: 'bg-green-500', DOWN: 'bg-red-500', UNKNOWN: 'bg-gray-400', }; const HEALTH_BADGE: Record = { UP: 'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300', DOWN: 'bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300', UNKNOWN: 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300', }; const HEALTH_LABEL: Record = { UP: '정상', DOWN: '중단', UNKNOWN: '알 수 없음', }; interface DomainSectionProps { domainName: string; apis: ServiceApiItem[]; serviceId: number; onNavigate: (serviceId: number, apiId: number) => void; } const DomainSection = ({ domainName, apis, serviceId, onNavigate }: DomainSectionProps) => (

{domainName}

{apis.length}개
{apis.map((api) => ( onNavigate(serviceId, api.apiId)} > ))}
메서드 경로 API명 설명 상태
{api.apiMethod} {api.apiPath} {api.apiName} {api.description || -} {api.isActive ? ( ) : ( )}
); const ApiHubServicePage = () => { const { serviceId } = useParams<{ serviceId: string }>(); const navigate = useNavigate(); const [service, setService] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { if (!serviceId) return; try { const res = await getServiceCatalog(Number(serviceId)); if (res.success && res.data) { setService(res.data); } else { setError('서비스 정보를 불러오지 못했습니다'); } } catch { setError('서비스 정보를 불러오는 중 오류가 발생했습니다'); } finally { setIsLoading(false); } }, [serviceId]); useEffect(() => { fetchData(); }, [fetchData]); const handleApiNavigate = (svcId: number, apiId: number) => { navigate(`/api-hub/services/${svcId}/apis/${apiId}`); }; if (isLoading) { return (
로딩 중...
); } if (error || !service) { return (
{error ?? '서비스를 찾을 수 없습니다'}
); } const domainsMap = new Map(); for (const dg of service.domains) { const key = dg.domain ? dg.domain.toUpperCase() : '기타'; domainsMap.set(key, dg.apis); } // If any apis fall under null domain and weren't covered by domains array, show them under 기타 const domainEntries = [...domainsMap.entries()]; return (
{/* Service Header */}

{service.serviceName}

{service.serviceCode}
{service.description && (

{service.description}

)}
{HEALTH_LABEL[service.healthStatus] ?? service.healthStatus}
API {service.apiCount}개 도메인 {service.domains.length}개
{/* API 목록 by Domain */} {domainEntries.length > 0 ? ( domainEntries.map(([domain, apis]) => ( )) ) : (
등록된 API가 없습니다
)}
); }; export default ApiHubServicePage;