import { isLoginRequiredError } from '@_api/apiClient'; import { createThemeV2, deleteTheme, fetchAdminThemeDetail, updateTheme } from '@_api/theme/themeAPI'; import { Difficulty, type ThemeCreateRequestV2, type ThemeUpdateRequest, type ThemeV2 } from '@_api/theme/themeTypes'; import React, { useEffect, useState } from 'react'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import '../../css/admin-theme-edit-page.css'; const AdminThemeEditPage: React.FC = () => { const { themeId } = useParams<{ themeId: string }>(); const navigate = useNavigate(); const location = useLocation(); const isNew = themeId === 'new'; const [theme, setTheme] = useState(null); const [originalTheme, setOriginalTheme] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isEditing, setIsEditing] = useState(isNew); const handleError = (err: any) => { if (isLoginRequiredError(err)) { alert('로그인이 필요해요.'); navigate('/login', { state: { from: location } }); } else { const message = err.response?.data?.message || '알 수 없는 오류가 발생했습니다.'; alert(message); console.error(err); } }; useEffect(() => { if (isNew) { const newTheme: ThemeCreateRequestV2 = { name: '', description: '', thumbnailUrl: '', difficulty: Difficulty.NORMAL, price: 0, minParticipants: 2, maxParticipants: 4, availableMinutes: 60, expectedMinutesFrom: 50, expectedMinutesTo: 70, isOpen: true, }; setTheme(newTheme); setOriginalTheme(newTheme); setIsLoading(false); } else if (themeId) { fetchAdminThemeDetail(themeId) .then(data => { // Map AdminThemeDetailRetrieveResponse to ThemeV2 const fetchedTheme: ThemeV2 = { id: data.id, name: data.name, description: data.description, thumbnailUrl: data.thumbnailUrl, difficulty: data.difficulty, price: data.price, minParticipants: data.minParticipants, maxParticipants: data.maxParticipants, availableMinutes: data.availableMinutes, expectedMinutesFrom: data.expectedMinutesFrom, expectedMinutesTo: data.expectedMinutesTo, isOpen: data.isOpen, createDate: data.createdAt, // Map createdAt to createDate updatedDate: data.updatedAt, // Map updatedAt to updatedDate createdBy: data.createdBy, updatedBy: data.updatedBy, }; setTheme(fetchedTheme); setOriginalTheme(fetchedTheme); }) .catch(handleError) .finally(() => setIsLoading(false)); } }, [themeId, isNew, navigate]); const handleChange = (e: React.ChangeEvent) => { const { name, value, type } = e.target; let processedValue: string | number | boolean = value; if (name === 'isOpen') { processedValue = value === 'true'; } else if (type === 'checkbox') { processedValue = (e.target as HTMLInputElement).checked; } else if (type === 'number') { processedValue = value === '' ? '' : Number(value); } setTheme(prev => prev ? { ...prev, [name]: processedValue } : null); }; const handleCancelEdit = () => { if (!isNew) { setTheme(originalTheme); setIsEditing(false); } else { navigate('/admin/theme'); } }; const handleSubmit = async (e: React.FormEvent) => { console.log('handleSubmit called'); e.preventDefault(); if (!theme) return; try { if (isNew) { await createThemeV2(theme as ThemeCreateRequestV2); alert('테마가 성공적으로 생성되었습니다.'); navigate(`/admin/theme`); } else { if (!themeId) { throw new Error('themeId is undefined'); } await updateTheme(themeId, theme as ThemeUpdateRequest); alert('테마가 성공적으로 업데이트되었습니다.'); setOriginalTheme(theme); setIsEditing(false); navigate(`/admin/theme`); } } catch (error) { handleError(error); } }; const handleDelete = async () => { if (isNew || !themeId) return; if (window.confirm('정말로 이 테마를 삭제하시겠습니까?')) { try { await deleteTheme(themeId); alert('테마가 삭제되었습니다.'); navigate('/admin/theme'); } catch (error) { handleError(error); } } }; if (isLoading) { return

로딩 중...

; } if (!theme) { return

테마 정보를 찾을 수 없습니다.

; } return (

{isNew ? '새 테마 추가' : '테마 정보 수정'}