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>
This commit is contained in:
114
frontend/src/lib/exchangeRateStore.ts
Normal file
114
frontend/src/lib/exchangeRateStore.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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,
|
||||
})}`;
|
||||
}
|
||||
Reference in New Issue
Block a user