Files
AutonetSellCar/frontend/src/lib/exchangeRateStore.ts
AutonetSellCar Deploy 1f0dcb1ddb Initial commit: AutonetSellCar platform with deployment system
- Frontend: Next.js 14 with TypeScript
- Backend: FastAPI with SQLAlchemy
- Agent: Carmodoo sync agent
- Deployment: Docker Compose based staging/production setup
- Scripts: Automated deployment with rollback support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:24:39 +09:00

115 lines
3.6 KiB
TypeScript

/**
* Exchange Rate Store
* 한국수출입은행 API에서 가져온 환율 정보를 저장하고 관리
*/
import { create } from 'zustand';
import { exchangeRateApi, ExchangeRateSimple } from './api';
// 기본 환율 (API 실패 시 사용) - 2024년 12월 기준
const DEFAULT_RATES: ExchangeRateSimple = {
USD: { rate: 1483, symbol: '$', name: '미국 달러' },
MNT: { rate: 0.43, symbol: '₮', name: '몽골 투그릭' },
RUB: { rate: 14.5, symbol: '₽', name: '러시아 루블' },
CNY: { rate: 203, symbol: '¥', name: '중국 위안' },
EUR: { rate: 1750, symbol: '€', name: '유로' },
JPY: { rate: 9.5, symbol: '¥', name: '일본 엔' },
};
interface ExchangeRateState {
rates: ExchangeRateSimple;
isLoading: boolean;
lastUpdated: Date | null;
error: string | null;
fetchRates: () => Promise<void>;
getKrwToUsd: () => number; // KRW를 USD로 변환하는 비율 (1 KRW = X USD)
getUsdToMnt: () => number; // USD를 MNT로 변환하는 비율 (1 USD = X MNT)
getUsdToRub: () => number; // USD를 RUB로 변환하는 비율 (1 USD = X RUB)
convertKrwTo: (krwAmount: number, currency: string) => number;
}
export const useExchangeRateStore = create<ExchangeRateState>((set, get) => ({
rates: DEFAULT_RATES,
isLoading: false,
lastUpdated: null,
error: null,
fetchRates: async () => {
// 이미 로딩 중이면 스킵
if (get().isLoading) return;
// 30분 이내에 업데이트했으면 스킵
const lastUpdated = get().lastUpdated;
if (lastUpdated && Date.now() - lastUpdated.getTime() < 30 * 60 * 1000) {
return;
}
set({ isLoading: true, error: null });
try {
const rates = await exchangeRateApi.getSimpleRates();
set({
rates: { ...DEFAULT_RATES, ...rates },
isLoading: false,
lastUpdated: new Date(),
});
} catch (error) {
console.error('Failed to fetch exchange rates:', error);
set({
isLoading: false,
error: 'Failed to fetch exchange rates',
});
// 실패해도 기본값 사용
}
},
getKrwToUsd: () => {
const { rates } = get();
const usdRate = rates.USD?.rate || DEFAULT_RATES.USD.rate;
return 1 / usdRate; // 1 KRW = 1/1450 USD
},
getUsdToMnt: () => {
const { rates } = get();
const usdRate = rates.USD?.rate || DEFAULT_RATES.USD.rate;
const mntRate = rates.MNT?.rate || DEFAULT_RATES.MNT.rate;
// MNT rate is already in KRW per MNT
// So 1 USD = (USD_KRW / MNT_KRW) MNT
return usdRate / mntRate;
},
getUsdToRub: () => {
const { rates } = get();
const usdRate = rates.USD?.rate || DEFAULT_RATES.USD.rate;
const rubRate = rates.RUB?.rate || DEFAULT_RATES.RUB.rate;
return usdRate / rubRate;
},
convertKrwTo: (krwAmount: number, currency: string) => {
const { rates } = get();
const rate = rates[currency]?.rate || DEFAULT_RATES[currency]?.rate;
if (!rate) return 0;
return krwAmount / rate;
},
}));
// 환율 초기화 함수 (앱 시작 시 호출)
export async function initExchangeRates() {
const store = useExchangeRateStore.getState();
await store.fetchRates();
}
// 환율 변환 헬퍼 함수들
export function formatWithExchangeRate(
krwAmount: number,
currency: 'USD' | 'MNT' | 'RUB' | 'CNY' | 'EUR'
): string {
const store = useExchangeRateStore.getState();
const converted = store.convertKrwTo(krwAmount, currency);
const symbol = store.rates[currency]?.symbol || DEFAULT_RATES[currency]?.symbol || '';
return `${symbol}${converted.toLocaleString('en-US', {
minimumFractionDigits: 0,
maximumFractionDigits: currency === 'USD' ? 0 : 0,
})}`;
}