import { useState } from 'react' const NAVY = '#032340' const GOLD = '#CD9E53' const NEON = '#d4ff2e' // neon yellow for conference-date markers type EventItem = { g: Date // Gregorian date of the event title: string city: string time: string type: string color: string } /* steel conferences during اردیبهشت ۱۴۰۵ (anchor month below) */ const EVENTS: EventItem[] = [ { g: new Date(2026, 3, 28), title: 'کنفرانس فولاد خاورمیانه', city: 'دبی، امارات', time: '۰۹:۰۰ – ۱۷:۰۰', type: 'کنفرانس بین‌المللی', color: '#9b1c1c' }, { g: new Date(2026, 4, 5), title: 'نمایشگاه متالکس ۱۴۰۵', city: 'تهران، ایران', time: '۱۰:۰۰ – ۱۸:۰۰', type: 'نمایشگاه', color: GOLD }, { g: new Date(2026, 4, 12), title: 'نشست تخصصی زنجیره فولاد', city: 'اصفهان، ایران', time: '۱۴:۰۰ – ۱۸:۰۰', type: 'نشست تخصصی', color: '#1e8449' }, { g: new Date(2026, 4, 18), title: 'وبینار فولاد سبز و کربن‌زدایی', city: 'آنلاین', time: '۱۶:۰۰ – ۱۸:۰۰', type: 'وبینار', color: '#2471a3' }, ] const ANCHOR = new Date(2026, 4, 10) // a day inside اردیبهشت ۱۴۰۵ const J_MONTHS = ['فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'] const WEEKDAYS = ['ش', 'ی', 'د', 'س', 'چ', 'پ', 'ج'] // شنبه … جمعه const faDigits = (n: number) => n.toLocaleString('fa-IR', { useGrouping: false }) /* Jalali year/month/day for a Gregorian Date, via the browser's Persian calendar */ function jParts(d: Date) { const parts = new Intl.DateTimeFormat('en-US-u-ca-persian', { day: 'numeric', month: 'numeric', year: 'numeric' }).formatToParts(d) const get = (t: string) => Number(parts.find((p) => p.type === t)?.value) return { day: get('day'), month: get('month'), year: get('year') } } const sameDay = (a: Date, b: Date) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate() function buildMonth(anchor: Date) { const { month, year } = jParts(anchor) // walk back to the 1st of this Jalali month const first = new Date(anchor) while (jParts(first).day !== 1) first.setDate(first.getDate() - 1) // collect every day until the Jalali month rolls over const days: Date[] = [] const cur = new Date(first) while (jParts(cur).month === month && jParts(cur).year === year) { days.push(new Date(cur)) cur.setDate(cur.getDate() + 1) } const firstCol = (first.getDay() + 1) % 7 // Sat→0 … Fri→6 return { month, year, days, firstCol } } export default function EventCalendar() { const { month, year, days, firstCol } = buildMonth(ANCHOR) const [hover, setHover] = useState(null) const eventFor = (d: Date) => EVENTS.findIndex((e) => sameDay(e.g, d)) return (
{/* header */}
تقویم رویدادها
{J_MONTHS[month - 1]} {faDigits(year)}
{/* weekday row */}
{WEEKDAYS.map((w, i) => (
{w}
))}
{/* day grid */}
{Array.from({ length: firstCol }).map((_, i) =>
)} {days.map((d, i) => { const j = jParts(d) const ev = eventFor(d) const marked = ev >= 0 const isHover = hover === ev && marked return (
{/* breathing neon ring on conference days */} {marked && ( )} {/* hover card */} {isHover && (
{EVENTS[ev].type}
{EVENTS[ev].title}
📅 {faDigits(j.day)} {J_MONTHS[month - 1]} {faDigits(year)}
📍 {EVENTS[ev].city}
🕐 {EVENTS[ev].time}
{/* arrow */}
)}
) })}
{/* legend */}
روزهای دارای رویداد — نشانگر را نگه دارید
) }