diff --git a/src/app/api/exchange-rates/route.js b/src/app/api/exchange-rates/route.js index 8576418..e9f480d 100644 --- a/src/app/api/exchange-rates/route.js +++ b/src/app/api/exchange-rates/route.js @@ -1,4 +1,4 @@ -import { format } from "date-fns"; +import { format, addDays, subDays } from "date-fns"; import axios from "axios"; import https from "https"; import crypto from "crypto"; @@ -105,7 +105,7 @@ function getDateRange(start, end) { const last = new Date(end); while (current <= last) { dates.push(new Date(current)); - current.setDate(current.getDate() + 1); + current = addDays(current, 1); } return dates; } @@ -114,7 +114,7 @@ function getDateRange(start, end) { async function getPreviousDayRate(date, bank, currency, rateCache, maxAttempts = 30) { let currentDate = new Date(date); for (let attempt = 0; attempt < maxAttempts; attempt++) { - currentDate.setDate(currentDate.getDate() - 1); + currentDate = subDays(currentDate, 1); const dateStr = format(currentDate, "yyyy-MM-dd"); if (rateCache.has(dateStr)) { diff --git a/src/app/components/exchange-rate-chart.js b/src/app/components/exchange-rate-chart.js index 4f51c3a..d5d1812 100644 --- a/src/app/components/exchange-rate-chart.js +++ b/src/app/components/exchange-rate-chart.js @@ -1,8 +1,11 @@ "use client"; -import React from "react"; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from "recharts"; +const CHART_COLORS = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16"]; +const MAX_DOTS_DAYS = 31; +const MAX_LEGEND_LINES = 8; + // Parse rate string to number (handles comma-separated values like "25,880") function parseRate(val) { if (!val) return null; @@ -54,8 +57,6 @@ export function RateTrendChart({ results, selectedBank, compareMode }) { } } - const colors = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16"]; - return (
{progress?.total ? `Fetching rates for ${progress.total} day${progress.total > 1 ? "s" : ""}...` : "Fetching exchange rates..."}
diff --git a/src/app/components/exchange-rate-storage.js b/src/app/components/exchange-rate-storage.js new file mode 100644 index 0000000..cdd6ac3 --- /dev/null +++ b/src/app/components/exchange-rate-storage.js @@ -0,0 +1,52 @@ +export function loadFromUrl() { + if (typeof window === "undefined") return null; + const params = new URLSearchParams(window.location.search); + const bank = params.get("bank"); + const currency = params.get("currency"); + const start = params.get("start"); + const end = params.get("end"); + if (!bank && !currency && !start && !end) return null; + return { + bank: bank || null, + currency: currency || null, + startDate: start ? new Date(start) : null, + endDate: end ? new Date(end) : null, + }; +} + +export function loadSavedSettings() { + if (typeof window === "undefined") return null; + try { + const saved = localStorage.getItem("exchangeRateSettings"); + if (!saved) return null; + const parsed = JSON.parse(saved); + return { + bank: parsed.bank || "bidv", + currency: parsed.currency || "USD", + startDate: parsed.startDate ? new Date(parsed.startDate) : null, + endDate: parsed.endDate ? new Date(parsed.endDate) : null, + }; + } catch { + return null; + } +} + +export function saveSettings(bank, currency, startDate, endDate) { + try { + localStorage.setItem("exchangeRateSettings", JSON.stringify({ + bank, + currency, + startDate: startDate?.toISOString(), + endDate: endDate?.toISOString(), + })); + } catch { /* ignore quota errors */ } +} + +export function applyTheme(value) { + const root = document.documentElement; + if (value === "system") { + root.removeAttribute("data-theme"); + } else { + root.setAttribute("data-theme", value); + } +} diff --git a/src/app/components/exchange-rate-table.js b/src/app/components/exchange-rate-table.js index 88a1dc5..dabf934 100644 --- a/src/app/components/exchange-rate-table.js +++ b/src/app/components/exchange-rate-table.js @@ -1,7 +1,5 @@ "use client"; -import React from "react"; - export function ComparisonTable({ results }) { const headers = [ { label: "Date", numeric: false }, @@ -41,7 +39,7 @@ export function ComparisonTable({ results }) { ]; return (- Fetch exchange rates from Vietnamese banks and export to CSV. + Fetch exchange rates from Vietnamese banks and export to Excel or CSV.