From fa9f9bfab1176e5d1886f05d7ed004cf54df8406 Mon Sep 17 00:00:00 2001 From: appdevelopsk Date: Sun, 25 Oct 2026 21:58:23 +0900 Subject: [PATCH 01/21] fix(currency): warn users when bundled conversion rates are older than seven days --- site/src/tools/currency-converter/Component.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/site/src/tools/currency-converter/Component.tsx b/site/src/tools/currency-converter/Component.tsx index 9b05eb0..637f489 100644 --- a/site/src/tools/currency-converter/Component.tsx +++ b/site/src/tools/currency-converter/Component.tsx @@ -1,6 +1,6 @@ "use client"; -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useLocale, useTranslations } from "next-intl"; import ratesData from "@/data/rates.json"; @@ -60,6 +60,14 @@ export default function CurrencyConverter() { const [amount, setAmount] = useState("100"); const [from, setFrom] = useState("USD"); const [to, setTo] = useState("JPY"); + // The bundled fallback file may be old if a rate API fetch failed during + // prebuild. Compute age only after hydration to avoid static-HTML mismatch. + const [rateIsStale, setRateIsStale] = useState(false); + useEffect(() => { + const updated = Date.parse(`${RATES_UPDATED_AT}T00:00:00Z`); + const ageMs = Date.now() - updated; + setRateIsStale(!Number.isFinite(updated) || ageMs >= 7 * 86400000 || ageMs < -86400000); + }, []); function handleSwap() { setFrom(to); @@ -104,6 +112,11 @@ export default function CurrencyConverter() { return (
+ {rateIsStale && ( +

+ {t("note.staleWarning", { date: RATES_UPDATED_AT })} +

+ )}
{QUICK_PAIRS.map((p) => (