158 lines
10 KiB
TypeScript
158 lines
10 KiB
TypeScript
// ─────────────────────────────────────────────────────────────
|
||
// Home media content layer (videocast + podcast items)
|
||
// Mock/seed data. Replaced at runtime by bootstrapMedia() which
|
||
// reuses the EXISTING articles API (type='video' / type='podcast').
|
||
// No dedicated table — see articleToVideo / articleToPodcast below.
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
export interface MediaLangText {
|
||
title: string;
|
||
guest: string;
|
||
body: string;
|
||
}
|
||
|
||
export interface VideoItem {
|
||
id: number | string;
|
||
fa: MediaLangText;
|
||
en: MediaLangText;
|
||
ep: string;
|
||
duration: string;
|
||
date: string;
|
||
thumb: string;
|
||
}
|
||
|
||
export interface PodcastItem {
|
||
id: number | string;
|
||
epNum: string;
|
||
date: string;
|
||
rating: string;
|
||
duration: string;
|
||
cover: string;
|
||
fa: MediaLangText & { ep: string };
|
||
en: MediaLangText & { ep: string };
|
||
}
|
||
|
||
export const videos: VideoItem[] = [
|
||
{
|
||
id: 1,
|
||
fa: { title: 'نگاهی به آن سوی مرزهای تولید', guest: 'گفتگو با مهندس سیامک فجری',
|
||
body: 'در ویدیوکست «Steel Horizon»، ما فراتر از دادههای خام قیمت و تناژ، به سراغ مهندسی تغییر و معماری آینده صنعت میرویم. اینجا محل تلاقی استراتژیهای کلان، تکنولوژیهای برهمزننده و رهبرانی است که فولاد فردا را نه با کورهها، که با «بینش» میسازند. ما طوفانهای بازار را تحلیل میکنیم تا شما با اطمینان، مسیر آینده را ترسیم کنید.\nصنعت فولاد در حال ورود به پیچیدهترین چرخه حیات خود است؛ جایی که هوش مصنوعی، مقررات کربنی و ژئواکونومی، قواعد بازی را بازنویسی کردهاند. در «Steel Logic» با تحلیلگران ارشد و استراتژیستهای تراز اول، به گفتگو مینشینیم تا لایههای پنهان این پیچیدگیها را آشکار کنیم. اینجا خبری از هیجانزدگی نیست؛ فقط تحلیلهای دادهمحور و تصمیمساز.' },
|
||
en: { title: 'Beyond the Frontiers of Production', guest: 'A talk with Eng. Siamak Fajri',
|
||
body: 'In the "Steel Horizon" videocast we go beyond raw price and tonnage data to the engineering of change and the architecture of the industry\'s future.' },
|
||
ep: 'EP.12', duration: '۴۲ دقیقه', date: '۲۵ خرداد ۱۴۰۵', thumb: '/news/photo-1504307651254-35680f356dfd.jpg',
|
||
},
|
||
{
|
||
id: 2,
|
||
fa: { title: 'تحلیل بازار جهانی فلزات پایه', guest: 'گفتگو با کارشناسان بازار',
|
||
body: 'نوسانات قیمت مس، آلومینیوم و روی و تأثیر آن بر زنجیره فولاد را با تحلیلگران بازار بررسی میکنیم.' },
|
||
en: { title: 'Global Base Metals Analysis', guest: 'With market analysts',
|
||
body: 'Price volatility in copper, aluminum and zinc and its steel-chain impact.' },
|
||
ep: 'EP.11', duration: '۳۸ دقیقه', date: '۱۸ خرداد ۱۴۰۵', thumb: '/news/photo-1558618666-fcd25c85cd64.jpg',
|
||
},
|
||
{
|
||
id: 3,
|
||
fa: { title: 'ژئوپلیتیک و صادرات فولاد', guest: 'گفتگو با تحلیلگران ژئواکونومی',
|
||
body: 'تأثیر تحولات منطقهای بر بازارهای صادراتی فولاد ایران و فرصتهای پیش رو.' },
|
||
en: { title: 'Geopolitics & Steel Exports', guest: 'With geo-economics analysts',
|
||
body: 'How regional developments shape Iran\'s steel export markets.' },
|
||
ep: 'EP.10', duration: '۵۱ دقیقه', date: '۱۱ خرداد ۱۴۰۵', thumb: '/news/photo-1504328345606-18bbc8c9d7d1.jpg',
|
||
},
|
||
{
|
||
id: 4,
|
||
fa: { title: 'سرمایهگذاری در صنعت فولاد', guest: 'گفتگو با مدیران سرمایهگذاری',
|
||
body: 'فرصتها و چالشهای سرمایهگذاری در بخشهای مختلف زنجیره ارزش فولاد.' },
|
||
en: { title: 'Steel Industry Investment', guest: 'With investment managers',
|
||
body: 'Opportunities and challenges across the steel value chain.' },
|
||
ep: 'EP.09', duration: '۴۵ دقیقه', date: '۴ خرداد ۱۴۰۵', thumb: '/news/photo-1611273426858-450d8e3c9fce.jpg',
|
||
},
|
||
]
|
||
|
||
export const podcasts: PodcastItem[] = [
|
||
{
|
||
id: 1,
|
||
epNum: 'اپیزود ۷۷', date: '۲۵ / خرداد / ۱۴۰۵', rating: '۴/۵', duration: '۱۰:۵۶', cover: '/news/photo-1540575467063-178a50c2df87.jpg',
|
||
fa: { title: 'کالبدشکافی عقلانی پیچیدگیهای صنعتی', ep: 'قسمت ۱۲', guest: 'مهندس سیامک شجاعی',
|
||
body: '«صنعت فولاد در عصر حاضر، در پیچیدهترین چرخه حیات خود قرار گرفته است؛ جایی که همگرایی هوش مصنوعی، الزامات زیستمحیطی و تنشهای ژئواکونومیک، قواعد کلاسیک تولید و تجارت را بهکلی بازنویسی کردهاند. در پادکست «نام انتخابی»، ما با عبور از هیاهوی رسانهای و تحلیلهای سطحی، به کالبدشکافی عقلانی این پیچیدگیها میپردازیم. ما با دعوت از استراتژیستهای تراز اول و خبرگان این حوزه، لایههای پنهان چالشهای صنعتی را میشکافیم تا بینشی شفاف، دادهمحور و تصمیمساز را در اختیار رهبری قرار دهیم که برای عبور از طوفانهای تغییر، به قطبنمای دقیقتر از عرفهای بازار نیاز دارند.»' },
|
||
en: { title: 'A Rational Dissection of Industrial Complexity', ep: 'Episode 12', guest: 'Eng. Siamak Shojaei',
|
||
body: 'Steel today is in its most complex cycle yet — where AI, environmental mandates and geo-economic tension rewrite the classic rules of production and trade.' },
|
||
},
|
||
{
|
||
id: 2,
|
||
epNum: 'اپیزود ۷۶', date: '۱۸ / خرداد / ۱۴۰۵', rating: '۴/۵', duration: '۱:۴۰:۱۸', cover: '/news/photo-1566873535350-6586b0b7a1f2.jpg',
|
||
fa: { title: 'آزمایشگاه کوره', ep: 'قسمت ۸', guest: 'کارشناسان بازار',
|
||
body: '«The Foundry Lab» محلی برای کالبدشکافی دقیق تحولات فناورانه و مدلهای نوین فولادسازی است. ما در این پادکست با نگاهی موشکافانه، چالشهای فنی را بررسی میکنیم.' },
|
||
en: { title: 'The Foundry Lab', ep: 'Episode 8', guest: 'Market experts',
|
||
body: 'The Foundry Lab dissects technological change and new steelmaking models with a meticulous engineering lens.' },
|
||
},
|
||
{
|
||
id: 3,
|
||
epNum: 'اپیزود ۷۵', date: '۱۱ / خرداد / ۱۴۰۵', rating: '۴/۵', duration: '۱:۴۰:۱۸', cover: '/news/photo-1578662996442-48f60103fc96.jpg',
|
||
fa: { title: 'معمار فولاد', ep: 'قسمت ۵', guest: 'رهبران صنعت',
|
||
body: 'در «Steel Architect»، ما به سراغ داستان ساختن فولاد فردا میرویم؛ روایتی که رهبرانی که از مدلهای سنتی کسبوکار به چالش کشیدهاند را به تصویر میکشد.' },
|
||
en: { title: 'Steel Architect', ep: 'Episode 5', guest: 'Industry leaders',
|
||
body: 'Steel Architect tells the story of building tomorrow\'s steel — leaders challenging traditional business models.' },
|
||
},
|
||
]
|
||
|
||
// ── article → media item mappers ───────────────────────────────
|
||
// The articles API has no per-language fields, so we put the same
|
||
// title/summary in both fa/en and let the component pick by lang.
|
||
function articleToVideo(a: Record<string, unknown>, i: number): VideoItem {
|
||
const title = String(a.title ?? '')
|
||
const guest = String(a.author ?? '')
|
||
const body = String(a.summary ?? '')
|
||
return {
|
||
id: String(a.id ?? i),
|
||
fa: { title, guest, body },
|
||
en: { title, guest, body },
|
||
ep: `EP.${i + 1}`,
|
||
duration: '',
|
||
date: String(a.publishDate ?? ''),
|
||
thumb: String(a.coverImage ?? '') || '/news/photo-1504307651254-35680f356dfd.jpg',
|
||
}
|
||
}
|
||
|
||
function articleToPodcast(a: Record<string, unknown>, i: number): PodcastItem {
|
||
const title = String(a.title ?? '')
|
||
const guest = String(a.author ?? '')
|
||
const body = String(a.summary ?? '')
|
||
const ep = `قسمت ${i + 1}`
|
||
return {
|
||
id: String(a.id ?? i),
|
||
epNum: `اپیزود ${i + 1}`,
|
||
date: String(a.publishDate ?? ''),
|
||
rating: '۵/۵',
|
||
duration: '',
|
||
cover: String(a.coverImage ?? '') || '/news/photo-1540575467063-178a50c2df87.jpg',
|
||
fa: { title, guest, body, ep },
|
||
en: { title, guest, body, ep },
|
||
}
|
||
}
|
||
|
||
const PANEL_API = (import.meta as ImportMeta & { env?: Record<string, string> }).env?.VITE_PANEL_API || 'http://localhost:3001'
|
||
|
||
export async function bootstrapMedia(): Promise<void> {
|
||
try {
|
||
const [videoRes, podRes] = await Promise.all([
|
||
fetch(`${PANEL_API}/api/articles?type=video&limit=50`),
|
||
fetch(`${PANEL_API}/api/articles?type=podcast&limit=50`),
|
||
])
|
||
|
||
if (videoRes.ok) {
|
||
const fetched = await videoRes.json()
|
||
if (Array.isArray(fetched) && fetched.length > 0) {
|
||
videos.length = 0
|
||
videos.push(...fetched.map((a: Record<string, unknown>, i: number) => articleToVideo(a, i)))
|
||
}
|
||
}
|
||
|
||
if (podRes.ok) {
|
||
const fetched = await podRes.json()
|
||
if (Array.isArray(fetched) && fetched.length > 0) {
|
||
podcasts.length = 0
|
||
podcasts.push(...fetched.map((a: Record<string, unknown>, i: number) => articleToPodcast(a, i)))
|
||
}
|
||
}
|
||
} catch { /* panel offline → keep static fallback */ }
|
||
}
|