From 4dfbc0c26f383989f6fecea2e40ebcd4bf28fe07 Mon Sep 17 00:00:00 2001 From: Francisco Pessano Date: Sat, 12 Jul 2025 01:21:50 -0300 Subject: [PATCH] Refactor VideoClassifierApp to use props for videos and update VirtualTable to utilize @tanstack/react-virtual --- web/package.json | 2 +- web/pnpm-lock.yaml | 16 +++- web/src/components/VideoClassifierApp.tsx | 92 ++++------------------- web/src/components/VirtualTable.tsx | 59 ++++++--------- web/src/pages/index.astro | 23 +++--- web/src/styles/global.css | 70 +++++++++++++++++ 6 files changed, 130 insertions(+), 132 deletions(-) diff --git a/web/package.json b/web/package.json index f777c12..00beaca 100644 --- a/web/package.json +++ b/web/package.json @@ -13,7 +13,7 @@ "@astrojs/react": "^4.3.0", "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/vite": "^4.1.3", - "@tanstack/virtual-core": "^3.13.12", + "@tanstack/react-virtual": "^3.13.12", "@types/canvas-confetti": "^1.9.0", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 7f39b76..b762edc 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -20,9 +20,9 @@ importers: '@tailwindcss/vite': specifier: ^4.1.3 version: 4.1.11(vite@6.3.5(@types/node@24.0.13)(jiti@2.4.2)(lightningcss@1.30.1)) - '@tanstack/virtual-core': + '@tanstack/react-virtual': specifier: ^3.13.12 - version: 3.13.12 + version: 3.13.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@types/canvas-confetti': specifier: ^1.9.0 version: 1.9.0 @@ -725,6 +725,12 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 + '@tanstack/react-virtual@3.13.12': + resolution: {integrity: sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@tanstack/virtual-core@3.13.12': resolution: {integrity: sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==} @@ -2711,6 +2717,12 @@ snapshots: tailwindcss: 4.1.11 vite: 6.3.5(@types/node@24.0.13)(jiti@2.4.2)(lightningcss@1.30.1) + '@tanstack/react-virtual@3.13.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@tanstack/virtual-core': 3.13.12 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + '@tanstack/virtual-core@3.13.12': {} '@types/babel__core@7.20.5': diff --git a/web/src/components/VideoClassifierApp.tsx b/web/src/components/VideoClassifierApp.tsx index 2801fa5..8547773 100644 --- a/web/src/components/VideoClassifierApp.tsx +++ b/web/src/components/VideoClassifierApp.tsx @@ -12,10 +12,7 @@ interface ApiResponse { message?: string; } -export default function VideoClassifierApp() { - const [data, setData] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); +export default function VideoClassifierApp({ videos }: { videos: VideoData[] }) { const [searchTerm, setSearchTerm] = useState(''); const [filters, setFilters] = useState({ classification: 'all', @@ -23,35 +20,9 @@ export default function VideoClassifierApp() { playlist_name: 'all' }); - // Fetch data - useEffect(() => { - const fetchData = async () => { - try { - setLoading(true); - const response = await fetch('/api/videos'); - const result: ApiResponse = await response.json(); - - if (!response.ok || result.error) { - setError(result.message || result.error || 'Failed to load data'); - setData([]); - } else { - setData(result.videos || []); - setError(null); - } - } catch (err) { - setError('Failed to fetch video data'); - setData([]); - } finally { - setLoading(false); - } - }; - - fetchData(); - }, []); - // Filter and search data const filteredData = useMemo(() => { - let result = data; + let result = videos; // Apply filters result = filterVideos(result, filters); @@ -60,50 +31,16 @@ export default function VideoClassifierApp() { result = searchVideos(result, searchTerm); return result; - }, [data, searchTerm, filters]); + }, [videos, searchTerm, filters]); - const refreshData = async () => { - setLoading(true); - setError(null); - - try { - const response = await fetch('/api/videos'); - const result: ApiResponse = await response.json(); - - if (!response.ok || result.error) { - setError(result.message || result.error || 'Failed to load data'); - setData([]); - } else { - setData(result.videos || []); - setError(null); - } - } catch (err) { - setError('Failed to fetch video data'); - setData([]); - } finally { - setLoading(false); - } - }; - - if (loading) { - return ( -
-
-
-

Loading video data...

-
-
- ); - } - - if (error) { + if (!videos) { return (
📁

CSV File Not Found

- {error} + It seems the video_classifications.csv file is missing or not properly configured.

To fix this:

@@ -113,9 +50,6 @@ export default function VideoClassifierApp() {
  • Refresh this page
  • -
    ); @@ -135,25 +69,25 @@ export default function VideoClassifierApp() { {/* Stats Overview */} - {data.length > 0 && ( - + {videos.length > 0 && ( + )} {/* Search and Filter */} - {data.length > 0 && ( + {videos.length > 0 && ( )} {/* Results */} - {data.length > 0 ? ( + {videos.length > 0 ? ( filteredData.length > 0 ? ( ) : ( @@ -178,12 +112,12 @@ export default function VideoClassifierApp() { {/* Footer */}

    - Powered by AI classification • {data.length} videos indexed + {videos.length} videos indexed