import Link from 'next/link'; import { useRouter } from 'next/router'; import { useCallback, useState } from 'react'; import { FiEdit2, FiPlus, FiTrash2 } from 'react-icons/fi'; import AdminLayout from '../../../components/admin/AdminLayout'; import AdminTable from '../../../components/admin/AdminTable'; import { AdminApiError, fetchAdmin } from '../../../lib/admin/api'; import { requireAuth } from '../../../lib/admin/requireAuth'; function AdminProjectsList({ initialProjects }) { const router = useRouter(); const [projects, setProjects] = useState(initialProjects); const [pendingId, setPendingId] = useState(null); const [error, setError] = useState(''); const handleDelete = useCallback( async (project) => { const confirmed = window.confirm( `'${project.title}' 프로젝트를 삭제할까요? 연관 이미지·상세·기술 목록도 함께 제거됩니다.`, ); if (!confirmed) return; setError(''); setPendingId(project.id); try { await fetchAdmin(`/api/admin/projects/${project.id}`, { method: 'DELETE' }); setProjects((prev) => prev.filter((p) => p.id !== project.id)); } catch (err) { if (err instanceof AdminApiError && err.status === 401) { router.replace('/admin/login'); return; } setError(err?.message ?? '삭제에 실패했습니다.'); } finally { setPendingId(null); } }, [router], ); return (

총 {projects.length}개 프로젝트

새 프로젝트
{error && (

{error}

)} ( {row.url} ), }, { key: 'category', label: '카테고리' }, ]} rows={projects} actions={(row) => ( <> 편집 )} emptyMessage="등록된 프로젝트가 없습니다. 새 프로젝트를 만들어보세요." />
); } const API_BASE_URL = process.env.API_INTERNAL_URL || 'http://localhost:7341'; export const getServerSideProps = requireAuth(async (ctx) => { // 목록은 공개 엔드포인트 재사용 (관리자 전용 목록이 따로 필요 없음) const cookieHeader = ctx.req?.headers?.cookie ?? ''; const res = await fetch(`${API_BASE_URL}/api/projects`, { headers: cookieHeader ? { cookie: cookieHeader } : undefined, }); if (!res.ok) { throw new Error(`[admin projects] list API returned ${res.status}`); } const body = await res.json(); return { props: { initialProjects: body?.data ?? [] } }; }); export default AdminProjectsList;