feat: add KurdMedia, Help pages + fix Docs + wire routes + i18n (6 langs)

- Add KurdMediaPage (/social/kurdmedia): DKS media channels + social platform links
- Add HelpPage (/help): coming soon with planned features + WhatsKURD shortcut
- Rewrite Docs.tsx (/docs): clean documentation overview with section cards + docs.pezkuwichain.io button
- Wire new routes in App.tsx: /social/kurdmedia, /help
- Update MobileHomeLayout: kurdMedia → /social/kurdmedia, help → /help (fix crash)
- Add i18n keys to all 6 locales: kurdMedia.*, help.*, docs.section.*, messaging.palletNotReady
This commit is contained in:
2026-04-09 08:19:45 +03:00
parent eaccf65beb
commit c56e021a6b
11 changed files with 591 additions and 298 deletions
+4
View File
@@ -70,6 +70,8 @@ const AssemblyPage = lazy(() => import('@/pages/governance/AssemblyPage'));
const JusticePage = lazy(() => import('@/pages/governance/JusticePage')); const JusticePage = lazy(() => import('@/pages/governance/JusticePage'));
const PollsPage = lazy(() => import('@/pages/governance/PollsPage')); const PollsPage = lazy(() => import('@/pages/governance/PollsPage'));
const WhatsKURDPage = lazy(() => import('@/pages/social/WhatsKURDPage')); const WhatsKURDPage = lazy(() => import('@/pages/social/WhatsKURDPage'));
const KurdMediaPage = lazy(() => import('@/pages/social/KurdMediaPage'));
const HelpPage = lazy(() => import('@/pages/HelpPage'));
// Network pages // Network pages
const Mainnet = lazy(() => import('@/pages/networks/Mainnet')); const Mainnet = lazy(() => import('@/pages/networks/Mainnet'));
@@ -238,6 +240,8 @@ function App() {
<Route path="/governance/justice" element={<JusticePage />} /> <Route path="/governance/justice" element={<JusticePage />} />
<Route path="/governance/polls" element={<PollsPage />} /> <Route path="/governance/polls" element={<PollsPage />} />
<Route path="/social/whatskurd" element={<WhatsKURDPage />} /> <Route path="/social/whatskurd" element={<WhatsKURDPage />} />
<Route path="/social/kurdmedia" element={<KurdMediaPage />} />
<Route path="/help" element={<HelpPage />} />
<Route path="/presale" element={<Presale />} /> <Route path="/presale" element={<Presale />} />
<Route path="/launchpad" element={<PresaleList />} /> <Route path="/launchpad" element={<PresaleList />} />
<Route path="/launchpad/:id" element={<PresaleDetail />} /> <Route path="/launchpad/:id" element={<PresaleDetail />} />
+2 -2
View File
@@ -83,9 +83,9 @@ const APP_SECTIONS: AppSection[] = [
apps: [ apps: [
{ title: 'mobile.app.whatsKurd', icon: '💬', route: '/social/whatskurd' }, { title: 'mobile.app.whatsKurd', icon: '💬', route: '/social/whatskurd' },
{ title: 'mobile.app.forum', icon: '📰', route: '/forum' }, { title: 'mobile.app.forum', icon: '📰', route: '/forum' },
{ title: 'mobile.app.kurdMedia', icon: '📺', route: '/forum', comingSoon: true }, { title: 'mobile.app.kurdMedia', icon: '📺', route: '/social/kurdmedia' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', comingSoon: true }, { title: 'mobile.app.events', icon: '📅', route: '/forum', comingSoon: true },
{ title: 'mobile.app.help', icon: '❓', route: '/docs' }, { title: 'mobile.app.help', icon: '❓', route: '/help' },
{ title: 'mobile.app.music', icon: '🎵', route: '/forum', comingSoon: true }, { title: 'mobile.app.music', icon: '🎵', route: '/forum', comingSoon: true },
{ title: 'mobile.app.vpn', icon: '🛡️', route: '/forum', comingSoon: true }, { title: 'mobile.app.vpn', icon: '🛡️', route: '/forum', comingSoon: true },
{ title: 'mobile.app.referral', icon: '👥', route: '/dashboard', requiresAuth: true }, { title: 'mobile.app.referral', icon: '👥', route: '/dashboard', requiresAuth: true },
+34
View File
@@ -3757,6 +3757,7 @@ export default {
'messaging.checkingKey': 'جاري التحقق من مفتاح التشفير...', 'messaging.checkingKey': 'جاري التحقق من مفتاح التشفير...',
'messaging.send': 'إرسال', 'messaging.send': 'إرسال',
'messaging.sending': 'جاري الإرسال...', 'messaging.sending': 'جاري الإرسال...',
'messaging.palletNotReady': 'حزمة المراسلة غير متاحة بعد على People Chain. يلزم تحديث وقت التشغيل.',
// Mobile Home Layout // Mobile Home Layout
'mobile.greeting': 'مرحباً', 'mobile.greeting': 'مرحباً',
@@ -3904,4 +3905,37 @@ export default {
'taxZekat.confirm.cancel': 'إلغاء', 'taxZekat.confirm.cancel': 'إلغاء',
'taxZekat.confirm.confirm': 'تأكيد', 'taxZekat.confirm.confirm': 'تأكيد',
'taxZekat.success': 'تم إرسال {{amount}} HEZ بنجاح. شكراً!', 'taxZekat.success': 'تم إرسال {{amount}} HEZ بنجاح. شكراً!',
// Messaging
'messaging.palletNotReady': 'حزمة المراسلة غير متاحة بعد على People Chain. يلزم تحديث وقت التشغيل.',
// KurdMedia page
'kurdMedia.title': 'KurdMedia',
'kurdMedia.subtitle': 'الإعلام الرقمي الكردي',
'kurdMedia.channels.title': 'الإعلام الكردي',
'kurdMedia.channels.subtitle': 'الإعلام الكردي',
'kurdMedia.channels.desc': 'البث الرسمي لدولة كردستان الرقمية.',
'kurdMedia.channels.descEn': 'البث الرسمي لـ DKS. تلفزيون، راديو، أخبار والمزيد.',
'kurdMedia.soon': 'قريباً',
'kurdMedia.social.title': 'دعم PezkuwiChain',
'kurdMedia.social.subtitle': 'دعم PezkuwiChain',
'kurdMedia.social.desc': 'تواصل معنا على منصات التواصل الاجتماعي.',
'kurdMedia.social.descEn': 'اطرح أسئلتك، تابع الأخبار وانضم إلى مجتمعنا.',
'kurdMedia.stats.kurds': 'كردي في العالم',
'kurdMedia.stats.hope': 'أمل',
'kurdMedia.banner': 'PezkuwiChain - أول بلوك تشين وطني للأكراد',
'kurdMedia.bannerEn': 'PezkuwiChain - أول بلوك تشين وطني للأكراد',
// Help page
'help.title': 'المساعدة والدعم',
'help.breadcrumb': 'المساعدة والدعم',
'help.desc': 'سيتم إطلاق نظام المساعدة والدعم قريباً.',
'help.descEn': 'The help and support system will be launched soon.',
'help.planned.title': 'الميزات المخططة',
'help.feature.faq': 'الأسئلة الشائعة (FAQ)',
'help.feature.live': 'الدعم المباشر',
'help.feature.guides': 'أدلة المستخدم',
'help.feature.community': 'التواصل مع المجتمع',
'help.whatskurd.title': 'مراسلة WhatsKURD',
'help.whatskurd.desc': 'تواصل معنا عبر نظام المراسلة على البلوك تشين',
}; };
+34
View File
@@ -3747,6 +3747,7 @@ export default {
'messaging.checkingKey': 'کلیلی شفرکردن پشکنین دەکرێت...', 'messaging.checkingKey': 'کلیلی شفرکردن پشکنین دەکرێت...',
'messaging.send': 'بنێرە', 'messaging.send': 'بنێرە',
'messaging.sending': 'دەنێردرێت...', 'messaging.sending': 'دەنێردرێت...',
'messaging.palletNotReady': 'پاڵێتی پەیامگێڕی هێشتا لەسەر People Chain بەردەست نییە. نوێکردنەوەی ڕانتایم پێویستە.',
// Mobile Home Layout // Mobile Home Layout
'mobile.greeting': 'ڕۆژباش', 'mobile.greeting': 'ڕۆژباش',
@@ -3894,4 +3895,37 @@ export default {
'taxZekat.confirm.cancel': 'هەڵوەشاندنەوە', 'taxZekat.confirm.cancel': 'هەڵوەشاندنەوە',
'taxZekat.confirm.confirm': 'پشتڕاست', 'taxZekat.confirm.confirm': 'پشتڕاست',
'taxZekat.success': '{{amount}} HEZ بە سەرکەوتوویی نێردرا. سوپاس!', 'taxZekat.success': '{{amount}} HEZ بە سەرکەوتوویی نێردرا. سوپاس!',
// Messaging
'messaging.palletNotReady': 'پاڵێتی پەیامگێڕی هێشتا لەسەر People Chain بەردەست نییە. نوێکردنەوەی ڕانتایم پێویستە.',
// KurdMedia page
'kurdMedia.title': 'KurdMedia',
'kurdMedia.subtitle': 'میدیای دیجیتاڵی کوردی',
'kurdMedia.channels.title': 'میدیای کوردی',
'kurdMedia.channels.subtitle': 'میدیای کوردی',
'kurdMedia.channels.desc': 'وەشانە فەرمییەکانی دەوڵەتی دیجیتاڵی کوردستان.',
'kurdMedia.channels.descEn': 'وەشانە فەرمییەکانی DKS. TV، ڕادیۆ، هەواڵ و زیاتر.',
'kurdMedia.soon': 'بەزووی',
'kurdMedia.social.title': 'پشتیوانی PezkuwiChain',
'kurdMedia.social.subtitle': 'پشتیوانی PezkuwiChain',
'kurdMedia.social.desc': 'پەیوەندیمان پێوە بکەن لەسەر پلاتفۆرمە کۆمەڵایەتییەکان.',
'kurdMedia.social.descEn': 'پرسیارەکانتان بپرسن، هەواڵ بشوێنەوە و بەشداری کۆمەڵگەمان بکەن.',
'kurdMedia.stats.kurds': 'کورد لە جیهاندا',
'kurdMedia.stats.hope': 'هیوا',
'kurdMedia.banner': 'PezkuwiChain - یەکەم بلۆکچێینی نەتەوەیی کوردان',
'kurdMedia.bannerEn': 'PezkuwiChain - یەکەم بلۆکچێینی نەتەوەیی کوردان',
// Help page
'help.title': 'یارمەتی و پشتیوانی',
'help.breadcrumb': 'یارمەتی و پشتیوانی',
'help.desc': 'سیستەمی یارمەتی بەم زووییە دەستی پێدەکات.',
'help.descEn': 'The help and support system will be launched soon.',
'help.planned.title': 'تایبەتمەندییە پلانکراوەکان',
'help.feature.faq': 'پرسیارە زۆرپرسراوەکان (FAQ)',
'help.feature.live': 'پشتیوانی زیندوو',
'help.feature.guides': 'ڕێنماییەکانی بەکارهێنەر',
'help.feature.community': 'پەیوەندی کۆمەڵگە',
'help.whatskurd.title': 'WhatsKURD پەیامگێڕ',
'help.whatskurd.desc': 'لەڕێگەی سیستەمی پەیامگێڕی بلۆکچێیندا پەیوەندیمان پێوە بکە',
}; };
+49 -1
View File
@@ -3037,11 +3037,25 @@ export default {
'docs.loading': 'Loading...', 'docs.loading': 'Loading...',
'docs.error': 'Error:', 'docs.error': 'Error:',
'docs.title': 'PezkuwiChain Documentation', 'docs.title': 'PezkuwiChain Documentation',
'docs.subtitle': 'Learn how to build on PezkuwiChain', 'docs.subtitle': 'Everything you need to build on the Kurdish national blockchain',
'docs.selectDoc': 'Select a document from the sidebar to get started.', 'docs.selectDoc': 'Select a document from the sidebar to get started.',
'docs.introduction': 'Introduction', 'docs.introduction': 'Introduction',
'docs.sdkDocs': 'SDK Docs', 'docs.sdkDocs': 'SDK Docs',
'docs.whitepaper': 'Whitepaper', 'docs.whitepaper': 'Whitepaper',
'docs.fullDocsNote': 'For complete and up-to-date documentation, visit the official documentation portal.',
'docs.visitFullDocs': 'Visit docs.pezkuwichain.io',
'docs.section.whitepaper': 'Whitepaper',
'docs.section.whitepaper.desc': 'The foundational document describing the PezkuwiChain vision, architecture, and tokenomics.',
'docs.section.architecture': 'Architecture',
'docs.section.architecture.desc': 'Technical deep-dive into the blockchain architecture, consensus, pallets, and relay chain.',
'docs.section.gettingStarted': 'Getting Started',
'docs.section.gettingStarted.desc': 'Set up your wallet, get test tokens from the faucet, and make your first transaction.',
'docs.section.nodeSetup': 'Node Setup',
'docs.section.nodeSetup.desc': 'Run a validator or full node on PezkuwiChain mainnet, testnet or local environment.',
'docs.section.sdk': 'SDK Reference',
'docs.section.sdk.desc': 'JavaScript/TypeScript SDK for building dApps on PezkuwiChain — API reference and examples.',
'docs.section.contributing': 'Contributor Guide',
'docs.section.contributing.desc': 'How to contribute to PezkuwiChain — code, documentation, translations, and governance.',
// Wiki // Wiki
'wiki.title': 'Community Wiki', 'wiki.title': 'Community Wiki',
@@ -3795,6 +3809,7 @@ export default {
'messaging.checkingKey': 'Checking encryption key...', 'messaging.checkingKey': 'Checking encryption key...',
'messaging.send': 'Send', 'messaging.send': 'Send',
'messaging.sending': 'Sending...', 'messaging.sending': 'Sending...',
'messaging.palletNotReady': 'Messaging pallet is not yet available on People Chain. A runtime upgrade is required.',
// Mobile Home Layout // Mobile Home Layout
'mobile.greeting': 'Rojbaş', 'mobile.greeting': 'Rojbaş',
@@ -3942,4 +3957,37 @@ export default {
'taxZekat.confirm.cancel': 'Cancel', 'taxZekat.confirm.cancel': 'Cancel',
'taxZekat.confirm.confirm': 'Confirm', 'taxZekat.confirm.confirm': 'Confirm',
'taxZekat.success': '{{amount}} HEZ sent successfully. Thank you!', 'taxZekat.success': '{{amount}} HEZ sent successfully. Thank you!',
// Messaging
'messaging.palletNotReady': 'Messaging pallet is not yet available on People Chain. A runtime upgrade is required.',
// KurdMedia page
'kurdMedia.title': 'KurdMedia',
'kurdMedia.subtitle': 'Kurdish Digital Media',
'kurdMedia.channels.title': 'Medyaya Kurdî',
'kurdMedia.channels.subtitle': 'Kurdish Media',
'kurdMedia.channels.desc': 'Weşanên fermî yên Dewleta Dijîtal a Kurdistanê.',
'kurdMedia.channels.descEn': 'Official broadcasts of Digital Kurdistan State. TV, radio, news and more.',
'kurdMedia.soon': 'Soon',
'kurdMedia.social.title': 'Piştgirî PezkuwiChain',
'kurdMedia.social.subtitle': 'Support PezkuwiChain',
'kurdMedia.social.desc': 'Bi me re têkildar bin li ser platformên civakî.',
'kurdMedia.social.descEn': 'Connect with us on social platforms. Ask questions, follow news and join our community.',
'kurdMedia.stats.kurds': 'Kurds worldwide',
'kurdMedia.stats.hope': 'Hope',
'kurdMedia.banner': "PezkuwiChain - Blockchain'a yekem a netewî ya Kurdan",
'kurdMedia.bannerEn': 'PezkuwiChain - The first national blockchain of the Kurds',
// Help page
'help.title': 'Help & Support',
'help.breadcrumb': 'Help & Support',
'help.desc': 'Sîstema arîkariyê dê di demeke nêzîk de were destpêkirin.',
'help.descEn': 'The help and support system will be launched soon.',
'help.planned.title': 'Planned Features',
'help.feature.faq': 'Frequently Asked Questions (FAQ)',
'help.feature.live': 'Live Support',
'help.feature.guides': 'User Guides',
'help.feature.community': 'Community Contact',
'help.whatskurd.title': 'WhatsKURD Messaging',
'help.whatskurd.desc': 'Contact us via the blockchain messaging system',
} }
+34
View File
@@ -3791,6 +3791,7 @@ export default {
'messaging.checkingKey': 'بررسی کلید رمزنگاری...', 'messaging.checkingKey': 'بررسی کلید رمزنگاری...',
'messaging.send': 'ارسال', 'messaging.send': 'ارسال',
'messaging.sending': 'در حال ارسال...', 'messaging.sending': 'در حال ارسال...',
'messaging.palletNotReady': 'پالت پیام‌رسانی هنوز در People Chain موجود نیست. یک به‌روزرسانی runtime لازم است.',
// Mobile Home Layout // Mobile Home Layout
'mobile.greeting': 'سلام', 'mobile.greeting': 'سلام',
@@ -3938,4 +3939,37 @@ export default {
'taxZekat.confirm.cancel': 'لغو', 'taxZekat.confirm.cancel': 'لغو',
'taxZekat.confirm.confirm': 'تأیید', 'taxZekat.confirm.confirm': 'تأیید',
'taxZekat.success': '{{amount}} HEZ با موفقیت ارسال شد. ممنون!', 'taxZekat.success': '{{amount}} HEZ با موفقیت ارسال شد. ممنون!',
// Messaging
'messaging.palletNotReady': 'پالت پیام‌رسانی هنوز در People Chain موجود نیست. یک به‌روزرسانی runtime لازم است.',
// KurdMedia page
'kurdMedia.title': 'KurdMedia',
'kurdMedia.subtitle': 'رسانه دیجیتال کردی',
'kurdMedia.channels.title': 'رسانه کردی',
'kurdMedia.channels.subtitle': 'رسانه کردی',
'kurdMedia.channels.desc': 'پخش رسمی دولت دیجیتال کردستان.',
'kurdMedia.channels.descEn': 'پخش رسمی DKS. تلویزیون، رادیو، اخبار و بیشتر.',
'kurdMedia.soon': 'به‌زودی',
'kurdMedia.social.title': 'حمایت از PezkuwiChain',
'kurdMedia.social.subtitle': 'حمایت از PezkuwiChain',
'kurdMedia.social.desc': 'در شبکه‌های اجتماعی با ما در ارتباط باشید.',
'kurdMedia.social.descEn': 'سوالات خود را بپرسید، اخبار را دنبال کنید و به جامعه ما بپیوندید.',
'kurdMedia.stats.kurds': 'کرد در جهان',
'kurdMedia.stats.hope': 'امید',
'kurdMedia.banner': 'PezkuwiChain - اولین بلاک‌چین ملی کردها',
'kurdMedia.bannerEn': 'PezkuwiChain - اولین بلاک‌چین ملی کردها',
// Help page
'help.title': 'کمک و پشتیبانی',
'help.breadcrumb': 'کمک و پشتیبانی',
'help.desc': 'سیستم کمک و پشتیبانی به‌زودی راه‌اندازی می‌شود.',
'help.descEn': 'The help and support system will be launched soon.',
'help.planned.title': 'ویژگی‌های برنامه‌ریزی‌شده',
'help.feature.faq': 'سوالات متداول (FAQ)',
'help.feature.live': 'پشتیبانی زنده',
'help.feature.guides': 'راهنمای کاربران',
'help.feature.community': 'ارتباط با جامعه',
'help.whatskurd.title': 'پیام‌رسانی WhatsKURD',
'help.whatskurd.desc': 'از طریق سیستم پیام‌رسانی بلاک‌چین با ما تماس بگیرید',
}; };
+34
View File
@@ -3774,6 +3774,7 @@ export default {
'messaging.checkingKey': 'Mifteya şîfrekirinê tê kontrol kirin...', 'messaging.checkingKey': 'Mifteya şîfrekirinê tê kontrol kirin...',
'messaging.send': 'Bişîne', 'messaging.send': 'Bişîne',
'messaging.sending': 'Tê şandin...', 'messaging.sending': 'Tê şandin...',
'messaging.palletNotReady': 'Pergala peyamgehê hîn li ser People Chain tune ye. Nûvekirina runtime lazim e.',
// Mobile Home Layout // Mobile Home Layout
'mobile.greeting': 'Rojbaş', 'mobile.greeting': 'Rojbaş',
@@ -3921,4 +3922,37 @@ export default {
'taxZekat.confirm.cancel': 'Betal', 'taxZekat.confirm.cancel': 'Betal',
'taxZekat.confirm.confirm': 'Piştrast', 'taxZekat.confirm.confirm': 'Piştrast',
'taxZekat.success': '{{amount}} HEZ bi serfirazî hate şandin. Spas!', 'taxZekat.success': '{{amount}} HEZ bi serfirazî hate şandin. Spas!',
// Messaging
'messaging.palletNotReady': 'Pergala peyamgehê hîn li ser People Chain tune ye. Nûvekirina runtime lazim e.',
// KurdMedia page
'kurdMedia.title': 'KurdMedia',
'kurdMedia.subtitle': 'Medyaya Dîjîtal a Kurdî',
'kurdMedia.channels.title': 'Medyaya Kurdî',
'kurdMedia.channels.subtitle': 'Medyaya Kurdî',
'kurdMedia.channels.desc': 'Weşanên fermî yên Dewleta Dijîtal a Kurdistanê.',
'kurdMedia.channels.descEn': 'Weşanên fermî yên DKS. TV, radyo, nûçe û zêdetir.',
'kurdMedia.soon': 'Zû tê',
'kurdMedia.social.title': 'Piştgirî PezkuwiChain',
'kurdMedia.social.subtitle': 'Piştgirî PezkuwiChain',
'kurdMedia.social.desc': 'Bi me re têkildar bin li ser platformên civakî.',
'kurdMedia.social.descEn': 'Bi pirsên xwe, nûçeyan bişopînin û tevlî civaka me bibin.',
'kurdMedia.stats.kurds': 'Kurd li cîhanê',
'kurdMedia.stats.hope': 'Hêvî',
'kurdMedia.banner': "PezkuwiChain - Blockchain'a yekem a netewî ya Kurdan",
'kurdMedia.bannerEn': 'PezkuwiChain - Yekem blockchain netewî ya Kurdan',
// Help page
'help.title': 'Arîkarî û Piştgirî',
'help.breadcrumb': 'Arîkarî û Piştgirî',
'help.desc': 'Sîstema arîkariyê dê di demeke nêzîk de were destpêkirin.',
'help.descEn': 'The help and support system will be launched soon.',
'help.planned.title': 'Taybetmendiyên Plankirin',
'help.feature.faq': 'Pirsên pir tên pirsîn (FAQ)',
'help.feature.live': 'Piştgiriya zindî',
'help.feature.guides': 'Rêberên bikarhêner',
'help.feature.community': 'Têkiliya civakê',
'help.whatskurd.title': 'WhatsKURD Peyamgeh',
'help.whatskurd.desc': 'Bi pergala peyamgehê ya blockchain re bi me re têkildar bibe',
}; };
+34
View File
@@ -3777,6 +3777,7 @@ export default {
'messaging.checkingKey': 'Şifreleme anahtarı kontrol ediliyor...', 'messaging.checkingKey': 'Şifreleme anahtarı kontrol ediliyor...',
'messaging.send': 'Gönder', 'messaging.send': 'Gönder',
'messaging.sending': 'Gönderiliyor...', 'messaging.sending': 'Gönderiliyor...',
'messaging.palletNotReady': 'Mesajlaşma paleti henüz People Chain üzerinde mevcut değil. Bir runtime güncellemesi gerekiyor.',
// Mobile Home Layout // Mobile Home Layout
'mobile.greeting': 'Rojbaş', 'mobile.greeting': 'Rojbaş',
@@ -3924,4 +3925,37 @@ export default {
'taxZekat.confirm.cancel': 'İptal', 'taxZekat.confirm.cancel': 'İptal',
'taxZekat.confirm.confirm': 'Onayla', 'taxZekat.confirm.confirm': 'Onayla',
'taxZekat.success': '{{amount}} HEZ başarıyla gönderildi. Teşekkürler!', 'taxZekat.success': '{{amount}} HEZ başarıyla gönderildi. Teşekkürler!',
// Messaging
'messaging.palletNotReady': 'Mesajlaşma paleti henüz People Chain üzerinde mevcut değil. Bir runtime güncellemesi gerekiyor.',
// KurdMedia page
'kurdMedia.title': 'KurdMedia',
'kurdMedia.subtitle': 'Kürt Dijital Medyası',
'kurdMedia.channels.title': 'Kürt Medyası',
'kurdMedia.channels.subtitle': 'Kürt Medyası',
'kurdMedia.channels.desc': 'Dijital Kürdistan Devleti\'nin resmi yayınları.',
'kurdMedia.channels.descEn': 'DKS\'nin resmi yayınları. TV, radyo, haberler ve daha fazlası.',
'kurdMedia.soon': 'Yakında',
'kurdMedia.social.title': 'PezkuwiChain\'i Destekle',
'kurdMedia.social.subtitle': 'PezkuwiChain\'i Destekle',
'kurdMedia.social.desc': 'Sosyal platformlarda bizimle iletişime geçin.',
'kurdMedia.social.descEn': 'Sorularınızı sorun, haberleri takip edin ve topluluğumuza katılın.',
'kurdMedia.stats.kurds': 'Dünyada Kürt',
'kurdMedia.stats.hope': 'Umut',
'kurdMedia.banner': 'PezkuwiChain - Kürtlerin ilk ulusal blockchain\'i',
'kurdMedia.bannerEn': 'PezkuwiChain - Kürtlerin ilk ulusal blockchain\'i',
// Help page
'help.title': 'Yardım ve Destek',
'help.breadcrumb': 'Yardım ve Destek',
'help.desc': 'Yardım ve destek sistemi yakında başlatılacak.',
'help.descEn': 'The help and support system will be launched soon.',
'help.planned.title': 'Planlanan Özellikler',
'help.feature.faq': 'Sıkça Sorulan Sorular (SSS)',
'help.feature.live': 'Canlı Destek',
'help.feature.guides': 'Kullanıcı Rehberleri',
'help.feature.community': 'Topluluk İletişimi',
'help.whatskurd.title': 'WhatsKURD Mesajlaşma',
'help.whatskurd.desc': 'Blockchain mesajlaşma sistemi aracılığıyla bizimle iletişime geçin',
}; };
+143 -295
View File
@@ -1,311 +1,159 @@
import React, { useState, useEffect, useMemo } from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useParams, useNavigate, Link } from 'react-router-dom'; import { ExternalLink } from 'lucide-react';
import Layout from '@/components/Layout'; import Layout from '@/components/Layout';
import { marked } from 'marked';
import { ChevronRight, Book, ExternalLink } from 'lucide-react';
import DOMPurify from 'dompurify';
// SDK Embedded View - shown inline in the content area (window in window style) const DOCS_URL = 'https://docs.pezkuwichain.io';
const SDKEmbeddedView: React.FC = () => {
const sdkUrl = '/sdk_docs/pezkuwi_sdk_docs/index.html';
return ( const DOC_SECTIONS = [
<div className="flex flex-col h-full min-h-[600px]"> {
{/* SDK Panel Header */} icon: '📄',
<div className="flex items-center gap-3 px-4 py-3 bg-gray-800 rounded-t-lg border border-gray-700 border-b-0"> titleKey: 'docs.section.whitepaper',
<img title: 'Whitepaper',
src="/pezkuwi_icon.png" descKey: 'docs.section.whitepaper.desc',
alt="Pezkuwi" desc: 'The foundational document describing the PezkuwiChain vision, architecture, and tokenomics.',
className="w-8 h-8 rounded" path: '/whitepaper',
/> color: 'bg-green-900/30 border-green-700/40',
<div> iconBg: 'bg-green-800',
<h3 className="text-white font-semibold">pezkuwi_sdk_docs</h3> },
<span className="text-gray-400 text-xs">0.0.1</span> {
</div> icon: '🏛️',
<div className="ml-auto flex items-center gap-2"> titleKey: 'docs.section.architecture',
<a title: 'Architecture',
href={sdkUrl} descKey: 'docs.section.architecture.desc',
target="_blank" desc: 'Technical deep-dive into the blockchain architecture, consensus, pallets, and relay chain.',
rel="noopener noreferrer" path: '/architecture',
className="p-2 hover:bg-gray-700 rounded-md transition-colors text-gray-400 hover:text-white" color: 'bg-blue-900/30 border-blue-700/40',
title="Open in new tab" iconBg: 'bg-blue-800',
> },
<ExternalLink size={16} /> {
</a> icon: '🚀',
</div> titleKey: 'docs.section.gettingStarted',
</div> title: 'Getting Started',
{/* SDK Docs iframe */} descKey: 'docs.section.gettingStarted.desc',
<div className="flex-1 border border-gray-700 rounded-b-lg overflow-hidden bg-white"> desc: 'Set up your wallet, get test tokens from the faucet, and make your first transaction.',
<iframe path: '/getting-started',
src={sdkUrl} color: 'bg-yellow-900/30 border-yellow-700/40',
title="Pezkuwi SDK Documentation" iconBg: 'bg-yellow-800',
className="w-full h-full border-0" },
style={{ minHeight: '550px' }} {
/> icon: '⚙️',
</div> titleKey: 'docs.section.nodeSetup',
</div> title: 'Node Setup',
); descKey: 'docs.section.nodeSetup.desc',
}; desc: 'Run a validator or full node on PezkuwiChain mainnet, testnet or local environment.',
path: '/node-setup',
const SidebarNav: React.FC<{ structure: object, onLinkClick: () => void, onSDKClick: () => void }> = ({ structure, onLinkClick, onSDKClick }) => { color: 'bg-purple-900/30 border-purple-700/40',
const [openCategories, setOpenCategories] = useState<string[]>(['Getting Started', 'SDK Reference', 'General Docs', 'Contributor Guide']); iconBg: 'bg-purple-800',
},
const toggleCategory = (category: string) => { {
setOpenCategories(prev => icon: '🛠️',
prev.includes(category) titleKey: 'docs.section.sdk',
? prev.filter(c => c !== category) title: 'SDK Reference',
: [...prev, category] descKey: 'docs.section.sdk.desc',
); desc: 'JavaScript/TypeScript SDK for building dApps on PezkuwiChain — API reference and examples.',
}; path: '/sdk',
color: 'bg-cyan-900/30 border-cyan-700/40',
const renderNav = (struct: Record<string, unknown>) => { iconBg: 'bg-cyan-800',
return Object.entries(struct).map(([key, value]) => { },
if (typeof value === 'string') { {
// Check if it's the SDK docs special link icon: '🤝',
const isSDKLink = value === 'sdk://open'; titleKey: 'docs.section.contributing',
title: 'Contributor Guide',
if (isSDKLink) { descKey: 'docs.section.contributing.desc',
return ( desc: 'How to contribute to PezkuwiChain — code, documentation, translations, and governance.',
<li key={key}> path: '/contributing',
<button color: 'bg-red-900/30 border-red-700/40',
onClick={() => { iconBg: 'bg-red-800',
onSDKClick(); },
}} ];
className="w-full text-left block py-1 px-2 rounded-md hover:bg-gray-700 transition-colors font-bold text-green-400 hover:text-green-300 flex items-center gap-2"
>
{key}
</button>
</li>
);
}
const path = value.replace(/\.(md|rs)$/, '');
return (
<li key={path}>
<Link
to={`/docs/${path}`}
onClick={onLinkClick}
className="block py-1 px-2 rounded-md hover:bg-gray-700 transition-colors text-gray-300 hover:text-white"
>
{key}
</Link>
</li>
);
} else {
const isExpanded = openCategories.includes(key);
return (
<li key={key}>
<div
onClick={() => toggleCategory(key)}
className="flex justify-between items-center cursor-pointer py-2 px-2 rounded-md hover:bg-gray-700"
>
<span className="font-semibold text-white">{key}</span>
<ChevronRight size={16} className={`transform transition-transform text-gray-400 ${isExpanded ? 'rotate-90' : ''}`} />
</div>
{isExpanded && (
<ul className="pl-4 border-l border-gray-600 ml-2">
{renderNav(value)}
</ul>
)}
</li>
);
}
});
};
return <nav><ul className="space-y-1">{renderNav(structure)}</ul></nav>;
};
const QUICK_LINKS = [
{ label: 'Mainnet RPC', value: 'wss://rpc.pezkuwichain.io' },
{ label: 'Explorer', value: 'explorer.pezkuwichain.io', href: 'https://explorer.pezkuwichain.io' },
{ label: 'Faucet', value: 'app.pezkuwichain.io/faucet', href: '/faucet' },
{ label: 'GitHub', value: 'github.com/pezkuwichain', href: 'https://github.com/pezkuwichain' },
];
const Docs: React.FC = () => { const Docs: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { '*': splat } = useParams();
const navigate = useNavigate();
const [docStructure, setDocStructure] = useState<object | null>(null);
const [content, setContent] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [showSDKLanding, setShowSDKLanding] = useState(false);
// Fetch the documentation structure return (
useEffect(() => { <Layout>
fetch('/docs-structure.json') <div className="max-w-4xl mx-auto px-4 py-10">
.then(res => {
if (!res.ok) {
throw new Error('Failed to load documentation structure.');
}
return res.json();
})
.then(data => setDocStructure(data))
.catch(e => setError(e.message));
}, []);
const filePath = useMemo(() => { {/* Hero */}
// If no splat, and the structure is loaded, default to the introduction markdown <div className="text-center mb-10">
if (!splat && docStructure) { <div className="text-6xl mb-4">📖</div>
const defaultEntry = docStructure['Introduction']; <h1 className="text-3xl font-bold text-white mb-2">
if (typeof defaultEntry === 'string') { {t('docs.title', 'PezkuwiChain Documentation')}
return defaultEntry; </h1>
} <p className="text-gray-400 text-lg">
} else if (splat) { {t('docs.subtitle', 'Everything you need to build on the Kurdish national blockchain')}
// Check if it's an SDK link which is an HTML file </p>
if (splat.startsWith('sdk_docs/') && splat.endsWith('html')) { </div>
return splat; // Treat as direct path, no .md or .rs append
}
return `${splat}.md`; // For .md or .rs files
}
return null; // No file selected, no default provided yet
}, [splat, docStructure]);
// If no splat and no default, avoid fetching content {/* Quick Links */}
const shouldFetchContent = !!filePath && !filePath.startsWith('sdk_docs/'); // Do not fetch content if it's an external SDK link <div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-10">
{QUICK_LINKS.map(link => (
<a
key={link.label}
href={link.href ?? '#'}
target={link.href?.startsWith('http') ? '_blank' : undefined}
rel="noopener noreferrer"
className="bg-gray-800 rounded-xl p-3 hover:bg-gray-700 transition-colors border border-gray-700"
>
<p className="text-xs text-gray-400 mb-1">{link.label}</p>
<p className="text-xs text-green-400 font-mono truncate">{link.value}</p>
</a>
))}
</div>
useEffect(() => { {/* Documentation Sections */}
if (!shouldFetchContent) { <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-10">
setContent(''); // Clear content if not fetching {DOC_SECTIONS.map(section => (
setError(null); <a
setIsLoading(false); key={section.path}
return; href={`${DOCS_URL}${section.path}`}
} target="_blank"
rel="noopener noreferrer"
className={`flex gap-4 p-4 rounded-2xl border ${section.color} hover:opacity-90 transition-opacity cursor-pointer`}
>
<div className={`w-12 h-12 ${section.iconBg} rounded-xl flex items-center justify-center text-2xl flex-shrink-0`}>
{section.icon}
</div>
<div className="flex-1 min-w-0">
<h2 className="font-bold text-white text-sm mb-1">
{t(section.titleKey, section.title)}
</h2>
<p className="text-xs text-gray-400 leading-relaxed">
{t(section.descKey, section.desc)}
</p>
</div>
<ExternalLink size={14} className="text-gray-500 flex-shrink-0 mt-1" />
</a>
))}
</div>
const fetchContent = async () => { {/* Full Docs Button */}
setIsLoading(true); <div className="text-center">
setError(null); <p className="text-gray-500 text-sm mb-4">
try { {t('docs.fullDocsNote', 'For complete and up-to-date documentation, visit the official documentation portal.')}
const response = await fetch(`/docs/${filePath}`); </p>
if (!response.ok) { <a
throw new Error(`Documentation file not found: ${filePath}`); href={DOCS_URL}
} target="_blank"
let text = await response.text(); rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-6 py-3 bg-green-600 hover:bg-green-500 text-white font-semibold rounded-xl transition-colors text-sm"
>
<ExternalLink size={16} />
{t('docs.visitFullDocs', 'Visit docs.pezkuwichain.io')}
</a>
</div>
// If the file is a Rust file, wrap it in a markdown code block </div>
if (filePath.endsWith('.rs')) { </Layout>
text = '```rust\n' + text + '\n```'; );
}
const renderer = new marked.Renderer();
renderer.image = (href, title, text) => {
try {
// The base URL for the markdown file itself
const base = new URL(`/docs/${filePath}`, window.location.origin);
// Resolve the image's relative path against the markdown file's path
const imageUrl = new URL(href, base);
// Return the final path part of the URL
return `<img src="${imageUrl.pathname}" alt="${text}" title="${title || ''}" />`;
} catch (e) {
console.error("Error processing image URL:", e);
// Fallback to the original href if URL construction fails
return `<img src="${href}" alt="${text}" title="${title || ''}" />`;
}
};
marked.setOptions({ renderer });
const parsed = await marked.parse(text);
const sanitized = DOMPurify.sanitize(parsed);
setContent(sanitized);
} catch (e: unknown) {
setError(e instanceof Error ? e.message : 'Unknown error');
setContent('');
} finally {
setIsLoading(false);
}
};
fetchContent();
}, [filePath, shouldFetchContent]); // Dependency array
// Check if we're on SDK route
const isSDKRoute = splat === 'sdk';
return (
<Layout>
<div className="flex h-full overflow-hidden">
{/* Sidebar */}
<aside
className={`fixed lg:static top-16 left-0 h-full lg:h-auto z-30 w-64 bg-gray-800 lg:bg-transparent lg:w-1/4 lg:pr-8 py-4 transition-transform transform ${isSidebarOpen ? 'translate-x-0' : '-translate-x-full'} lg:translate-x-0`}
>
<div className="px-4">
{docStructure ? (
<SidebarNav
structure={docStructure}
onLinkClick={() => {
setIsSidebarOpen(false);
setShowSDKLanding(false); // Clear SDK landing when navigating to other docs
}}
onSDKClick={() => {
setIsSidebarOpen(false);
setShowSDKLanding(true); // Show SDK landing
setContent(''); // Clear any markdown content
navigate('/docs/sdk');
}}
/>
) : (
<p className="text-gray-400">{t('docs.loadingNav')}</p>
)}
</div>
</aside>
{/* Mobile Sidebar Toggle */}
<button
className="fixed bottom-4 right-4 lg:hidden w-12 h-12 bg-green-600 rounded-full z-40 flex items-center justify-center text-white shadow-lg"
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
>
<Book size={24} />
</button>
{/* Main Content */}
<main className="w-full lg:w-3/4 lg:pl-8 flex flex-col">
<div className="prose prose-invert prose-headings:text-cyan-400 prose-a:text-blue-400 hover:prose-a:text-blue-300 prose-code:text-yellow-400 prose-pre:bg-gray-800 prose-pre:p-4 prose-pre:rounded-md max-w-none flex-1 min-h-0">
{isLoading && <p className="text-gray-400">{t('docs.loading')}</p>}
{error && <p className="text-red-400">{t('docs.error')} {error}</p>}
{/* SDK Embedded View - window in window style */}
{(showSDKLanding || isSDKRoute) && (
<SDKEmbeddedView />
)}
{/* Regular Markdown Content */}
{!isLoading && !error && content && !showSDKLanding && !isSDKRoute && (
<div dangerouslySetInnerHTML={{ __html: content }} />
)}
{/* Default Welcome */}
{!isLoading && !error && !content && !splat && !showSDKLanding && (
<div className="text-center py-12">
<div className="mb-8">
<div className="text-6xl mb-4">📖</div>
<h1 className="text-3xl font-bold text-white mb-2">{t('docs.title')}</h1>
<p className="text-lg text-gray-400">{t('docs.subtitle')}</p>
</div>
<p className="text-xl text-gray-400 mb-4">
{t('docs.selectDoc')}
</p>
<div className="flex flex-wrap gap-4 justify-center mt-8">
<Link to="/docs/GENESIS_ENGINEERING_PLAN" className="px-4 py-2 bg-green-600 hover:bg-green-500 text-white rounded-lg transition-colors">
{t('docs.introduction')}
</Link>
<Link
to="/docs/sdk"
onClick={() => setShowSDKLanding(true)}
className="px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg transition-colors"
>
{t('docs.sdkDocs')}
</Link>
<Link to="/docs/whitepaper/whitepaper" className="px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg transition-colors">
{t('docs.whitepaper')}
</Link>
</div>
</div>
)}
</div>
</main>
</div>
</Layout>
);
}; };
export default Docs; export default Docs;
+73
View File
@@ -0,0 +1,73 @@
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
export default function HelpPage() {
const navigate = useNavigate();
const { t } = useTranslation();
const features = [
{ icon: '❓', label: t('help.feature.faq', 'Frequently Asked Questions (FAQ)') },
{ icon: '💬', label: t('help.feature.live', 'Live Support') },
{ icon: '📖', label: t('help.feature.guides', 'User Guides') },
{ icon: '🤝', label: t('help.feature.community', 'Community Contact') },
];
return (
<div className="min-h-screen bg-gray-100 text-gray-800">
{/* Header */}
<div className="bg-green-700 px-4 pt-4 pb-5">
<div className="flex items-center gap-3 mb-4">
<button onClick={() => navigate(-1)} className="text-white/80 hover:text-white text-xl leading-none"></button>
<span className="text-sm text-white/70">{t('help.breadcrumb', 'Help & Support')}</span>
</div>
<div className="text-center">
<span className="text-5xl block mb-2">🤝</span>
<h1 className="text-2xl font-bold text-white">{t('help.title', 'Help & Support')}</h1>
</div>
</div>
<div className="px-4 py-6 space-y-4 max-w-lg mx-auto">
{/* Coming Soon Card */}
<div className="bg-white rounded-2xl p-6 text-center shadow-sm">
<p className="text-base text-gray-600 leading-relaxed mb-2">
{t('help.desc', 'Sîstema arîkariyê dê di demeke nêzîk de were destpêkirin.')}
</p>
<p className="text-sm text-gray-400">
{t('help.descEn', 'The help and support system will be launched soon.')}
</p>
</div>
{/* Planned Features */}
<div className="bg-white rounded-2xl p-4 shadow-sm">
<h2 className="font-bold text-green-700 mb-3 text-sm">
{t('help.planned.title', 'Taybetmendiyên Plankirin / Planned Features')}
</h2>
<div className="space-y-3">
{features.map((f, i) => (
<div key={i} className="flex items-center gap-3 p-3 bg-gray-50 rounded-xl">
<span className="text-2xl flex-shrink-0">{f.icon}</span>
<span className="text-sm text-gray-700">{f.label}</span>
</div>
))}
</div>
</div>
{/* Contact via WhatsKURD */}
<div
onClick={() => navigate('/social/whatskurd')}
className="bg-green-700 text-white rounded-2xl p-4 flex items-center gap-3 cursor-pointer active:opacity-80"
>
<span className="text-2xl">💬</span>
<div>
<p className="font-semibold text-sm">{t('help.whatskurd.title', 'WhatsKURD Messaging')}</p>
<p className="text-xs text-white/70">{t('help.whatskurd.desc', 'Contact us via the blockchain messaging system')}</p>
</div>
<span className="ml-auto text-white/60"></span>
</div>
</div>
<div className="h-10" />
</div>
);
}
+150
View File
@@ -0,0 +1,150 @@
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
interface MediaChannel {
id: string;
nameKu: string;
name: string;
icon: string;
descriptionKu: string;
description: string;
color: string;
}
interface SocialPlatform {
id: string;
name: string;
icon: string;
url: string;
color: string;
}
const MEDIA_CHANNELS: MediaChannel[] = [
{ id: 'dkstv', nameKu: 'DKS TV', name: 'DKS TV', icon: '📺', descriptionKu: 'Televizyona Dewleta Dijîtal a Kurdistanê', description: 'Digital Kurdistan State Television', color: '#E53935' },
{ id: 'dksgzt', nameKu: 'DKS Rojname', name: 'DKS Gazette', icon: '📰', descriptionKu: 'Nûçe û Daxuyaniyên Fermî', description: 'Official News & Announcements', color: '#1E88E5' },
{ id: 'dksradio', nameKu: 'DKS Radyo', name: 'DKS Radio', icon: '📻', descriptionKu: 'Radyoya Dewleta Dijîtal a Kurdistanê', description: 'Digital Kurdistan State Radio', color: '#7B1FA2' },
{ id: 'dksmusic', nameKu: 'DKS Muzîk', name: 'DKS Music', icon: '🎵', descriptionKu: 'Weşana Muzîka Kurdî', description: 'Kurdish Music Streaming', color: '#00897B' },
{ id: 'dkspodcast',nameKu: 'DKS Podcast', name: 'DKS Podcast', icon: '🎙️', descriptionKu: 'Podcast û Gotûbêjên Kurdî', description: 'Kurdish Podcasts & Talks', color: '#F4511E' },
{ id: 'dksdocs', nameKu: 'DKS Belgefîlm', name: 'DKS Docs', icon: '🎬', descriptionKu: 'Belgefîlm û Fîlim', description: 'Documentaries & Films', color: '#6D4C41' },
];
const SOCIAL_PLATFORMS: SocialPlatform[] = [
{ id: 'telegram', name: 'Telegram', icon: '✈️', url: 'https://t.me/pezkuwichain', color: '#0088CC' },
{ id: 'discord', name: 'Discord', icon: '💬', url: 'https://discord.gg/Y3VyEC6h8W', color: '#5865F2' },
{ id: 'twitter', name: 'X', icon: '🐦', url: 'https://twitter.com/pezkuwichain', color: '#1DA1F2' },
{ id: 'facebook', name: 'Facebook', icon: '📘', url: 'https://www.facebook.com/profile.php?id=61582484611719', color: '#1877F2' },
{ id: 'medium', name: 'Medium', icon: '📝', url: 'https://medium.com/@pezkuwichain', color: '#555555' },
{ id: 'github', name: 'GitHub', icon: '💻', url: 'https://github.com/pezkuwichain', color: '#333333' },
];
export default function KurdMediaPage() {
const navigate = useNavigate();
const { t } = useTranslation();
return (
<div className="min-h-screen bg-gray-950 text-white">
{/* Header */}
<div className="bg-green-700 px-4 pt-4 pb-5">
<div className="flex items-center gap-3 mb-4">
<button onClick={() => navigate(-1)} className="text-white/80 hover:text-white text-xl leading-none"></button>
<span className="text-sm text-white/70">{t('mobile.section.social', 'Social')}</span>
</div>
<div className="text-center">
<span className="text-5xl block mb-2">📡</span>
<h1 className="text-2xl font-bold">{t('kurdMedia.title', 'KurdMedia')}</h1>
<p className="text-white/70 text-sm mt-0.5">{t('kurdMedia.subtitle', 'Kurdish Digital Media')}</p>
</div>
</div>
<div className="px-4 py-4 space-y-4 max-w-lg mx-auto">
{/* Media Channels */}
<div>
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-red-600 rounded-xl flex items-center justify-center text-xl flex-shrink-0">📺</div>
<div>
<h2 className="font-bold text-white">{t('kurdMedia.channels.title', 'Medyaya Kurdî')}</h2>
<p className="text-xs text-gray-400">{t('kurdMedia.channels.subtitle', 'Kurdish Media')}</p>
</div>
</div>
<div className="bg-gray-900 rounded-xl p-4">
<p className="text-sm text-gray-300 mb-1">{t('kurdMedia.channels.desc', 'Weşanên fermî yên Dewleta Dijîtal a Kurdistanê.')}</p>
<p className="text-xs text-gray-500 mb-4">{t('kurdMedia.channels.descEn', 'Official broadcasts of Digital Kurdistan State. TV, radio, news and more.')}</p>
<div className="space-y-3">
{MEDIA_CHANNELS.map(ch => (
<div key={ch.id} className="flex items-center gap-3 bg-gray-800 rounded-xl p-3">
<div className="w-12 h-12 rounded-xl flex items-center justify-center text-2xl flex-shrink-0" style={{ backgroundColor: ch.color }}>
{ch.icon}
</div>
<div className="flex-1 min-w-0">
<p className="font-semibold text-white text-sm">{ch.nameKu}</p>
<p className="text-xs text-gray-400 truncate">{ch.descriptionKu}</p>
</div>
<span className="text-[10px] font-bold text-yellow-400 bg-yellow-400/10 px-2 py-1 rounded-full flex-shrink-0">
{t('kurdMedia.soon', 'Soon')}
</span>
</div>
))}
</div>
</div>
</div>
{/* Social Platforms */}
<div>
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-green-700 rounded-xl flex items-center justify-center text-xl flex-shrink-0">🤝</div>
<div>
<h2 className="font-bold text-white">{t('kurdMedia.social.title', 'Piştgirî PezkuwiChain')}</h2>
<p className="text-xs text-gray-400">{t('kurdMedia.social.subtitle', 'Support PezkuwiChain')}</p>
</div>
</div>
<div className="bg-gray-900 rounded-xl p-4">
<p className="text-sm text-gray-300 mb-1">{t('kurdMedia.social.desc', 'Bi me re têkildar bin li ser platformên civakî.')}</p>
<p className="text-xs text-gray-500 mb-4">{t('kurdMedia.social.descEn', 'Connect with us on social platforms. Ask questions, follow news and join our community.')}</p>
<div className="grid grid-cols-3 gap-3 mb-4">
{SOCIAL_PLATFORMS.map(p => (
<a
key={p.id}
href={p.url}
target="_blank"
rel="noopener noreferrer"
className="flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-gray-800 transition-colors"
>
<div className="w-14 h-14 rounded-2xl flex items-center justify-center text-3xl" style={{ backgroundColor: p.color }}>
{p.icon}
</div>
<span className="text-xs text-gray-400 font-medium">{p.name}</span>
</a>
))}
</div>
{/* Stats */}
<div className="grid grid-cols-3 gap-0 bg-gray-800 rounded-xl overflow-hidden">
{[
{ val: '40M+', label: t('kurdMedia.stats.kurds', 'Kurd li cîhanê') },
{ val: '5B', label: 'PEZ Total' },
{ val: '∞', label: t('kurdMedia.stats.hope', 'Hêvî / Hope') },
].map((s, i) => (
<div key={i} className={`py-4 text-center ${i > 0 ? 'border-l border-gray-700' : ''}`}>
<p className="text-xl font-bold text-red-400">{s.val}</p>
<p className="text-[10px] text-gray-500 mt-1">{s.label}</p>
</div>
))}
</div>
</div>
</div>
{/* Info banner */}
<div className="bg-green-900/20 border-l-4 border-green-600 rounded-xl p-4 flex gap-3">
<span className="text-2xl flex-shrink-0">💡</span>
<div>
<p className="text-sm text-green-300 font-medium">{t('kurdMedia.banner', 'PezkuwiChain - Blockchain\'a yekem a netewî ya Kurdan')}</p>
<p className="text-xs text-green-500 mt-1">{t('kurdMedia.bannerEn', 'PezkuwiChain - The first national blockchain of the Kurds')}</p>
</div>
</div>
</div>
<div className="h-10" />
</div>
);
}