diff --git a/frontend/src/components/ResourcesView.tsx b/frontend/src/components/ResourcesView.tsx index 6700720f..5ece7c21 100644 --- a/frontend/src/components/ResourcesView.tsx +++ b/frontend/src/components/ResourcesView.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useMemo } from 'react'; +import { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger, TabsHighlight, TabsHighlightItem } from "@/components/ui/tabs"; @@ -37,22 +37,9 @@ import { FootprintTreemap } from './resources/FootprintTreemap'; import { ImageDetailsSheet } from './resources/ImageDetailsSheet'; import { VolumeBrowserSheet } from './resources/VolumeBrowserSheet'; import { NetworkDetailSheet, type NetworkInspectData } from './resources/NetworkDetailSheet'; -import { TabLanding, type TabLandingEntry } from './resources/TabLanding'; const NetworkTopologyView = lazy(() => import('./NetworkTopologyView')); -const RECENT_WINDOW_MS = 24 * 60 * 60 * 1000; - -function ageLabel(ms: number): string { - const minutes = Math.max(0, Math.round((Date.now() - ms) / 60000)); - if (minutes < 1) return 'just now'; - if (minutes < 60) return `${minutes}m ago`; - const hours = Math.round(minutes / 60); - if (hours < 24) return `${hours}h ago`; - const days = Math.round(hours / 24); - return `${days}d ago`; -} - // ── Interfaces ───────────────────────────────────────────────────────────────── interface UsageData { @@ -627,28 +614,6 @@ export default function ResourcesView() { setConfirmPrune({ target: 'images', scope: 'all' }); }; - const volumeLandings = useMemo(() => { - const largest: TabLandingEntry[] = [...volumes] - .sort((a, b) => b.Size - a.Size) - .slice(0, 5) - .map(vol => ({ - key: vol.Name, - primary: vol.Name, - secondary: vol.Size > 0 ? formatBytes(vol.Size) : '-', - })); - const now = Date.now(); - const recent: TabLandingEntry[] = volumes - .filter(v => !!v.CreatedAt && now - new Date(v.CreatedAt).getTime() <= RECENT_WINDOW_MS) - .sort((a, b) => new Date(b.CreatedAt ?? 0).getTime() - new Date(a.CreatedAt ?? 0).getTime()) - .slice(0, 5) - .map(vol => ({ - key: vol.Name, - primary: vol.Name, - secondary: vol.CreatedAt ? ageLabel(new Date(vol.CreatedAt).getTime()) : '-', - })); - return { largest, recent }; - }, [volumes]); - return (
@@ -896,16 +861,6 @@ export default function ResourcesView() { {/* Volumes */} - {!isLoading && volumes.length > 0 && ( - - )} void; - accent?: 'brand' | 'warning'; -} - -function LandingCard({ label, subtitle, entries, emptyLabel, onEntryClick, accent = 'brand' }: LandingCardProps) { - const accentClass = accent === 'warning' ? 'text-warning' : 'text-brand'; - return ( -
-
- - {label} - - {subtitle ? ( - {subtitle} - ) : null} -
- {entries.length === 0 ? ( -
- {emptyLabel} -
- ) : ( -
    - {entries.map(entry => ( -
  • - -
  • - ))} -
- )} -
- ); -} - -interface TabLandingProps { - largestLabel?: string; - largestSubtitle?: string; - largestEntries: TabLandingEntry[]; - largestEmpty: string; - recentLabel?: string; - recentSubtitle?: string; - recentEntries: TabLandingEntry[]; - recentEmpty: string; - onLargestClick?: (entry: TabLandingEntry) => void; - onRecentClick?: (entry: TabLandingEntry) => void; -} - -export function TabLanding({ - largestLabel = 'Largest 5', - largestSubtitle, - largestEntries, - largestEmpty, - recentLabel = 'Recently changed', - recentSubtitle, - recentEntries, - recentEmpty, - onLargestClick, - onRecentClick, -}: TabLandingProps) { - const largestTop = useMemo(() => largestEntries.slice(0, 5), [largestEntries]); - const recentTop = useMemo(() => recentEntries.slice(0, 5), [recentEntries]); - - return ( -
- - -
- ); -}