'use client'; import './style.scss'; import { useState, useEffect, useCallback } from 'react'; import { fetchApi } from '@/lib/utils/client'; import { useStudioContext } from '@/app/studio/context'; import type { CrewListResponse, CrewItem } from '@/types/response/crew/list'; const EMPTY_FORM = { name: '', description: '', minAmount: '' as string|number, isActive: true }; export default function CrewConfigPage() { const { channelID } = useStudioContext(); const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [modal, setModal] = useState<{ open: boolean; editing: CrewItem|null }>({ open: false, editing: null }); const [form, setForm] = useState(EMPTY_FORM); const [saving, setSaving] = useState(false); useEffect(() => { if (error) { alert(error); setError(''); } }, [error]); const fetchList = useCallback(() => { if (!channelID) { setLoading(false); return; } setLoading(true); fetchApi(`/api/studio/crew/list/${channelID}`).then(res => { setItems(res.data?.list ?? []); }) .catch(err => setError(err.message)) .finally(() => setLoading(false)); }, [channelID]); useEffect(() => { fetchList(); }, [fetchList]); const openAdd = () => { setForm(EMPTY_FORM); setModal({ open: true, editing: null }); }; const openEdit = (item: CrewItem) => { setForm({ name: item.name, description: item.description ?? '', minAmount: item.minAmount ?? '', isActive: item.isActive }); setModal({ open: true, editing: item }); }; const closeModal = () => setModal({ open: false, editing: null }); const handleSave = async () => { if (!form.name.trim()) { alert('크루명을 입력해 주세요.'); return; } setSaving(true); try { const body = { channelID, id: modal.editing?.id ?? undefined, name: form.name, description: form.description || undefined, minAmount: form.minAmount !== '' ? Number(form.minAmount) : undefined, isActive: form.isActive }; const res = await fetchApi('/api/studio/crew/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); closeModal(); fetchList(); } catch (err: unknown) { setError(err instanceof Error ? err.message : '저장에 실패했습니다.'); } finally { setSaving(false); } }; return (

크루 후원 설정

{loading ? (

준비 중...

) : ( {items.length === 0 ? ( ) : ( items.map(item => ( )) )}
크루명 설명 최소 후원금 멤버 수 활성 작업
등록된 크루가 없습니다.
{item.name} {item.description ?? '-'} {item.minAmount ? `${item.minAmount.toLocaleString()}원` : '-'} {item.memberCount}명 {item.isActive ? '활성' : '비활성'}
)}
{modal.open && (

{modal.editing ? '크루 수정' : '크루 추가'}

setForm(f => ({ ...f, name: e.target.value }))} title='크루명' />
setForm(f => ({ ...f, description: e.target.value }))} title='설명' />
setForm(f => ({ ...f, minAmount: e.target.value }))} />

이 금액 이상 후원한 회원만 크루에 가입할 수 있습니다.

)}
); }