'use client' import { useEffect } from 'react' import Link from 'next/link' export type DeckSlide = { kicker: string index: string title: React.ReactNode body: string format: React.ReactNode link?: { href: string; label: string } meta?: React.ReactNode } const V1_SLIDES: DeckSlide[] = [ { kicker: 'دليل حصري · المستوى المتوسط', index: '01', title: 'ابنِ وكيلك الأول دون فوضى', body: 'خريطة عملية لتقسيم المهام، اختيار الأدوات، وضبط ذاكرة الوكيل قبل كتابة الكود.', format: <>▶فيديو · 28 دقيقة>, link: { href: '/posts/agent-loop-stop-condition', label: 'شاهد المعاينة ←' }, }, { kicker: 'مقال تطبيقي · للمبتدئين', index: '02', title: 'كيف تختار نموذجاً لمهمتك؟', body: 'مقارنة منهجية حسب الجودة، التكلفة، السرعة، والخصوصية — من دون ضجيج تسويقي.', format: <>قراءة · 12 دقيقة>, link: { href: '/posts/article-agent-guide', label: 'ابدأ القراءة ←' }, }, { kicker: 'مسار متقدم · للأعضاء', index: '03', title: <>من RAG إلى إجابة موثوقة>, body: 'صمّم الاسترجاع، اختبر المصادر، وافهم أين تنهار الإجابة قبل أن تصل إلى المستخدم.', format: <>▶سلسلة · 4 أجزاء>, link: { href: '/subscription', label: 'شاهد للأعضاء ←' }, }, ] const DOT_LABELS = ['الشريحة الأولى', 'الشريحة الثانية', 'الشريحة الثالثة'] /* Featured deck — markup and slide logic from arabic-ai-learning-catalog(.v2).html (autoplay 6.5s, dots, arrows, localStorage persistence). Slides render a link when given; otherwise the v2 home variant shows a meta tag. */ export default function CatalogDeck({ slides = V1_SLIDES }: { slides?: DeckSlide[] }) { useEffect(() => { const slideEls = [...document.querySelectorAll('.deck-slide')] as HTMLElement[] const dots = [...document.querySelectorAll('.deck-dot')] as HTMLElement[] let activeSlide = Number(localStorage.getItem('midad-slide') || 0) % slideEls.length let timer: ReturnType | undefined function showSlide(index: number) { activeSlide = (index + slideEls.length) % slideEls.length slideEls.forEach((slide, i) => slide.classList.toggle('active', i === activeSlide)) dots.forEach((dot, i) => { dot.classList.toggle('active', i === activeSlide) dot.setAttribute('aria-current', i === activeSlide ? 'true' : 'false') }) localStorage.setItem('midad-slide', String(activeSlide)) } function restartDeck() { clearInterval(timer) if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) timer = setInterval(() => showSlide(activeSlide + 1), 6500) } document.getElementById('prevSlide')?.addEventListener('click', () => { showSlide(activeSlide - 1); restartDeck() }) document.getElementById('nextSlide')?.addEventListener('click', () => { showSlide(activeSlide + 1); restartDeck() }) dots.forEach(dot => dot.addEventListener('click', () => { showSlide(Number((dot as HTMLElement).dataset.dot)); restartDeck() })) /* QA-05: keep controls stationary — pause autoplay while hovered/focused. */ const deck = document.querySelector('.deck') deck?.addEventListener('mouseenter', () => clearInterval(timer)) deck?.addEventListener('mouseleave', () => restartDeck()) deck?.addEventListener('focusin', () => clearInterval(timer)) deck?.addEventListener('focusout', () => restartDeck()) showSlide(activeSlide) restartDeck() return () => clearInterval(timer) }, []) return ( {slides.map((s, i) => ( {s.kicker}{s.index} {s.title}{s.body} {s.format} {s.link ? {s.link.label} : {s.meta}} ))} {slides.map((_, i) => ( ))} ← → ) }
{s.body}