diff --git a/backend/src/middleware/cache.ts b/backend/src/middleware/cache.ts index e51a35c..6694c8b 100644 --- a/backend/src/middleware/cache.ts +++ b/backend/src/middleware/cache.ts @@ -7,12 +7,14 @@ export function cacheFor(ttlMs: number) { const key = req.originalUrl; const cached = store.get(key); if (cached && Date.now() < cached.expiresAt) { + res.setHeader('Cache-Control', `public, max-age=${Math.floor(ttlMs / 1000)}`); return res.json(cached.data); } const original = res.json.bind(res); res.json = (data: unknown) => { if (store.size > 500) store.clear(); // bound memory store.set(key, { data, expiresAt: Date.now() + ttlMs }); + res.setHeader('Cache-Control', `public, max-age=${Math.floor(ttlMs / 1000)}`); return original(data); }; next(); diff --git a/backend/src/routes/meters.ts b/backend/src/routes/meters.ts index 61932b1..c4ca3e3 100644 --- a/backend/src/routes/meters.ts +++ b/backend/src/routes/meters.ts @@ -57,6 +57,7 @@ export function createMeterRouter(stellar: StellarService) { /** GET /api/meters/export?format=csv|json — download all meter data */ meterRouter.get( "/export", + requireAdminKey, asyncHandler(async (req, res) => { const format = req.query.format === "json" ? "json" : "csv"; const result = await stellar.query("get_all_meters", []); diff --git a/backend/src/routes/payments.ts b/backend/src/routes/payments.ts index 40d9667..3744414 100644 --- a/backend/src/routes/payments.ts +++ b/backend/src/routes/payments.ts @@ -110,8 +110,12 @@ async function fetchPaymentEvents( const EVT_NS = StellarSdk.xdr.ScVal.scvSymbol("solargrid").toXDR("base64"); const ACTION = StellarSdk.xdr.ScVal.scvSymbol("payment").toXDR("base64"); + const latestLedgerResp = await (server as any).getLatestLedger(); + const latestLedger = latestLedgerResp.sequence; + const startLedger = Math.max(1, latestLedger - Math.floor((days * 24 * 60 * 60) / 6)); + const response = await (server as any).getEvents({ - startLedger: 1, + startLedger, filters: [ { type: "contract", diff --git a/frontend/src/app/dashboard/provider/page.tsx b/frontend/src/app/dashboard/provider/page.tsx index a604cbc..e023f70 100644 --- a/frontend/src/app/dashboard/provider/page.tsx +++ b/frontend/src/app/dashboard/provider/page.tsx @@ -3,7 +3,7 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { useSearchParams, useRouter } from "next/navigation"; import Navbar from "@/components/Navbar"; -import { Skeleton } from "@/components/Skeleton"; +import { SkeletonCard } from "@/components/SkeletonCard"; import { useToast } from "@/components/ToastProvider"; import { getAllMeters, type MeterData } from "@/services/meterService"; import { parseWalletError } from "@/lib/errors"; @@ -32,6 +32,7 @@ export default function ProviderDashboardPage() { const [meters, setMeters] = useState([]); const [fetching, setFetching] = useState(false); + const [fetchError, setFetchError] = useState(null); const searchInputRef = useRef(null); useEffect(() => { @@ -66,11 +67,13 @@ export default function ProviderDashboardPage() { const fetchMeters = useCallback(async () => { setFetching(true); + setFetchError(null); try { const allMeters = await getAllMeters(); setMeters(allMeters); } catch (err: unknown) { console.error("Failed to fetch meters:", err); + setFetchError(err instanceof Error ? err.message : "Failed to fetch meters"); } finally { setFetching(false); } @@ -314,30 +317,36 @@ export default function ProviderDashboardPage() { - {fetching && meters.length === 0 ? ( + {fetchError ? ( + + + {fetchError} + + + ) : fetching && meters.length === 0 ? ( <> - {[1, 2, 3].map((i) => ( + {[1, 2, 3, 4, 5].map((i) => ( - + - + - + - + - + - + - + ))}