// src/App.js import React, { useState, useEffect } from 'react'; import axios from 'axios'; import './App.css'; const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://127.0.0.1:4000'; function App() { const [videos, setVideos] = useState([]); const [channels, setChannels] = useState([]); const [loading, setLoading] = useState(true); const [channelsLoading, setChannelsLoading] = useState(true); const [error, setError] = useState(null); const [selectedChannelId, setSelectedChannelId] = useState(''); const [expandedDescriptions, setExpandedDescriptions] = useState({}); const fetchChannels = async () => { try { setChannelsLoading(true); const response = await axios.get(`${API_BASE_URL}/subs-info`); if (response.data && Array.isArray(response.data)) { const formattedChannels = response.data.map(channel => { // Extract the channel ID from the _id field const channelId = channel._id.replace('yt:channel:', ''); return { id: channelId, _id: channel._id, last_video_update: channel.last_video_update, new_vids: channel.new_vids, time_between_fetches: channel.time_between_fetches, videos: channel.videos }; }); setChannels(formattedChannels); } } catch (err) { console.error('Error fetching channels:', err); setError('Failed to fetch available channels.'); } finally { setChannelsLoading(false); } }; const fetchVideos = async (channelId) => { try { setLoading(true); setError(null); setExpandedDescriptions({}); // Reset expanded states when fetching new videos const apiUrl = `${API_BASE_URL}/vid-from-link/yt:channel:${channelId}`; const response = await axios.get(apiUrl); if (response.data && Array.isArray(response.data)) { setVideos(response.data); } else { throw new Error('Invalid response format'); } } catch (err) { setError('Failed to fetch videos. Please check the channel and ensure the API is running.'); console.error('Error fetching videos:', err); } finally { setLoading(false); } }; useEffect(() => { fetchChannels(); }, []); useEffect(() => { if (selectedChannelId) { fetchVideos(selectedChannelId); } }, [selectedChannelId]); const handleChannelChange = (e) => { setSelectedChannelId(e.target.value); }; const handleRefreshChannels = () => { fetchChannels(); }; const toggleDescription = (videoId) => { setExpandedDescriptions(prev => ({ ...prev, [videoId]: !prev[videoId] })); }; const formatDate = (dateString) => { try { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } catch { return dateString; } }; const formatRelativeTime = (dateString) => { try { const date = new Date(dateString); const now = new Date(); const diffInHours = Math.floor((now - date) / (1000 * 60 * 60)); if (diffInHours < 1) { return 'Just now'; } else if (diffInHours < 24) { return `${diffInHours}h ago`; } else { const diffInDays = Math.floor(diffInHours / 24); return `${diffInDays}d ago`; } } catch { return dateString; } }; return (

YouTube Channel Videos

{selectedChannelId && channels.length > 0 && (

Selected: {selectedChannelId} {channels.find(ch => ch.id === selectedChannelId)?.last_video_update && ( • Last updated: {formatRelativeTime(channels.find(ch => ch.id === selectedChannelId).last_video_update)} )}

)}
{channelsLoading &&
Loading channels...
} {error && (
{error}
)} {!channelsLoading && channels.length === 0 && !error && (

No channels available

No YouTube channels found in the subscription list.

)} {loading && selectedChannelId && (
Loading videos for {selectedChannelId}...
)} {!loading && !error && selectedChannelId && (

Latest Videos from {selectedChannelId} {videos.length > 0 && ` (${videos.length})`}

{videos.sort((a, b) => new Date(b.published) - new Date(a.published)).map((video) => (
{video.title} { e.target.src = 'https://via.placeholder.com/300x180/333/fff?text=No+Thumbnail'; }} />

{video.title}

By: {video.author}

Published: {formatDate(video.published)}

{video.updated && (

Updated: {formatDate(video.updated)}

)} {video.summary && (

{video.summary}

{video.summary.length > 100 && ( )}
)}
))}
)} {!loading && !error && selectedChannelId && videos.length === 0 && (

No videos found for this channel

The channel might not have any videos or there was an issue loading them.

)} {!channelsLoading && !selectedChannelId && channels.length > 0 && (

Please select a channel to view videos

Choose a channel from the dropdown above to see its latest videos.

)}
); } export default App;