diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 14a2539..ed3630d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,11 +1,14 @@ import { Routes, Route, Link, useLocation } from 'react-router-dom' import EpisodeList from './components/EpisodeList' import FeedManager from './components/FeedManager' +import FeedList from './components/FeedList' +import FeedDetail from './components/FeedDetail' import EpisodeDetail from './components/EpisodeDetail' function App() { const location = useLocation() const isEpisodeDetail = location.pathname.startsWith('/episode/') + const isFeedDetail = location.pathname.startsWith('/feeds/') && location.pathname.split('/').length === 3 if (isEpisodeDetail) { return ( @@ -15,6 +18,14 @@ function App() { ) } + if (isFeedDetail) { + return ( + + } /> + + ) + } + return (
@@ -32,6 +43,12 @@ function App() { + フィード一覧 + + フィードリクエスト @@ -40,7 +57,8 @@ function App() {
} /> - } /> + } /> + } />
diff --git a/frontend/src/components/EpisodeDetail.tsx b/frontend/src/components/EpisodeDetail.tsx index f774a8c..bc884ac 100644 --- a/frontend/src/components/EpisodeDetail.tsx +++ b/frontend/src/components/EpisodeDetail.tsx @@ -1,41 +1,84 @@ import { useState, useEffect } from 'react' import { useParams, Link } from 'react-router-dom' -interface Episode { + +interface EpisodeWithFeedInfo { id: string title: string - description: string - pubDate: string - audioUrl: string - audioLength: string - guid: string - link: string + description?: string + audioPath: string + duration?: number + fileSize?: number + createdAt: string + articleId: string + articleTitle: string + articleLink: string + articlePubDate: string + feedId: string + feedTitle?: string + feedUrl: string } function EpisodeDetail() { const { episodeId } = useParams<{ episodeId: string }>() - const [episode, setEpisode] = useState(null) + const [episode, setEpisode] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) + const [useDatabase, setUseDatabase] = useState(true) useEffect(() => { fetchEpisode() - }, [episodeId]) + }, [episodeId, useDatabase]) const fetchEpisode = async () => { if (!episodeId) return try { setLoading(true) - const response = await fetch(`/api/episode/${episodeId}`) - if (!response.ok) { - const errorData = await response.json() - throw new Error(errorData.error || 'エピソードの取得に失敗しました') + + if (useDatabase) { + // Try to fetch from database with source info first + const response = await fetch(`/api/episode-with-source/${episodeId}`) + if (!response.ok) { + throw new Error('データベースからの取得に失敗しました') + } + const data = await response.json() + setEpisode(data.episode) + } else { + // Fallback to XML parsing (existing functionality) + const response = await fetch(`/api/episode/${episodeId}`) + if (!response.ok) { + const errorData = await response.json() + throw new Error(errorData.error || 'エピソードの取得に失敗しました') + } + const data = await response.json() + const xmlEpisode = data.episode + + // Convert XML episode to EpisodeWithFeedInfo format + const convertedEpisode: EpisodeWithFeedInfo = { + id: xmlEpisode.id, + title: xmlEpisode.title, + description: xmlEpisode.description, + audioPath: xmlEpisode.audioUrl, + createdAt: xmlEpisode.pubDate, + articleId: xmlEpisode.guid, + articleTitle: xmlEpisode.title, + articleLink: xmlEpisode.link, + articlePubDate: xmlEpisode.pubDate, + feedId: '', + feedTitle: 'RSS Feed', + feedUrl: '' + } + setEpisode(convertedEpisode) } - const data = await response.json() - setEpisode(data.episode) } catch (err) { console.error('Episode fetch error:', err) + if (useDatabase) { + // Fallback to XML if database fails + console.log('Falling back to XML parsing...') + setUseDatabase(false) + return + } setError(err instanceof Error ? err.message : 'エラーが発生しました') } finally { setLoading(false) @@ -62,13 +105,12 @@ function EpisodeDetail() { return new Date(dateString).toLocaleString('ja-JP') } - const formatFileSize = (bytes: string) => { - const size = parseInt(bytes) - if (isNaN(size)) return '' + const formatFileSize = (bytes?: number) => { + if (!bytes) return '' const units = ['B', 'KB', 'MB', 'GB'] let unitIndex = 0 - let fileSize = size + let fileSize = bytes while (fileSize >= 1024 && unitIndex < units.length - 1) { fileSize /= 1024 @@ -118,7 +160,7 @@ function EpisodeDetail() { {episode.title}
- 公開日: {formatDate(episode.pubDate)} + 作成日: {formatDate(episode.createdAt)}
@@ -127,7 +169,7 @@ function EpisodeDetail() {