Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ const config: Config = {
},
{
label: "🎙️ Podcast",
to: "https://open.spotify.com/show/6oPJ7ZBlN7y34yiSMguIda",
to: "podcasts/",
},
],
},
Expand Down
105 changes: 105 additions & 0 deletions src/pages/podcasts/details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React from 'react';
import Layout from '@theme/Layout';
import type { ReactElement } from 'react';
import { useLocation } from '@docusaurus/router';
import './index.css';

interface PodcastData {
id: string;
spotifyUrl: string;
type: 'episode' | 'show' | 'playlist';
}

interface LocationState {
podcast: PodcastData;
}

interface SpotifyTitleProps {
spotifyUrl: string;
type: 'episode' | 'show' | 'playlist';
}

// Fetches the podcast/show/episode title from Spotify oEmbed API
const SpotifyTitle: React.FC<SpotifyTitleProps> = ({ spotifyUrl, type }) => {
const [title, setTitle] = React.useState<string>('');

React.useEffect(() => {
let cancelled = false;
fetch(`https://open.spotify.com/oembed?url=${encodeURIComponent(spotifyUrl)}`)
.then(res => res.json())
.then(data => {
if (!cancelled) setTitle(data.title);
})
.catch(() => {
if (!cancelled) setTitle('');
});
return () => { cancelled = true; };
}, [spotifyUrl]);
return (
<div className="spotify-title">
<strong>{title || (type.charAt(0).toUpperCase() + type.slice(1))}</strong>
</div>
);
};

export default function PodcastDetails(): ReactElement {
const location = useLocation();
const state = location.state as LocationState;
const podcast = state?.podcast;

// Random descriptive text about podcasts
const descriptions = [
"Dive deep into fascinating conversations and thought-provoking content.",
"Experience the power of audio storytelling at its finest.",
"Join us on a journey of discovery through captivating discussions.",
"Explore new perspectives and expand your horizons.",
"Listen to expert insights and engaging narratives.",
"Uncover the stories behind the stories.",
"Get inspired by the voices that shape our world.",
"Tune in to the latest trends and timeless tales.",
"Discover the art of conversation and the beauty of sound.",
];

// Get a random description
const randomDescription = descriptions[Math.floor(Math.random() * descriptions.length)];

if (!podcast) {
return (
<Layout>
<div className="podcast-container">
<h1>Podcast Not Found</h1>
<p>Sorry, we couldn't find the podcast you're looking for.</p>
</div>
</Layout>
);
}

return (
<Layout>
<div className="podcast-container">
<div className="podcast-card details-card">
<div className="podcast-content">
<div className="podcast-info">
<SpotifyTitle spotifyUrl={podcast.spotifyUrl} type={podcast.type} />
</div>
<div className="podcast-description">
<p>{randomDescription}</p>
</div>
<div className="podcast-embed-large">
<iframe
src={`https://open.spotify.com/embed/${podcast.type}/${podcast.spotifyUrl.split('/').pop()?.split('?')[0]}`}
width="100%"
height="352"
frameBorder="0"
allowFullScreen
allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
loading="lazy"
title={`Spotify embed ${podcast.id}`}
/>
</div>
</div>
</div>
</div>
</Layout>
);
}
193 changes: 193 additions & 0 deletions src/pages/podcasts/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
.podcast-container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}

.podcast-subtitle {
color: #666;
font-size: 1.2rem;
margin-bottom: 2rem;
text-align: center;
}

h1 {
text-align: center;
margin-bottom: 1rem;
}

.podcast-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
margin-top: 2rem;
}

.podcast-card {
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.2s ease;
}

.podcast-card:hover {
transform: translateY(-4px);
}

.podcast-content {
height: 100%;
}

.podcast-info {
padding: 1rem;
background: rgba(0, 0, 0, 0.05);
border-radius: 8px 8px 0 0;
}

.podcast-info h3 {
margin: 0 0 0.5rem 0;
font-size: 1.2rem;
color: #333;
}

.podcast-description {
font-size: 0.9rem;
color: #666;
margin-bottom: 0.5rem;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}

.podcast-publisher {
font-size: 0.8rem;
color: #888;
margin: 0;
font-style: italic;
}

.podcast-embed {
height: 100%;
border-radius: 0 0 12px 12px;
overflow: hidden;
}

.podcast-embed iframe {
border: none;
width: 100%;
height: 100%;
min-height: 352px;
background: #282828;
border-radius: 12px;
}

.pagination {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-top: 2rem;
padding: 1rem;
}

.pagination-button {
padding: 0.5rem 1rem;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}

.pagination-button:hover {
background: #f0f0f0;
}

.pagination-button.active {
background: #0066cc;
color: white;
border-color: #0066cc;
}

@media (max-width: 968px) {
.podcast-grid {
grid-template-columns: repeat(2, 1fr);
}
}

@media (max-width: 768px) {
.podcast-grid {
grid-template-columns: 1fr;
}

.podcast-container {
padding: 1rem;
}
}

/* Podcast Details Page Styles */
.back-button {
margin-bottom: 1rem;
padding: 0.5rem 1rem;
border: none;
background-color: #f0f0f0;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
color: #333;
display: inline-flex;
align-items: center;
transition: background-color 0.2s;
}

.back-button:hover {
background-color: #e0e0e0;
}

.podcast-details {
max-width: 800px;
margin: 0 auto;
padding-top: 1rem;
}

.podcast-embed-large {
margin-bottom: 2rem;
}

.podcast-transcript {
background: #fff;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.podcast-transcript h2 {
margin-bottom: 1rem;
color: #333;
}

.podcast-card {
cursor: pointer;
}

.details-card {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border-radius: 8px;
background: var(--ifm-background-surface-color);
}

.podcast-description {
margin: 1rem 0;
font-size: 1.1rem;
color: var(--ifm-color-emphasis-700);
line-height: 1.6;
text-align: center;
}
Loading