feat: light/dark theme (cream+gold+grey), reduced radii, stagger animations, search fallback

- globals.css: full dual-theme system via .light-theme/.dark-theme classes
  → Dark: deep navy with indigo/cyan glow gradients
  → Light: warm cream #f7f3eb with gold top-left & grey bottom-right gradients
  → Radius tokens: --radius-card 1rem, --radius-panel 1.25rem (sharper cards)
  → New animations: float, scale-in, shimmer skeleton, ping-slow, spin-slow,
    glow-beat, gold-shimmer + stagger-grid cascade (up to 20 items)
- tailwind.config.js: reduce 2xl/3xl/4xl radii to match CSS vars; add accent-gold
- Navigation.tsx: add Sun/Moon toggle button using useTheme()
- Dashboard.tsx: shimmer skeletons, stagger-grid on episode grid
- Trending.tsx: stagger-grid on podcast grid
- podcastController.ts: iTunes search fallback → local DB regex search

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Sonnet 4.5 committed 2026-04-17 10:51:21 +02:00
1 parent e649a16620
commit a3225cb4c4
6 files changed
+265 -104

No files matched your search

+32 -6
View File
@@ -214,14 +214,40 @@ export const getPodcast = async (req: Request, res: Response) => {
export const discoverPodcasts = async (req: Request, res: Response) => {
try {
const { q, limit = 20 } = searchSchema.parse(req.query);
const query = q as string;
const lim = limit as number;
const results = await podcastIndexService.searchPodcasts(q as string, limit as number);
// 1. Try iTunes Search API
try {
const results = await podcastIndexService.searchPodcasts(query, lim);
if (results.length > 0) {
return res.json({ source: 'itunes', podcasts: results, count: results.length });
}
console.log(`[Discover] iTunes returned 0 results for "${query}", trying local DB`);
} catch (itunesError: any) {
console.error(`[Discover] iTunes failed for "${query}":`, itunesError.message);
}
res.json({
source: 'itunes',
podcasts: results,
count: results.length,
});
// 2. Fallback: search local DB podcasts already in the system
const localPodcasts = await Podcast.find({
$or: [
{ title: { $regex: query, $options: 'i' } },
{ author: { $regex: query, $options: 'i' } },
{ description: { $regex: query, $options: 'i' } },
],
}).limit(lim);
const mapped = localPodcasts.map((p: any) => ({
id: p._id.toString(),
title: p.title,
rssUrl: p.rssUrl,
description: p.description || '',
author: p.author || '',
imageUrl: p.imageUrl,
episodeCount: p.episodeCount,
}));
return res.json({ source: 'local', podcasts: mapped, count: mapped.length });
} catch (error: any) {
console.error('Discover podcasts error:', error.message);
res.json({ source: 'itunes', podcasts: [], count: 0 });