import { useEffect, useMemo, useState } from 'react'; import type { DemoLocale } from './types'; type MarketingScene = { id: 'brief' | 'copy' | 'visual'; durationMs: number; }; type MarketingFeatureDemoProps = { locale: DemoLocale; isBusy: boolean; }; const COPY = { en: { title: 'Marketing Demo', busy: 'Running', hidden: 'Hidden', play: 'Play', pause: 'Pause', replay: 'Replay', hide: 'Hide', show: 'Show', videoName: 'marketing_demo.webm', step: 'Step', lanes: { brief: 'Brief', copy: 'Copy', visual: 'Visual', }, captions: { brief: 'Collect product + tone inputs', copy: 'Stream campaign copy blocks', visual: 'Generate image variations', }, words: { briefChips: ['Product', 'Tone', 'Channel'], copyChips: ['Headline', 'Caption', 'CTA', 'Tags'], visualCards: ['Hero', 'Social'], streamWords: ['Drafting', 'Refining', 'Scoring', 'Polishing'], visualImages: [ 'https://upload.wikimedia.org/wikipedia/commons/d/dd/Eggs_in_basket_2020_G1.jpg', 'https://upload.wikimedia.org/wikipedia/commons/c/c2/Fresh_Vegetables_2.jpg', ], }, }, 'zh-TW': { title: '行銷導覽', busy: '執行中', hidden: '已隱藏', play: '播放', pause: '暫停', replay: '重播', hide: '隱藏', show: '顯示', videoName: '行銷導覽影片.webm', step: '步驟', lanes: { brief: '需求', copy: '文案', visual: '素材', }, captions: { brief: '收集產品與語氣設定', copy: '串流活動文案區塊', visual: '生成多版本圖片', }, words: { briefChips: ['產品', '語氣', '渠道'], copyChips: ['標題', '內文', 'CTA', '標籤'], visualCards: ['主視覺', '社群版'], streamWords: ['生成', '潤稿', '評估', '優化'], visualImages: [ 'https://upload.wikimedia.org/wikipedia/commons/d/dd/Eggs_in_basket_2020_G1.jpg', 'https://upload.wikimedia.org/wikipedia/commons/c/c2/Fresh_Vegetables_2.jpg', ], }, }, } as const; const SCENES: MarketingScene[] = [ { id: 'brief', durationMs: 1650 }, { id: 'copy', durationMs: 1750 }, { id: 'visual', durationMs: 1700 }, ]; export default function MarketingFeatureDemo({ locale, isBusy }: MarketingFeatureDemoProps) { const copy = COPY[locale]; const scenes = useMemo(() => SCENES, []); const [sceneIndex, setSceneIndex] = useState(0); const [elapsedMs, setElapsedMs] = useState(0); const [isPlaying, setIsPlaying] = useState(true); const [isCollapsed, setIsCollapsed] = useState(false); const [reducedMotion, setReducedMotion] = useState(false); useEffect(() => { const media = window.matchMedia('(prefers-reduced-motion: reduce)'); const apply = () => setReducedMotion(media.matches); apply(); if (media.addEventListener) { media.addEventListener('change', apply); return () => media.removeEventListener('change', apply); } media.addListener(apply); return () => media.removeListener(apply); }, []); useEffect(() => { if (reducedMotion) setIsPlaying(false); }, [reducedMotion]); useEffect(() => { setSceneIndex(0); setElapsedMs(0); setIsCollapsed(false); if (!reducedMotion) setIsPlaying(true); }, [locale, reducedMotion]); useEffect(() => { if (!isBusy) return; setIsCollapsed(true); setIsPlaying(false); }, [isBusy]); useEffect(() => { if (!isPlaying || isCollapsed || isBusy || reducedMotion) return; const timer = window.setInterval(() => { setElapsedMs((prev) => { const scene = scenes[sceneIndex]; if (!scene) return 0; const next = prev + 120; if (next < scene.durationMs) return next; setSceneIndex((current) => (current + 1) % scenes.length); return 0; }); }, 120); return () => window.clearInterval(timer); }, [isPlaying, isCollapsed, isBusy, reducedMotion, scenes, sceneIndex]); const activeScene = scenes[sceneIndex] ?? scenes[0]; const totalDuration = scenes.reduce((sum, scene) => sum + scene.durationMs, 0); const previousDuration = scenes.slice(0, sceneIndex).reduce((sum, scene) => sum + scene.durationMs, 0); const progress = totalDuration > 0 ? Math.round(((previousDuration + elapsedMs) / totalDuration) * 100) : 0; const sceneCaption = copy.captions[activeScene.id]; const streamOffset = Math.floor(elapsedMs / 420); const activeStreamWords = copy.words.streamWords.map( (_word, index) => copy.words.streamWords[(streamOffset + index) % copy.words.streamWords.length] ); const replay = () => { setSceneIndex(0); setElapsedMs(0); if (!reducedMotion && !isBusy) setIsPlaying(true); }; if (isCollapsed) { return (

{isBusy ? copy.busy : copy.hidden}

{!isBusy ? ( ) : null}
); } return (

{copy.title}

{copy.step} {sceneIndex + 1}/{scenes.length}
{copy.videoName}
1 {copy.lanes.brief}
{copy.words.briefChips.map((item) => ( {item} ))}

{locale === 'zh-TW' ? '產品資訊與活動目標已整理。' : 'Product context and campaign goal prepared.'}

2 {copy.lanes.copy}
{activeStreamWords.slice(0, 3).map((word, index) => (
{word}
))}
{copy.words.copyChips.map((item) => ( {item} ))}
3 {copy.lanes.visual}
{copy.words.visualCards.map((label, index) => (
{label} {label}
))}

{locale === 'zh-TW' ? '輸出可下載圖像與套用按鈕。' : 'Download-ready assets and apply actions.'}

); }