diff --git a/web/public/assembly/PezkuwiChain_Horizontal.png b/web/public/assembly/PezkuwiChain_Horizontal.png new file mode 100644 index 00000000..cb4468e2 Binary files /dev/null and b/web/public/assembly/PezkuwiChain_Horizontal.png differ diff --git a/web/public/assembly/krd-sun.svg b/web/public/assembly/krd-sun.svg new file mode 100644 index 00000000..4b29acb4 --- /dev/null +++ b/web/public/assembly/krd-sun.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assembly/kurdistan-flag.svg b/web/public/assembly/kurdistan-flag.svg new file mode 100644 index 00000000..d620bc84 --- /dev/null +++ b/web/public/assembly/kurdistan-flag.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/pages/governance/AssemblyPage.tsx b/web/src/pages/governance/AssemblyPage.tsx index 22c89c01..6f684079 100644 --- a/web/src/pages/governance/AssemblyPage.tsx +++ b/web/src/pages/governance/AssemblyPage.tsx @@ -1,137 +1,108 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import { languages } from '@/i18n/config'; +import { LanguageSwitcher } from '@/components/LanguageSwitcher'; +import { ASSEMBLY_CSS } from './assembly/_css'; -interface Member { - id: string; - name: string; - role: string; - roleKu: string; - emoji: string; - region: string; - since: string; -} - -interface Session { - id: string; - titleKu: string; - title: string; - date: string; - status: 'upcoming' | 'completed' | 'in-session'; - agenda: string; -} - -const MEMBERS: Member[] = [ - { id: '1', name: 'Azad Kurdo', role: 'Speaker', roleKu: 'Serokê Meclîsê', emoji: '👨‍⚖️', region: 'Amed', since: '2025-06' }, - { id: '2', name: 'Rozerin Xan', role: 'Deputy Speaker', roleKu: 'Cîgirê Serokê Meclîsê', emoji: '👩‍⚖️', region: 'Hewler', since: '2025-06' }, - { id: '3', name: 'Serhat Demirtash', role: 'Finance Committee', roleKu: 'Komîteya Darayî', emoji: '👨‍💼', region: 'Diyarbekir', since: '2025-08' }, - { id: '4', name: 'Jîn Bakir', role: 'Technology Committee', roleKu: 'Komîteya Teknolojiyê', emoji: '👩‍💻', region: 'Silêmanî', since: '2025-07' }, - { id: '5', name: 'Kawa Zana', role: 'Education Committee', roleKu: 'Komîteya Perwerdê', emoji: '👨‍🎓', region: 'Wan', since: '2025-09' }, - { id: '6', name: 'Berfîn Shêx', role: 'Social Affairs', roleKu: 'Karên Civakî', emoji: '👩‍🏫', region: 'Kerkûk', since: '2025-08' }, - { id: '7', name: 'Dilovan Ehmed', role: 'Foreign Relations', roleKu: 'Têkiliyên Derve', emoji: '🧑‍💼', region: 'Qamişlo', since: '2025-10' }, -]; - -const SESSIONS: Session[] = [ - { id: 's1', titleKu: 'Civîna Budceya Q2 2026', title: 'Q2 2026 Budget Session', date: '2026-04-15', status: 'upcoming', agenda: 'Treasury allocation, staking rewards adjustment, education fund.' }, - { id: 's2', titleKu: 'Civîna Yasadanînê #12', title: 'Legislative Session #12', date: '2026-04-10', status: 'upcoming', agenda: 'Cross-chain bridge proposal, fee structure revision.' }, - { id: 's3', titleKu: 'Civîna Awarte ya Ewlehiyê', title: 'Emergency Security Session', date: '2026-03-28', status: 'completed', agenda: 'Network security audit results, validator requirements update.' }, - { id: 's4', titleKu: 'Civîna Yasadanînê #11', title: 'Legislative Session #11', date: '2026-03-15', status: 'completed', agenda: 'Citizenship criteria, NFT standards, community grants.' }, -]; - -type Tab = 'members' | 'sessions'; +// Pro design ported from "Kurdistan Parliament" — on-chain governance landing. +// Content is fully localized into the app's 6 standard languages; each variant is +// lazy-loaded so only the active language ships. Hemicycle seat tooltip wired below. +const LOADERS: Record Promise<{ HTML: string }>> = { + en: () => import('./assembly/en'), + tr: () => import('./assembly/tr'), + kmr: () => import('./assembly/kmr'), + ckb: () => import('./assembly/ckb'), + fa: () => import('./assembly/fa'), + ar: () => import('./assembly/ar'), +}; +// i18n language code -> assembly variant file +const MAP: Record = { + en: 'en', tr: 'tr', 'ku-kurmanji': 'kmr', 'ku-sorani': 'ckb', ar: 'ar', fa: 'fa', +}; export default function AssemblyPage() { const navigate = useNavigate(); - const { t } = useTranslation(); - const [activeTab, setActiveTab] = useState('members'); + const { i18n } = useTranslation(); + const fkey = MAP[i18n.language] || 'en'; + const dir = (languages as Record)[i18n.language]?.dir || 'ltr'; + const [html, setHtml] = useState(''); - const sessionStatusLabel = (status: Session['status']) => { - if (status === 'upcoming') return t('assembly.session.upcoming', 'Upcoming'); - if (status === 'in-session') return t('assembly.session.inSession', 'In Session'); - return t('assembly.session.completed', 'Completed'); - }; + useEffect(() => { + let alive = true; + (LOADERS[fkey] || LOADERS.en)().then((m) => { if (alive) setHtml(m.HTML); }); + return () => { alive = false; }; + }, [fkey]); - const sessionStatusCls = (status: Session['status']) => { - if (status === 'upcoming') return 'bg-blue-900/50 text-blue-400'; - if (status === 'in-session') return 'bg-green-900/50 text-green-400'; - return 'bg-gray-800 text-gray-400'; - }; + // hemicycle seat tooltip (ported from the design's support.js _wire) + useEffect(() => { + if (!html) return; + const root = document.getElementById('khemi'); + const tip = document.getElementById('khemi-tip'); + if (!root || !tip) return; + const dot = tip.querySelector('[data-tdot]') as HTMLElement | null; + const nm = tip.querySelector('[data-tname]') as HTMLElement | null; + const bl = tip.querySelector('[data-tbloc]') as HTMLElement | null; + const rg = tip.querySelector('[data-tregion]') as HTMLElement | null; + const onMove = (e: MouseEvent) => { + const el = (e.target as HTMLElement).closest('[data-mp]') as HTMLElement | null; + if (!el) { tip.style.display = 'none'; return; } + if (nm) nm.textContent = el.getAttribute('data-name'); + if (bl) bl.textContent = el.getAttribute('data-bloc'); + if (rg) rg.textContent = el.getAttribute('data-region'); + if (dot) dot.style.background = el.getAttribute('data-color') || '#888'; + const r = root.getBoundingClientRect(); + tip.style.display = 'block'; + let x = e.clientX - r.left; + x = Math.max(90, Math.min(x, r.width - 90)); + tip.style.left = x + 'px'; + tip.style.top = (e.clientY - r.top - 14) + 'px'; + }; + const onLeave = () => { tip.style.display = 'none'; }; + root.addEventListener('mousemove', onMove); + root.addEventListener('mouseleave', onLeave); + return () => { + root.removeEventListener('mousemove', onMove); + root.removeEventListener('mouseleave', onLeave); + }; + }, [html]); + + const startSide = dir === 'rtl' ? { right: 14 } : { left: 14 }; + const navPad = dir === 'rtl' + ? '.kp-root header{padding-right:72px !important;padding-left:120px !important;}' + : '.kp-root header{padding-left:72px !important;padding-right:120px !important;}'; return ( -
- {/* Header */} -
-
- - {t('assembly.breadcrumb', 'Governance')} -
-
- 🏛️ -

{t('assembly.title', 'Kurdistan Digital Assembly')}

-

{t('assembly.subtitle', 'Kurdistan Digital Assembly')}

-
-
- {[ - { val: MEMBERS.length, label: t('assembly.stats.members', 'Members') }, - { val: 4, label: t('assembly.stats.committees', 'Committees') }, - { val: 12, label: t('assembly.stats.sessions', 'Sessions') }, - ].map((stat, i) => ( -
0 ? 'border-l border-white/20' : ''}`}> -

{stat.val}

-

{stat.label}

-
- ))} -
+
+