502 lines
26 KiB
TypeScript
502 lines
26 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { useLang } from '@/context/LangContext'
|
|
import { Bookmark, Podcast, Clock, Calendar, Play, ChevronRight } from 'lucide-react'
|
|
import { bootstrapMedia, videos as VIDEOS, podcasts as PODCASTS } from '@/data/media'
|
|
import MediaWavePlayer from '@/components/MediaWavePlayer'
|
|
import { authFetch, useAuth } from '@/context/AuthContext'
|
|
|
|
const NAVY = '#032340'
|
|
const GOLD = '#CD9E53'
|
|
|
|
|
|
|
|
const T = {
|
|
fa: {
|
|
videoLabel: 'ویدیوکست', videoSub: 'آخرین گفتگوهای تصویری اندیشکده',
|
|
podLabel: 'پادکستها', podSub: 'شنیدنیهای اندیشکده فولاد آینده',
|
|
watchAll: 'مشاهده همه', listenAll: 'مشاهده همه',
|
|
},
|
|
en: {
|
|
videoLabel: 'Videocast', videoSub: 'Latest video conversations from the Institute',
|
|
podLabel: 'Podcasts', podSub: 'Audio episodes from Future Steel Institute',
|
|
watchAll: 'View All', listenAll: 'View All',
|
|
},
|
|
}
|
|
|
|
export default function VideocastPodcastSection({ only }: { only?: 'video' | 'pod' }) {
|
|
const { lang } = useLang()
|
|
const { member } = useAuth()
|
|
const navigate = useNavigate()
|
|
const t = T[lang]
|
|
const [activeVideo, setActiveVideo] = useState(0)
|
|
const [activePod, setActivePod] = useState(() => {
|
|
const playableIndex = PODCASTS.findIndex(item => Boolean(item.mediaUrl?.trim()))
|
|
return playableIndex >= 0 ? playableIndex : 0
|
|
})
|
|
const [podcasts, setPodcasts] = useState(() => [...PODCASTS])
|
|
const [bookmarkedIds, setBookmarkedIds] = useState<Set<string>>(new Set())
|
|
const [bookmarkBusy, setBookmarkBusy] = useState(false)
|
|
const pod = podcasts[activePod] ?? podcasts[0]
|
|
|
|
useEffect(() => {
|
|
let active = true
|
|
bootstrapMedia().then(() => {
|
|
if (!active) return
|
|
setPodcasts([...PODCASTS])
|
|
const playableIndex = PODCASTS.findIndex(item => Boolean(item.mediaUrl?.trim()))
|
|
setActivePod(playableIndex >= 0 ? playableIndex : 0)
|
|
})
|
|
return () => { active = false }
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (!member) { setBookmarkedIds(new Set()); return }
|
|
let active = true
|
|
authFetch('/api/members/me/bookmarks')
|
|
.then(async response => response.ok ? response.json() : [])
|
|
.then(items => {
|
|
if (!active || !Array.isArray(items)) return
|
|
setBookmarkedIds(new Set(items.filter(item => item.contentType === 'podcast').map(item => String(item.contentId))))
|
|
})
|
|
.catch(() => {})
|
|
return () => { active = false }
|
|
}, [member])
|
|
|
|
const togglePodcastBookmark = async () => {
|
|
if (!member) { navigate('/login'); return }
|
|
if (!pod || bookmarkBusy) return
|
|
const contentId = String(pod.id)
|
|
const saved = bookmarkedIds.has(contentId)
|
|
setBookmarkBusy(true)
|
|
try {
|
|
const response = saved
|
|
? await authFetch(`/api/members/me/bookmarks/podcast/${encodeURIComponent(contentId)}`, { method: 'DELETE' })
|
|
: await authFetch('/api/members/me/bookmarks', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
contentId,
|
|
contentType: 'podcast',
|
|
title: pod[lang].title,
|
|
summary: pod[lang].body,
|
|
coverImage: pod.cover,
|
|
path: '/podcast',
|
|
}),
|
|
})
|
|
if (!response.ok) throw new Error('bookmark_failed')
|
|
setBookmarkedIds(current => {
|
|
const next = new Set(current)
|
|
if (saved) next.delete(contentId)
|
|
else next.add(contentId)
|
|
return next
|
|
})
|
|
} catch { /* keep the previous state when the request fails */ }
|
|
finally { setBookmarkBusy(false) }
|
|
}
|
|
|
|
const showVideo = only !== 'pod'
|
|
const showPod = only !== 'video'
|
|
// when split into one column, give it full width instead of 60/40
|
|
const gridCols = only ? '1fr' : '60% 40%'
|
|
|
|
return (
|
|
<section style={{ direction: lang === 'fa' ? 'rtl' : 'ltr', background: 'var(--paper)' }}>
|
|
<div className="max-w-7xl mx-auto px-12 max-md:px-5">
|
|
<div style={{ display: 'grid', gridTemplateColumns: gridCols }} className="max-lg:!grid-cols-1">
|
|
|
|
{/* ── VIDEOCAST (full-width featured player + playlist + description) ── */}
|
|
{showVideo && (
|
|
<div style={{ padding: '40px 40px 44px', display: 'flex', flexDirection: 'column', gridColumn: '1 / -1', background: 'linear-gradient(180deg, #f6f8fa 0%, #edf0f4 100%)', borderRadius: 24, margin: '36px 0', border: '1px solid rgba(3,35,64,0.06)', boxShadow: '0 24px 64px -40px rgba(3,35,64,0.35)' }} className="max-md:!p-5">
|
|
|
|
{/* heading */}
|
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, marginBottom: 24 }}>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
|
<div style={{ width: 4, height: 28, background: GOLD, borderRadius: 2 }} />
|
|
<h2 style={{ fontSize: 'clamp(20px,2.2vw,28px)', fontWeight: 900, letterSpacing: '-0.5px', color: NAVY, margin: 0 }}>{t.videoLabel}</h2>
|
|
</div>
|
|
<button style={{
|
|
display: 'inline-flex', alignItems: 'center', gap: 8, direction: 'ltr',
|
|
fontSize: 13, fontWeight: 700, color: GOLD,
|
|
background: 'none', border: 'none', cursor: 'pointer', fontFamily: 'inherit',
|
|
}}>
|
|
<div style={{ width: 24, height: 24, borderRadius: '50%', border: `1px solid ${GOLD}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
<ChevronRight size={14} strokeWidth={2.5} />
|
|
</div>
|
|
<span style={{ direction: 'rtl' }}>{t.watchAll}</span>
|
|
</button>
|
|
</div>
|
|
|
|
{/* featured player + playlist — all in one row */}
|
|
<div style={{ display: 'flex', gap: 16, alignItems: 'stretch', marginBottom: 32 }} className="max-lg:!flex-col">
|
|
<div style={{ flex: '1.2 1 0', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 14 }} className="max-lg:!w-full">
|
|
<div style={{ flex: '1 1 0', minWidth: 0, position: 'relative', overflow: 'hidden', background: '#000', borderRadius: 16, minHeight: 0, boxShadow: '0 30px 70px -34px rgba(3,35,64,0.5)' }} className="max-lg:!aspect-video max-lg:!flex-none">
|
|
<img src={VIDEOS[activeVideo].thumb} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block', opacity: 0.9, position: 'absolute', inset: 0 }} />
|
|
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(3,35,64,0.55) 0%, transparent 45%)' }} />
|
|
{/* center play */}
|
|
<button aria-label="play" style={{
|
|
position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)',
|
|
width: 64, height: 64, borderRadius: '50%', border: '2px solid rgba(255,255,255,0.6)',
|
|
background: 'rgba(255,255,255,0.14)', backdropFilter: 'blur(4px)', cursor: 'pointer',
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
}}>
|
|
<div style={{ width: 0, height: 0, borderTop: '11px solid transparent', borderBottom: '11px solid transparent', borderLeft: '19px solid #fff', marginLeft: 4 }} />
|
|
</button>
|
|
{/* controls bar */}
|
|
<div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '0 16px 14px', direction: 'ltr' }}>
|
|
<div style={{ height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.3)', marginBottom: 12 }}>
|
|
<div style={{ width: '22%', height: '100%', borderRadius: 2, background: GOLD, position: 'relative' }}>
|
|
<span style={{ position: 'absolute', right: -5, top: '50%', transform: 'translateY(-50%)', width: 11, height: 11, borderRadius: '50%', background: '#fff' }} />
|
|
</div>
|
|
</div>
|
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: '#fff' }}>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
|
<span style={{ fontSize: 18 }}>⏸</span>
|
|
<span style={{ fontSize: 15, opacity: 0.85 }}>⏭</span>
|
|
<span style={{ fontSize: 15, opacity: 0.85 }}>🔊</span>
|
|
<span style={{ fontSize: 11, opacity: 0.8, direction: 'ltr' }}>۰۹:۲۷ / {VIDEOS[activeVideo].duration}</span>
|
|
</div>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 14, opacity: 0.85 }}>
|
|
<span style={{ fontSize: 14 }}>⤴</span>
|
|
<span style={{ fontSize: 14 }}>⛶</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* title — directly below the video, inside the right column */}
|
|
<div style={{ direction: lang === 'fa' ? 'rtl' : 'ltr' }}>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
|
|
<span style={{ fontSize: 16 }}>🎙</span>
|
|
<h3 style={{ fontSize: 'clamp(15px,1.5vw,20px)', fontWeight: 900, color: NAVY, margin: 0, lineHeight: 1.4 }}>{VIDEOS[activeVideo][lang].title}</h3>
|
|
</div>
|
|
<p style={{ fontSize: 13, lineHeight: 1.9, color: 'rgba(3,35,64,0.7)', margin: 0, textAlign: 'justify', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{VIDEOS[activeVideo][lang].body}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* playlist column — beside the featured player */}
|
|
<div style={{ flex: '1 1 0', minWidth: 0 }} className="max-lg:!w-full">
|
|
{/* video playlist — 3 thumbnail cards */}
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, alignContent: 'start', direction: lang === 'fa' ? 'rtl' : 'ltr' }} className="max-md:!grid-cols-2">
|
|
{VIDEOS.slice(0, 3).map((v, i) => (
|
|
<button
|
|
key={v.id}
|
|
onClick={() => setActiveVideo(i)}
|
|
style={{
|
|
textAlign: 'inherit', background: i === activeVideo ? '#efe9e1' : '#fff',
|
|
border: `1px solid ${i === activeVideo ? GOLD : 'rgba(3,35,64,0.08)'}`,
|
|
borderRadius: 12, overflow: 'hidden', cursor: 'pointer',
|
|
display: 'flex', flexDirection: 'column', transition: 'box-shadow .2s',
|
|
gridColumn: i === 2 ? '1 / -1' : undefined,
|
|
}}
|
|
className="hover:!shadow-md"
|
|
>
|
|
<div style={{ position: 'relative', aspectRatio: '16/9', overflow: 'hidden' }}>
|
|
<img src={v.thumb} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
|
|
<div style={{ position: 'absolute', inset: 0, background: 'rgba(3,35,64,0.28)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
<div style={{ width: 36, height: 36, borderRadius: '50%', background: 'rgba(255,255,255,0.85)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
<div style={{ width: 0, height: 0, borderTop: '7px solid transparent', borderBottom: '7px solid transparent', borderLeft: `12px solid ${NAVY}`, marginLeft: 3 }} />
|
|
</div>
|
|
</div>
|
|
<span style={{ position: 'absolute', bottom: 8, left: 8, fontSize: 10, fontWeight: 800, color: '#fff', background: 'rgba(0,0,0,0.55)', padding: '2px 7px', borderRadius: 4, direction: 'ltr' }}>{v.duration}</span>
|
|
</div>
|
|
<div style={{ padding: '12px 14px', direction: lang === 'fa' ? 'rtl' : 'ltr', textAlign: 'right' }}>
|
|
<div style={{ fontSize: 11, color: GOLD, fontWeight: 800, marginBottom: 4 }}>{v.ep}</div>
|
|
<div style={{ fontSize: 13, fontWeight: 800, color: NAVY, lineHeight: 1.4 }}>{v[lang].title}</div>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
)}
|
|
|
|
{/* ── PODCAST (full width) ── */}
|
|
{showPod && (
|
|
<div style={{ padding: '56px 0 72px', background: 'var(--paper)', gridColumn: '1 / -1' }} className="max-md:!px-5">
|
|
<div className="max-w-7xl mx-auto px-12 max-md:!px-0">
|
|
|
|
{/* heading */}
|
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 24, gap: 12 }}>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
|
<div style={{ width: 4, height: 28, background: GOLD, borderRadius: 2 }} />
|
|
<h2 style={{ fontSize: 'clamp(20px,2.2vw,28px)', fontWeight: 900, letterSpacing: '-0.5px', color: NAVY, margin: 0 }}>{t.podLabel}</h2>
|
|
</div>
|
|
<button style={{
|
|
display: 'inline-flex', alignItems: 'center', gap: 8,
|
|
fontSize: 13, fontWeight: 700, color: GOLD,
|
|
background: 'none', border: 'none', cursor: 'pointer', fontFamily: 'inherit',
|
|
}}>
|
|
<span>{t.listenAll}</span>
|
|
<div style={{ width: 24, height: 24, borderRadius: '50%', border: `1px solid ${GOLD}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
<ChevronRight size={14} strokeWidth={2.5} />
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
{/* ── featured player card ── */}
|
|
<div style={{
|
|
display: 'flex',
|
|
flexDirection: lang === 'fa' ? 'row' : 'row-reverse',
|
|
alignItems: 'stretch',
|
|
background: '#efe9e1',
|
|
borderRadius: 18,
|
|
marginBottom: 32,
|
|
overflow: 'hidden',
|
|
minHeight: 200,
|
|
}} className="max-md:!flex-col">
|
|
|
|
{/* cover — full height, flush to right edge */}
|
|
<div style={{ flexShrink: 0, width: 200, position: 'relative' }} className="max-md:!w-full max-md:!h-48">
|
|
<img src={pod.cover} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
|
|
{/* rating badge overlaid at bottom of cover */}
|
|
<div style={{
|
|
position: 'absolute', bottom: 0, left: 0, right: 0,
|
|
background: 'rgba(3,35,64,0.75)', backdropFilter: 'blur(4px)',
|
|
padding: '6px 10px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
|
|
}}>
|
|
<span style={{ color: GOLD, fontSize: 12, letterSpacing: 1 }}>★★★★★</span>
|
|
<span style={{ fontSize: 11, fontWeight: 700, color: '#fff' }}>{pod.rating}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* player body — directly beside cover, no gap */}
|
|
<div style={{
|
|
flex: 1, minWidth: 0, padding: 24,
|
|
display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
|
|
direction: lang === 'fa' ? 'rtl' : 'ltr',
|
|
}}>
|
|
{/* bookmark */}
|
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-start', marginBottom: 12, direction: 'ltr' }}>
|
|
<div style={{ display: 'flex', gap: 10 }}>
|
|
<button
|
|
type="button"
|
|
onClick={togglePodcastBookmark}
|
|
disabled={bookmarkBusy}
|
|
aria-label={bookmarkedIds.has(String(pod.id)) ? 'حذف از علاقهمندیها' : 'افزودن به علاقهمندیها'}
|
|
title={bookmarkedIds.has(String(pod.id)) ? 'حذف از علاقهمندیها' : 'ذخیره در علاقهمندیها'}
|
|
style={{
|
|
width: 36, height: 36, borderRadius: '50%',
|
|
border: `1px solid ${bookmarkedIds.has(String(pod.id)) ? GOLD : 'rgba(3,35,64,0.18)'}`,
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
background: bookmarkedIds.has(String(pod.id)) ? `${GOLD}22` : 'transparent',
|
|
color: bookmarkedIds.has(String(pod.id)) ? GOLD : NAVY,
|
|
cursor: bookmarkBusy ? 'wait' : 'pointer', transition: 'all 0.2s',
|
|
}}
|
|
>
|
|
<Bookmark size={16} strokeWidth={2} fill={bookmarkedIds.has(String(pod.id)) ? 'currentColor' : 'none'} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* title */}
|
|
<h3 style={{ fontSize: 'clamp(16px,1.8vw,22px)', fontWeight: 900, color: NAVY, margin: '0 0 8px', lineHeight: 1.4, textAlign: lang === 'fa' ? 'right' : 'left' }}>
|
|
{pod[lang].title}
|
|
</h3>
|
|
|
|
{/* date */}
|
|
<div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, color: 'rgba(3,35,64,0.65)', fontWeight: 600, marginBottom: 16, flexDirection: lang === 'fa' ? 'row' : 'row-reverse' }}>
|
|
<Calendar size={14} color={GOLD} />
|
|
<span>{pod.date}</span>
|
|
</div>
|
|
|
|
<div style={{ height: 1, background: 'rgba(3,35,64,0.1)', marginBottom: 16 }} />
|
|
|
|
{/* play + waveform */}
|
|
{pod.mediaUrl ? (
|
|
<div style={{ marginInlineStart: -16, minWidth: 0 }}>
|
|
<MediaWavePlayer src={pod.mediaUrl} episodeKey={pod.id} tone="light" compact />
|
|
</div>
|
|
) : (
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16, flexDirection: lang === 'fa' ? 'row-reverse' : 'row', minWidth: 0 }}>
|
|
<button aria-label="play" style={{ flexShrink: 0, width: 44, height: 44, borderRadius: '50%', border: 'none', cursor: 'pointer', background: GOLD, display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'transform 0.2s, background-color 0.2s' }} className="hover:!scale-105 hover:!bg-[#b88d46]">
|
|
<Play size={18} fill="#fff" color="#fff" style={{ marginLeft: 2 }} />
|
|
</button>
|
|
<div style={{ flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 10, direction: 'ltr' }}>
|
|
<span style={{ fontSize: 11, color: 'rgba(3,35,64,0.6)', fontWeight: 700, flexShrink: 0 }}>۰۲:۳۱</span>
|
|
<div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 3, height: 26, overflow: 'hidden' }}>
|
|
{[4,6,8,10,7,5,8,12,15,18,14,10,8,12,16,20,22,17,12,9,12,15,18,22,24,20,15,11,8,12,15,17,20,22,18,14,10,8,12,15,19,21,16,12,9,11,14,18,20,16,11,8,6,9,12,15,17,13,9,7,10,13,16,18,14,10,8,11,14,16,13,9,7,10,13,16,18,14,10,7].map((h, i) => (
|
|
<span key={i} style={{ flex: 1, height: h, borderRadius: 1.5, background: i < 20 ? GOLD : 'rgba(3,35,64,0.18)', minWidth: 2, transition: 'background-color 0.2s' }} />
|
|
))}
|
|
</div>
|
|
<span style={{ fontSize: 11, color: 'rgba(3,35,64,0.6)', fontWeight: 700, flexShrink: 0 }}>{pod.duration}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* ── episode list (left) + description (right) ── */}
|
|
<div style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: '1fr 1.2fr',
|
|
gap: 40,
|
|
direction: lang === 'fa' ? 'rtl' : 'ltr'
|
|
}} className="max-lg:!grid-cols-1 max-lg:!gap-8">
|
|
|
|
{/* episode list — first DOM → left in LTR, left in RTL via order */}
|
|
<div style={{
|
|
order: lang === 'fa' ? 2 : 1,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: 16
|
|
}}>
|
|
{podcasts.filter((_, idx) => idx !== activePod).slice(0, 2).map((p) => {
|
|
const originalIndex = podcasts.findIndex(item => item.id === p.id);
|
|
return (
|
|
<button
|
|
key={p.id}
|
|
onClick={() => setActivePod(originalIndex)}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 16,
|
|
width: '100%',
|
|
cursor: 'pointer',
|
|
background: '#FAF8F5',
|
|
border: '1px solid rgba(3, 35, 64, 0.04)',
|
|
borderRadius: 16,
|
|
padding: 16,
|
|
flexDirection: lang === 'fa' ? 'row-reverse' : 'row',
|
|
textAlign: lang === 'fa' ? 'right' : 'left',
|
|
transition: 'all 0.2s'
|
|
}}
|
|
className="hover:!bg-[#fff] hover:!border-transparent hover:!shadow-[0_8px_20px_-8px_rgba(3,35,64,0.15)]"
|
|
>
|
|
<img
|
|
src={p.cover}
|
|
alt=""
|
|
style={{
|
|
width: 120,
|
|
height: 80,
|
|
borderRadius: 12,
|
|
objectFit: 'cover',
|
|
flexShrink: 0,
|
|
display: 'block'
|
|
}}
|
|
/>
|
|
<div style={{
|
|
flex: 1,
|
|
minWidth: 0,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: 8,
|
|
direction: lang === 'fa' ? 'rtl' : 'ltr'
|
|
}}>
|
|
{/* Top Row inside card text: Title & Duration */}
|
|
<div style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
width: '100%'
|
|
}}>
|
|
<div style={{
|
|
fontSize: 14.5,
|
|
fontWeight: 900,
|
|
color: NAVY,
|
|
margin: 0
|
|
}}>
|
|
{p[lang].title}
|
|
</div>
|
|
<span style={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
gap: 4,
|
|
fontSize: 11,
|
|
color: GOLD,
|
|
fontWeight: 700,
|
|
flexShrink: 0,
|
|
direction: 'ltr'
|
|
}}>
|
|
<Clock size={12} strokeWidth={2.5} />
|
|
<span>{p.duration}</span>
|
|
</span>
|
|
</div>
|
|
<div style={{
|
|
fontSize: 12,
|
|
color: 'rgba(3, 35, 64, 0.55)',
|
|
lineHeight: 1.8,
|
|
display: '-webkit-box',
|
|
WebkitLineClamp: 2,
|
|
WebkitBoxOrient: 'vertical',
|
|
overflow: 'hidden',
|
|
textAlign: 'justify'
|
|
}}>
|
|
{p[lang].body}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
)
|
|
})}
|
|
</div>
|
|
|
|
{/* description — second DOM → right in LTR, right in RTL via order */}
|
|
<div style={{
|
|
order: lang === 'fa' ? 1 : 2,
|
|
direction: lang === 'fa' ? 'rtl' : 'ltr'
|
|
}}>
|
|
<div style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 12,
|
|
marginBottom: 16,
|
|
justifyContent: 'flex-start'
|
|
}}>
|
|
{lang === 'fa' ? (
|
|
<>
|
|
<h3 style={{ fontSize: 'clamp(16px, 1.6vw, 22px)', fontWeight: 900, color: NAVY, margin: 0, lineHeight: 1.4, flex: 1, textAlign: 'right' }}>
|
|
{pod[lang].title}
|
|
</h3>
|
|
<div style={{ width: 34, height: 34, borderRadius: '50%', border: `1.5px solid ${GOLD}`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: GOLD, flexShrink: 0 }}>
|
|
<Podcast size={16} strokeWidth={2.5} />
|
|
</div>
|
|
</>
|
|
) : (
|
|
<>
|
|
<div style={{ width: 34, height: 34, borderRadius: '50%', border: `1.5px solid ${GOLD}`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: GOLD, flexShrink: 0 }}>
|
|
<Podcast size={16} strokeWidth={2.5} />
|
|
</div>
|
|
<h3 style={{ fontSize: 'clamp(16px, 1.6vw, 22px)', fontWeight: 900, color: NAVY, margin: 0, lineHeight: 1.4, flex: 1, textAlign: 'left' }}>
|
|
{pod[lang].title}
|
|
</h3>
|
|
</>
|
|
)}
|
|
</div>
|
|
<p style={{
|
|
fontSize: 13.5,
|
|
lineHeight: 2.1,
|
|
color: 'rgba(3, 35, 64, 0.75)',
|
|
margin: '0 0 18px',
|
|
textAlign: 'justify',
|
|
direction: lang === 'fa' ? 'rtl' : 'ltr'
|
|
}}>
|
|
{pod[lang].body}
|
|
</p>
|
|
<div style={{
|
|
fontSize: 13.5,
|
|
fontWeight: 800,
|
|
color: GOLD,
|
|
marginBottom: 12,
|
|
textAlign: lang === 'fa' ? 'right' : 'left'
|
|
}}>
|
|
{lang === 'fa' ? 'مهمان برنامه: ' : 'Guest: '}{pod[lang].guest}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
</div>
|
|
<style>{`
|
|
@keyframes spinRing {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
`}</style>
|
|
</section>
|
|
)
|
|
}
|