Update
This commit is contained in:
@ -27,10 +27,14 @@ interface EpisodeWithFeedInfo {
|
||||
feedId: string;
|
||||
feedTitle?: string;
|
||||
feedUrl: string;
|
||||
feedCategory?: string;
|
||||
}
|
||||
|
||||
function EpisodeList() {
|
||||
const [episodes, setEpisodes] = useState<EpisodeWithFeedInfo[]>([]);
|
||||
const [filteredEpisodes, setFilteredEpisodes] = useState<EpisodeWithFeedInfo[]>([]);
|
||||
const [categories, setCategories] = useState<string[]>([]);
|
||||
const [selectedCategory, setSelectedCategory] = useState<string>("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [currentAudio, setCurrentAudio] = useState<string | null>(null);
|
||||
@ -38,8 +42,13 @@ function EpisodeList() {
|
||||
|
||||
useEffect(() => {
|
||||
fetchEpisodes();
|
||||
fetchCategories();
|
||||
}, [useDatabase]);
|
||||
|
||||
useEffect(() => {
|
||||
filterEpisodesByCategory();
|
||||
}, [episodes, selectedCategory]);
|
||||
|
||||
const fetchEpisodes = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@ -106,6 +115,29 @@ function EpisodeList() {
|
||||
}
|
||||
};
|
||||
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/categories");
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setCategories(data.categories || []);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching categories:", err);
|
||||
}
|
||||
};
|
||||
|
||||
const filterEpisodesByCategory = () => {
|
||||
if (!selectedCategory) {
|
||||
setFilteredEpisodes(episodes);
|
||||
} else {
|
||||
const filtered = episodes.filter(episode =>
|
||||
episode.feedCategory === selectedCategory
|
||||
);
|
||||
setFilteredEpisodes(filtered);
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
return new Date(dateString).toLocaleString("ja-JP");
|
||||
};
|
||||
@ -165,6 +197,21 @@ function EpisodeList() {
|
||||
return <div className="error">{error}</div>;
|
||||
}
|
||||
|
||||
if (filteredEpisodes.length === 0 && episodes.length > 0 && selectedCategory) {
|
||||
return (
|
||||
<div className="empty-state">
|
||||
<p>カテゴリ「{selectedCategory}」のエピソードがありません</p>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setSelectedCategory("")}
|
||||
style={{ marginTop: "10px" }}
|
||||
>
|
||||
全てのエピソードを表示
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (episodes.length === 0) {
|
||||
return (
|
||||
<div className="empty-state">
|
||||
@ -193,8 +240,27 @@ function EpisodeList() {
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<h2>エピソード一覧 ({episodes.length}件)</h2>
|
||||
<h2>エピソード一覧 ({selectedCategory ? `${filteredEpisodes.length}/${episodes.length}` : episodes.length}件)</h2>
|
||||
<div style={{ display: "flex", gap: "10px", alignItems: "center" }}>
|
||||
{categories.length > 0 && (
|
||||
<select
|
||||
value={selectedCategory}
|
||||
onChange={(e) => setSelectedCategory(e.target.value)}
|
||||
style={{
|
||||
padding: "5px 10px",
|
||||
fontSize: "14px",
|
||||
border: "1px solid #ccc",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
>
|
||||
<option value="">全カテゴリ</option>
|
||||
{categories.map((category) => (
|
||||
<option key={category} value={category}>
|
||||
{category}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
<span style={{ fontSize: "12px", color: "#666" }}>
|
||||
データソース: {useDatabase ? "データベース" : "XML"}
|
||||
</span>
|
||||
@ -214,7 +280,7 @@ function EpisodeList() {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{episodes.map((episode) => (
|
||||
{filteredEpisodes.map((episode) => (
|
||||
<tr key={episode.id}>
|
||||
<td>
|
||||
<div style={{ marginBottom: "8px" }}>
|
||||
@ -242,6 +308,11 @@ function EpisodeList() {
|
||||
>
|
||||
{episode.feedTitle}
|
||||
</Link>
|
||||
{episode.feedCategory && (
|
||||
<span style={{ marginLeft: "8px", color: "#999", fontSize: "11px" }}>
|
||||
({episode.feedCategory})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{episode.articleTitle &&
|
||||
|
Reference in New Issue
Block a user