"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}

); }