Initial commit

This commit is contained in:
2025-06-04 08:14:55 +09:00
commit 4fe300d5d6
17 changed files with 486 additions and 0 deletions

14
frontend/src/App.tsx Normal file
View File

@ -0,0 +1,14 @@
import React from "react";
import FeedList from "./components/FeedList";
import EpisodeList from "./components/EpisodeList";
export default function App() {
return (
<div style={{ padding: "20px", fontFamily: "sans-serif" }}>
<h1> </h1>
<FeedList />
<hr style={{ margin: "20px 0" }} />
<EpisodeList />
</div>
);
}

View File

@ -0,0 +1,61 @@
import React, { useEffect, useState } from "react";
interface Episode {
id: string;
title: string;
pubDate: string;
audioPath: string;
sourceLink: string;
}
export default function EpisodeList() {
const [episodes, setEpisodes] = useState<Episode[]>([]);
useEffect(() => {
fetch("/api/episodes")
.then((res) => res.json())
.then((data) => setEpisodes(data));
}, []);
return (
<div>
<h2></h2>
<table style={{ width: "100%", borderCollapse: "collapse" }}>
<thead>
<tr>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>
</th>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>
</th>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>
</th>
</tr>
</thead>
<tbody>
{episodes.map((ep) => (
<tr key={ep.id}>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>
{ep.title}
</td>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>
{new Date(ep.pubDate).toLocaleString("ja-JP")}
</td>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>
<audio controls preload="none">
<source
src={`/podcast_audio/${ep.id}.mp3`}
type="audio/mpeg"
/>
使 audio
</audio>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}

View File

@ -0,0 +1,45 @@
import React, { useEffect, useState } from "react";
export default function FeedList() {
const [feeds, setFeeds] = useState<string[]>([]);
const [newUrl, setNewUrl] = useState("");
useEffect(() => {
fetch("/api/feeds")
.then((res) => res.json())
.then((data) => setFeeds(data));
}, []);
const addFeed = async () => {
if (!newUrl) return;
await fetch("/api/feeds", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ feedUrl: newUrl }),
});
setNewUrl("");
const updated = await fetch("/api/feeds").then((res) => res.json());
setFeeds(updated);
};
return (
<div>
<h2>RSSフィード管理</h2>
<ul>
{feeds.map((url) => (
<li key={url}>{url}</li>
))}
</ul>
<input
type="text"
placeholder="RSSフィードURLを入力"
value={newUrl}
onChange={(e) => setNewUrl(e.target.value)}
style={{ width: "300px" }}
/>
<button onClick={addFeed} style={{ marginLeft: "8px" }}>
</button>
</div>
);
}

6
frontend/src/index.tsx Normal file
View File

@ -0,0 +1,6 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(<App />);