add cost for the variants using USD to GBP conversion
This commit is contained in:
18
src/lib/currency.ts
Normal file
18
src/lib/currency.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export function getUsdGbpRate(): number {
|
||||
// Allow override via env var; must be NEXT_PUBLIC_* to be available on client
|
||||
const raw = process.env.NEXT_PUBLIC_USD_GBP_RATE;
|
||||
const parsed = raw ? Number(raw) : NaN;
|
||||
// Fallback default rate; update as needed
|
||||
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0.78;
|
||||
}
|
||||
|
||||
export function formatUsdToGbp(usd?: number): string | undefined {
|
||||
if (typeof usd !== 'number') return undefined;
|
||||
const gbp = usd * getUsdGbpRate();
|
||||
try {
|
||||
return new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP', maximumFractionDigits: 2 }).format(gbp);
|
||||
} catch {
|
||||
// Fallback simple formatting
|
||||
return `£${gbp.toFixed(2)}`;
|
||||
}
|
||||
}
|
||||
64
src/lib/useExchangeRate.ts
Normal file
64
src/lib/useExchangeRate.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
"use client";
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const CACHE_KEY = 'fx-usd-gbp-v1';
|
||||
const TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
||||
const DEFAULT_RATE = 0.78;
|
||||
|
||||
function readCache(): { rate: number; ts: number } | null {
|
||||
if (typeof window === 'undefined') return null;
|
||||
try {
|
||||
const raw = window.localStorage.getItem(CACHE_KEY);
|
||||
if (!raw) return null;
|
||||
const obj = JSON.parse(raw) as { rate: number; ts: number };
|
||||
if (typeof obj?.rate !== 'number' || typeof obj?.ts !== 'number') return null;
|
||||
if (Date.now() - obj.ts > TTL_MS) return null;
|
||||
return obj;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writeCache(rate: number) {
|
||||
if (typeof window === 'undefined') return;
|
||||
try {
|
||||
window.localStorage.setItem(CACHE_KEY, JSON.stringify({ rate, ts: Date.now() }));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUsdGbpRate(): Promise<number | null> {
|
||||
try {
|
||||
const res = await fetch('https://api.frankfurter.app/latest?from=USD&to=GBP');
|
||||
if (!res.ok) return null;
|
||||
const json = await res.json();
|
||||
const rate = json?.rates?.GBP;
|
||||
return typeof rate === 'number' ? rate : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function useUsdGbpRate(): number {
|
||||
const [rate, setRate] = useState<number>(DEFAULT_RATE);
|
||||
|
||||
useEffect(() => {
|
||||
const cached = readCache();
|
||||
if (cached) {
|
||||
setRate(cached.rate);
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
const live = await fetchUsdGbpRate();
|
||||
if (!cancelled && typeof live === 'number') {
|
||||
setRate(live);
|
||||
writeCache(live);
|
||||
}
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, []);
|
||||
|
||||
return rate;
|
||||
}
|
||||
Reference in New Issue
Block a user