'use client'; import { useCallback, useEffect, useState } from 'react'; import { fetchApi } from '@/lib/utils/client'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { formatTokenNumber } from '@/lib/utils/paper'; import type { PaperAccountResponse, PaperDepositResponse, PaperWithdrawResponse } from '@/types/paper'; // 지갑 토큰(Reward+Airdrop) 합산용 최소 타입 — GET /api/wallet interface WalletBalanceRow { type: string; amount: number; } interface WalletResponse { balances: WalletBalanceRow[]; } type Props = { mode: 'deposit'|'withdraw'; account: PaperAccountResponse|null; onClose: () => void; onDone: () => void; }; const TOKEN_TYPES = ['Reward', 'Airdrop']; export default function PaperDepositWithdrawModal({ mode, account, onClose, onDone }: Props) { const isDeposit = mode === 'deposit'; const [amount, setAmount] = useState(''); const [all, setAll] = useState(false); const [walletToken, setWalletToken] = useState(null); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); // 입금 모드: 지갑 가용 토큰 조회 useEffect(() => { if (!isDeposit) { return; } let cancelled = false; (async () => { const res = await fetchApi('/api/wallet', { silent: true }); if (cancelled) { return; } if (res.success && res.data) { const sum = res.data.balances .filter(c => TOKEN_TYPES.includes(c.type)) .reduce((acc, c) => acc + c.amount, 0); setWalletToken(sum); } else { setWalletToken(null); } })(); return () => { cancelled = true; }; }, [isDeposit]); const submit = useCallback(async () => { setError(null); const numeric = Number(amount); if (!isDeposit && all) { // 전액 출금 — 금액 불필요 } else if (!Number.isInteger(numeric) || numeric <= 0) { setError('1 이상의 정수 토큰 금액을 입력해 주세요.'); return; } setBusy(true); const endpoint = isDeposit ? '/api/paper/account/deposit' : '/api/paper/account/withdraw'; const body = isDeposit ? { tokenAmount: numeric } : (all ? { all: true } : { tokenAmount: numeric }); const res = await fetchApi(endpoint, { method: 'POST', body, silent: true }); setBusy(false); if (res.success && res.data) { onDone(); } else { setError(res.message || `${isDeposit ? '입금' : '출금'}에 실패했습니다.`); } }, [amount, all, isDeposit, onDone]); return ( { if (!open) onClose(); }}> {isDeposit ? '토큰 입금' : '토큰 출금'}
{isDeposit ? (

지갑 가용 토큰 {walletToken === null ? '—' : formatTokenNumber(walletToken)}

) : (

계좌 가용 토큰 {formatTokenNumber(account?.token ?? 0)}

)} {!isDeposit && ( )} {!(!isDeposit && all) && (
{isDeposit ? '입금' : '출금'} 토큰 setAmount(e.target.value)} placeholder='토큰 수량' autoFocus />
)}

{isDeposit ? '입금한 토큰만큼 좌수가 발행되며, 지갑 토큰이 차감됩니다.' : '출금한 토큰만큼 좌수가 소각되며, 지갑 토큰으로 환급됩니다.'}

{error &&

{error}

}
); }