'use client'; /** * 환율 위젯 컴포넌트 * - 실시간 환율 정보를 표시 * - 한국은행(BOK) API 연동 */ import React, { useEffect, useState } from 'react'; import { getExchangeRate, ExchangeRateData } from '@/lib/api/openApi'; import { TrendingUp, TrendingDown, RefreshCw, ArrowRightLeft } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Input } from '@/components/ui/input'; import { DashboardElement } from '@/components/admin/dashboard/types'; interface ExchangeWidgetProps { element?: DashboardElement; baseCurrency?: string; targetCurrency?: string; refreshInterval?: number; // 새로고침 간격 (ms), 기본값: 600000 (10분) } export default function ExchangeWidget({ element, baseCurrency = 'KRW', targetCurrency = 'USD', refreshInterval = 600000, }: ExchangeWidgetProps) { const [base, setBase] = useState(baseCurrency); const [target, setTarget] = useState(targetCurrency); const [exchangeRate, setExchangeRate] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [lastUpdated, setLastUpdated] = useState(null); const [calculatorAmount, setCalculatorAmount] = useState(''); const [displayAmount, setDisplayAmount] = useState(''); // 지원 통화 목록 const currencies = [ { value: 'KRW', label: '🇰🇷 KRW (원)', symbol: '₩' }, { value: 'USD', label: '🇺🇸 USD (달러)', symbol: '$' }, { value: 'EUR', label: '🇪🇺 EUR (유로)', symbol: '€' }, { value: 'JPY', label: '🇯🇵 JPY (엔)', symbol: '¥' }, { value: 'CNY', label: '🇨🇳 CNY (위안)', symbol: '¥' }, { value: 'GBP', label: '🇬🇧 GBP (파운드)', symbol: '£' }, ]; // 환율 조회 const fetchExchangeRate = async () => { try { setError(null); setLoading(true); const data = await getExchangeRate(base, target); setExchangeRate(data); setLastUpdated(new Date()); } catch (err: any) { console.error('환율 조회 실패:', err); let errorMessage = '환율 정보를 가져오는 중 오류가 발생했습니다.'; if (err.response?.status === 503) { errorMessage = 'API 키가 설정되지 않았습니다. 관리자에게 문의하세요.'; } else if (err.response?.status === 401) { errorMessage = 'API 키가 유효하지 않습니다.'; } else if (err.response?.data?.message) { errorMessage = err.response.data.message; } setError(errorMessage); } finally { setLoading(false); } }; // 초기 로딩 및 자동 새로고침 useEffect(() => { fetchExchangeRate(); const interval = setInterval(fetchExchangeRate, refreshInterval); return () => clearInterval(interval); }, [base, target, refreshInterval]); // 통화 스왑 const handleSwap = () => { setBase(target); setTarget(base); }; // 통화 기호 가져오기 const getCurrencySymbol = (currency: string) => { return currencies.find((c) => c.value === currency)?.symbol || currency; }; // 계산기 금액 입력 처리 const handleCalculatorInput = (e: React.ChangeEvent) => { const value = e.target.value; // 쉼표 제거 후 숫자만 추출 const cleanValue = value.replace(/,/g, '').replace(/[^\d]/g, ''); // 계산용 원본 값 저장 setCalculatorAmount(cleanValue); // 표시용 포맷팅된 값 저장 if (cleanValue === '') { setDisplayAmount(''); } else { const num = parseInt(cleanValue); setDisplayAmount(num.toLocaleString('ko-KR')); } }; // 계산 결과 const calculateResult = () => { const amount = parseFloat(calculatorAmount || '0'); if (!exchangeRate || isNaN(amount)) return 0; return amount * (base === 'KRW' ? exchangeRate.rate : 1 / exchangeRate.rate); }; // 로딩 상태 if (loading && !exchangeRate) { return (

환율 정보 불러오는 중...

); } // 에러 상태 - 하지만 계산기는 표시 const hasError = error || !exchangeRate; return (
{/* 헤더 */}

{element?.customTitle || "환율"}

{lastUpdated ? `업데이트: ${lastUpdated.toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit', })}` : ''}

{/* 통화 선택 - 반응형 (좁을 때 세로 배치) */}
{/* 에러 메시지 */} {hasError && (

{error || '환율 정보를 불러올 수 없습니다.'}

)} {/* 환율 표시 */} {!hasError && (
{exchangeRate.base === 'KRW' ? '1,000' : '1'} {getCurrencySymbol(exchangeRate.base)} =
{exchangeRate.base === 'KRW' ? (exchangeRate.rate * 1000).toLocaleString('ko-KR', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : exchangeRate.rate.toLocaleString('ko-KR', { minimumFractionDigits: 2, maximumFractionDigits: 4, })}
{getCurrencySymbol(exchangeRate.target)}
)} {/* 계산기 입력 */}
{base}
{calculateResult().toLocaleString('ko-KR', { minimumFractionDigits: 0, maximumFractionDigits: 2, })}
{target}
{/* 데이터 출처 */}

출처: {exchangeRate.source}

); }