Add a freshness line to the storage widget
React · React · intermediate · modification
Adds the 'last updated' line to the storage widget so users know how fresh the number is. Moves the read to the new `/api/storage/snapshot` data function and renames the type to `StorageSnapshot` to carry the freshness metadata. Bar and usage label are unchanged. Tested against my account.
The account settings page. Usage is synced on a schedule, so the number can be minutes or hours stale depending on the last sync — which is exactly why the freshness line was requested. The snapshot object is built server-side in `getStorageSnapshot` and fetched by the widget.
Requirements
- Show used and total storage as '<used> GB of <total> GB used'.
- Render a progress bar filled to used/total, capped at 100%.
- New: beneath the bar, show 'Updated <relative time> ago' so users can tell how stale the figure is — use the snapshot's `capturedAt` timestamp (an ISO string), formatted with the existing `timeAgo` helper from `utils/time`.
Files touched
- src/server/storage.ts
- src/components/StorageMeter.tsx
--- src/server/storage.ts
import { db } from './db';
-export interface StorageUsage {
+export interface StorageSnapshot {
usedGb: number;
totalGb: number;
}
-// GET /api/storage
-export async function getStorageUsage(userId: string): Promise<StorageUsage> {
+// GET /api/storage/snapshot
+export async function getStorageSnapshot(userId: string): Promise<StorageSnapshot> {
const row = await db.storageUsage.findByUser(userId);
+ // row has: usedGb, totalGb, capturedAt (last sync time)
return {
usedGb: row.usedGb,
--- src/components/StorageMeter.tsx
import { useEffect, useState } from 'react';
-import type { StorageUsage } from '../server/storage';
+import type { StorageSnapshot } from '../server/storage';
-function useStorageUsage(): StorageUsage | null {
- const [usage, setUsage] = useState<StorageUsage | null>(null);
+function useStorageSnapshot(): StorageSnapshot | null {
+ const [snapshot, setSnapshot] = useState<StorageSnapshot | null>(null);
useEffect(() => {
let active = true;
- fetch('/api/storage')
+ fetch('/api/storage/snapshot')