mirror of
https://github.com/R0m1k3/podcastic.git
synced 2026-10-11 17:26:20 +02:00
feat: add Trending page to display and subscribe to popular podcasts by genre
This commit is contained in:
1 parent
f68989c228
commit
5305f3e5f6
5 files changed
+26
-14
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { X, AlertCircle, Info, CheckCircle2, AlertTriangle } from 'lucide-react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
export type AlertType = 'error' | 'info' | 'success' | 'warning';
|
||||
|
||||
@@ -52,8 +53,8 @@ export default function AlertModal({
|
||||
|
||||
const { icon: StatusIcon, color, bg, border, glow } = config[type];
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[150] flex items-center justify-center p-4">
|
||||
return createPortal(
|
||||
<div className="fixed inset-0 z-[210] flex items-center justify-center p-4">
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="absolute inset-0 bg-black/60 backdrop-blur-md animate-fade-in"
|
||||
@@ -91,6 +92,7 @@ export default function AlertModal({
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
@@ -159,7 +159,7 @@ export default function AudioPlayer({ episode, onClose, userId }: AudioPlayerPro
|
||||
isExpanded
|
||||
? 'inset-0 rounded-none'
|
||||
: 'bottom-6 left-1/2 -translate-x-1/2 w-[96%] max-w-5xl rounded-[2rem] h-[88px]'
|
||||
} premium-glass border-[var(--border-color)] shadow-2xl overflow-hidden flex flex-col`}>
|
||||
} ${theme === 'light' ? 'bg-gradient-to-r from-slate-800/95 to-slate-900/95 backdrop-blur-xl' : 'premium-glass'} border-[var(--border-color)] shadow-2xl overflow-hidden flex flex-col`}>
|
||||
|
||||
<audio
|
||||
ref={audioRef}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { X, Play, Clock, Calendar, BarChart2 } from 'lucide-react';
|
||||
import { Episode } from '../services/episodeService';
|
||||
|
||||
@@ -20,7 +21,7 @@ export default function EpisodeDetails({ episode, isOpen, onClose, onPlay }: Epi
|
||||
year: 'numeric'
|
||||
});
|
||||
|
||||
return (
|
||||
return createPortal(
|
||||
<>
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
@@ -131,6 +132,7 @@ export default function EpisodeDetails({ episode, isOpen, onClose, onPlay }: Epi
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CheckCircle2, ChevronRight, BookOpen, Sparkles, X } from 'lucide-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
interface SuccessModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -20,8 +21,8 @@ export default function SuccessModal({
|
||||
}: SuccessModalProps) {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[110] flex items-center justify-center p-4">
|
||||
return createPortal(
|
||||
<div className="fixed inset-0 z-[200] flex items-center justify-center p-4">
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="absolute inset-0 bg-black/60 backdrop-blur-md animate-fade-in"
|
||||
@@ -85,6 +86,7 @@ export default function SuccessModal({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
@@ -164,15 +164,18 @@ export default function Trending() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Genre Pills */}
|
||||
<div className="w-full min-w-0 overflow-hidden">
|
||||
<div className="flex items-center gap-2 overflow-x-auto pb-4 no-scrollbar -mx-4 px-4 sm:mx-0 sm:px-0 scroll-smooth">
|
||||
<div className="flex items-center gap-2 flex-nowrap">
|
||||
{/* Genre Pills with Scroll Indicators */}
|
||||
<div className="relative w-full min-w-0 group/genres mb-14">
|
||||
{/* Fade effect left */}
|
||||
<div className="absolute left-0 top-0 bottom-4 w-12 bg-gradient-to-r from-[var(--bg-primary)] to-transparent z-10 pointer-events-none opacity-100 sm:hidden" />
|
||||
|
||||
<div className="flex items-center gap-2 overflow-x-auto pb-4 no-scrollbar scroll-smooth">
|
||||
<div className="flex items-center gap-2 flex-nowrap px-4 sm:px-0">
|
||||
{GENRES.map(genre => (
|
||||
<button
|
||||
key={genre.id}
|
||||
onClick={() => setSelectedGenre(genre.id)}
|
||||
className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase tracking-widest whitespace-nowrap transition-all border ${
|
||||
className={`px-5 py-2.5 rounded-xl text-[11px] font-black uppercase tracking-widest whitespace-nowrap transition-all border ${
|
||||
selectedGenre === genre.id
|
||||
? 'bg-[var(--accent-primary)] text-white border-[var(--accent-primary)] shadow-glow-indigo'
|
||||
: 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)] hover:border-[var(--accent-primary)]'
|
||||
@@ -183,6 +186,9 @@ export default function Trending() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Fade effect right */}
|
||||
<div className="absolute right-0 top-0 bottom-4 w-12 bg-gradient-to-l from-[var(--bg-primary)] to-transparent z-10 pointer-events-none opacity-100 sm:hidden" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user