7 Commits

Author SHA1 Message Date
pezkuwichain 070d682759 feat(p2p): rename Finance tile to P2P/Buy-Sell + add 'Buy with Visa' nav action
The Finance section tile label becomes 'P2P/Buy-Sell'. In the P2P dashboard's
top nav, next to the Messages icon, a Visa card (CreditCard) action 'Buy with
Visa' opens buy-sell.pezkiwi.app in a new tab. Adds p2pNav.buyVisa in all 6
locales.
2026-06-19 17:37:14 -07:00
pezkuwichain cd56ab8fb6 feat(social): replace Help tile with Loto (Newroz) → loto.pex.mom
In the Social section of both the desktop app grid and the mobile home, the Help
tile becomes a Loto tile with the Newroz flame logo (loto-icon.svg) that opens
loto.pex.mom in a new tab. Adds the mobile.app.loto i18n key in all 6 locales.
Help remains reachable from the landing page.
2026-06-19 17:32:57 -07:00
pezkuwichain b012fcaaac fix(security): patch ws (high DoS) and dompurify (XSS) via npm audit fix
Unblocks the deploy security gate — production deps only, no major bumps.
2026-06-15 18:07:37 -07:00
pezkuwichain 7a1d3e7917 feat(social): wire DKS Rojname → news.pex.mom and Events → kurdishtts.pezkiwi.app
- KurdMedia: DKS Rojname channel now links to the Dijital Kurdistan News site
- Social Events item opens the Kurdish TTS app (was coming-soon/locked)
- applies across mobile drawer, mobile home and desktop landing pallets
2026-06-15 17:54:19 -07:00
pezkuwichain 2ee3caac0d fix(ci): audit only production deps in the deploy gate (--omit=dev) (#18)
The security-audit gate ran 'npm audit --audit-level=high' over all deps,
so newly-published advisories on build-only tooling (esbuild, elliptic via
vite-plugin-node-polyfills, etc.) repeatedly blocked production deploys
even though that code ships to no user. Scope the gate to production
dependencies with --omit=dev. Verified: 'npm audit --audit-level=high
--omit=dev' → 0 vulnerabilities. TruffleHog secret scanning is unchanged.
2026-06-12 23:39:55 -07:00
pezkuwichain 78e93e9766 feat(web): PEZ-20 badge on PEZ & USDT balance cards (#17)
* fix(ci): unblock deploy pipeline (audit gate + orphan submodule)

The Quality Gate & Deploy pipeline was failing at security-audit
(npm audit --audit-level=high), which blocks telegram-gate and the
whole deploy chain — that is why production was serving a stale bundle.

- npm audit fix (no --force, lockfile only): clears the critical vitest
  advisory (GHSA-5xrq-8626-4rwp) and the high elliptic one; only low-
  severity items remain, so 'npm audit --audit-level=high' now exits 0.
- Remove the orphaned 'exchange' gitlink: it is an empty submodule
  pointer with no .gitmodules mapping, which made git print
  'fatal: no submodule mapping found' during checkout.

Verified: lint, test (32 passed), and vite build all pass; audit gate
is green. No package.json changes.

* feat(web): PEZ-20 badge on PEZ and USDT balance cards

Add a small reusable Pez20Badge pill next to the PEZ and USDT tokens in
the wallet balance view, linking to the Token Standards docs. These are
fungible assets on Asset Hub, i.e. the PEZ-20 standard — this gives users
the familiar ERC-20-style mental model at a glance.

Additive only: no labels removed, native HEZ is intentionally not badged
(it is the native/gas token, not a PEZ-20 asset).
2026-06-12 23:28:05 -07:00
pezkuwichain 83d66feacc fix(ci): unblock deploy pipeline (audit gate + orphan submodule) (#16)
The Quality Gate & Deploy pipeline was failing at security-audit
(npm audit --audit-level=high), which blocks telegram-gate and the
whole deploy chain — that is why production was serving a stale bundle.

- npm audit fix (no --force, lockfile only): clears the critical vitest
  advisory (GHSA-5xrq-8626-4rwp) and the high elliptic one; only low-
  severity items remain, so 'npm audit --audit-level=high' now exits 0.
- Remove the orphaned 'exchange' gitlink: it is an empty submodule
  pointer with no .gitmodules mapping, which made git print
  'fatal: no submodule mapping found' during checkout.

Verified: lint, test (32 passed), and vite build all pass; audit gate
is green. No package.json changes.
2026-06-11 18:42:45 -07:00
14 changed files with 149 additions and 34 deletions
+5 -2
View File
@@ -628,11 +628,14 @@ jobs:
with: with:
node-version: '20' node-version: '20'
- name: Web — npm audit (high + critical) - name: Web — npm audit (high + critical, production deps only)
working-directory: ./web working-directory: ./web
run: | run: |
npm install npm install
npm audit --audit-level=high # Audit only production dependencies. Build tooling (vite, esbuild,
# vite-plugin-node-polyfills → elliptic, etc.) ships to no user, and
# advisories on those dev deps kept blocking production deploys.
npm audit --audit-level=high --omit=dev
- name: TruffleHog — PR diff (verified secrets only) - name: TruffleHog — PR diff (verified secrets only)
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
+6 -6
View File
@@ -5457,9 +5457,9 @@
} }
}, },
"node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": {
"version": "7.5.10", "version": "7.5.11",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8.3.0" "node": ">=8.3.0"
@@ -7651,9 +7651,9 @@
} }
}, },
"node_modules/dompurify": { "node_modules/dompurify": {
"version": "3.4.2", "version": "3.4.10",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.10.tgz",
"integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", "integrity": "sha512-0xzNv0e7oYC6yyuOGZIABPM4qtg3QxLFniDNPP4ZP90wR8Yq3zgwpRbrNiT4N3IKqDbbYFEJLV+JWEs19aZ//w==",
"license": "(MPL-2.0 OR Apache-2.0)", "license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": { "optionalDependencies": {
"@types/trusted-types": "^2.0.7" "@types/trusted-types": "^2.0.7"
+72
View File
@@ -0,0 +1,72 @@
<?xml version="1.0"?>
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="fireGradient" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" style="stop-color:#1B5E20;stop-opacity:1"></stop>
<stop offset="30%" style="stop-color:#FF6F00;stop-opacity:1"></stop>
<stop offset="60%" style="stop-color:#FFD600;stop-opacity:1"></stop>
<stop offset="100%" style="stop-color:#D32F2F;stop-opacity:1"></stop>
</linearGradient>
<linearGradient id="innerFlame" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" style="stop-color:#FFD600;stop-opacity:1"></stop>
<stop offset="50%" style="stop-color:#FF8F00;stop-opacity:1"></stop>
<stop offset="100%" style="stop-color:#FF5722;stop-opacity:1"></stop>
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="8" result="coloredBlur"></feGaussianBlur>
<feMerge>
<feMergeNode in="coloredBlur"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<radialGradient id="sunGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" style="stop-color:#FFD600;stop-opacity:0.6"></stop>
<stop offset="100%" style="stop-color:#FFD600;stop-opacity:0"></stop>
</radialGradient>
</defs>
<circle cx="256" cy="256" r="240" fill="#1a1a2e" opacity="0.9"></circle>
<circle cx="256" cy="280" r="180" fill="url(#sunGlow)" filter="url(#glow)"></circle>
<path d="M256 60&#xA; C280 120 340 160 360 220&#xA; C380 280 360 340 340 380&#xA; C320 420 280 460 256 470&#xA; C232 460 192 420 172 380&#xA; C152 340 132 280 152 220&#xA; C172 160 232 120 256 60Z" fill="url(#fireGradient)" filter="url(#glow)">
</path>
<path d="M256 140&#xA; C270 180 310 210 320 260&#xA; C330 310 320 350 300 380&#xA; C280 410 268 430 256 440&#xA; C244 430 232 410 212 380&#xA; C192 350 182 310 192 260&#xA; C202 210 242 180 256 140Z" fill="url(#innerFlame)" opacity="0.95">
</path>
<ellipse cx="256" cy="320" rx="50" ry="80" fill="#FFFDE7" opacity="0.8">
</ellipse>
<circle cx="200" cy="180" r="8" fill="#4CAF50" opacity="0.8">
</circle>
<circle cx="312" cy="200" r="6" fill="#4CAF50" opacity="0.7">
</circle>
<circle cx="230" cy="150" r="5" fill="#81C784" opacity="0.6">
</circle>
<circle cx="280" cy="165" r="7" fill="#66BB6A" opacity="0.7">
</circle>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+2 -2
View File
@@ -110,8 +110,8 @@ const APP_SECTIONS: AppSection[] = [
{ 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: '/social/kurdmedia' }, { title: 'mobile.app.kurdMedia', icon: '📺', route: '/social/kurdmedia' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', comingSoon: true }, { title: 'mobile.app.events', icon: '📅', route: '/forum', href: 'https://kurdishtts.pezkiwi.app' },
{ title: 'mobile.app.help', icon: '❓', route: '/help' }, { title: 'mobile.app.loto', icon: '🔥', imgIcon: '/loto-icon.svg', route: '/forum', href: 'https://loto.pex.mom' },
{ title: 'mobile.app.music', icon: '🎵', route: '/forum', comingSoon: true }, { title: 'mobile.app.music', icon: '🎵', route: '/forum', comingSoon: true },
{ title: 'mobile.app.rewshenbir',icon: '📡', imgIcon: '/rewshenbir-icon.png', route: '/rewshenbir', href: 'https://rewshenbir.pezkuwi.app' }, { title: 'mobile.app.rewshenbir',icon: '📡', imgIcon: '/rewshenbir-icon.png', route: '/rewshenbir', href: 'https://rewshenbir.pezkuwi.app' },
{ title: 'mobile.app.referral', icon: '👥', route: '/dashboard', requiresAuth: true }, { title: 'mobile.app.referral', icon: '👥', route: '/dashboard', requiresAuth: true },
+2 -2
View File
@@ -87,8 +87,8 @@ const APP_SECTIONS: AppSection[] = [
{ 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: '/social/kurdmedia' }, { title: 'mobile.app.kurdMedia', icon: '📺', route: '/social/kurdmedia' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', comingSoon: true }, { title: 'mobile.app.events', icon: '📅', route: '/forum', href: 'https://kurdishtts.pezkiwi.app' },
{ title: 'mobile.app.help', icon: '❓', route: '/help' }, { title: 'mobile.app.loto', icon: '🔥', imgIcon: '/loto-icon.svg', route: '/forum', href: 'https://loto.pex.mom' },
{ title: 'mobile.app.music', icon: '🎵', route: '/forum', comingSoon: true }, { title: 'mobile.app.music', icon: '🎵', route: '/forum', comingSoon: true },
{ title: 'mobile.app.rewshenbir', icon: '📡', imgIcon: '/rewshenbir-icon.png', route: '/rewshenbir', href: 'https://rewshenbir.pezkuwi.app' }, { title: 'mobile.app.rewshenbir', icon: '📡', imgIcon: '/rewshenbir-icon.png', route: '/rewshenbir', href: 'https://rewshenbir.pezkuwi.app' },
{ title: 'mobile.app.referral', icon: '👥', route: '/dashboard', requiresAuth: true }, { title: 'mobile.app.referral', icon: '👥', route: '/dashboard', requiresAuth: true },
@@ -1099,7 +1099,7 @@ const LandingPageDesktop: React.FC = () => {
<PalletItem icon="lp-i-chat" label={t('landing.pallets.whatskurd')} to="/social/whatskurd" requiresLogin /> <PalletItem icon="lp-i-chat" label={t('landing.pallets.whatskurd')} to="/social/whatskurd" requiresLogin />
<PalletItem icon="lp-i-forum" label={t('landing.pallets.forum')} to="/forum" /> <PalletItem icon="lp-i-forum" label={t('landing.pallets.forum')} to="/forum" />
<PalletItem icon="lp-i-media" label={t('landing.pallets.kurdmedia')} to="/social/kurdmedia" requiresLogin /> <PalletItem icon="lp-i-media" label={t('landing.pallets.kurdmedia')} to="/social/kurdmedia" requiresLogin />
<PalletItem icon="lp-i-cal" label={t('landing.pallets.events')} locked /> <PalletItem icon="lp-i-cal" label={t('landing.pallets.events')} external="https://kurdishtts.pezkiwi.app" />
<PalletItem icon="lp-i-help" label={t('landing.pallets.help')} to="/help" /> <PalletItem icon="lp-i-help" label={t('landing.pallets.help')} to="/help" />
<PalletItem icon="lp-i-music" label={t('landing.pallets.music')} locked /> <PalletItem icon="lp-i-music" label={t('landing.pallets.music')} locked />
<PalletItem imgSrc="/rewshenbir-icon.png" label={t('landing.pallets.rewshenbir')} external="https://rewshenbir.pezkuwi.app" /> <PalletItem imgSrc="/rewshenbir-icon.png" label={t('landing.pallets.rewshenbir')} external="https://rewshenbir.pezkuwi.app" />
+10 -1
View File
@@ -5,7 +5,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { PlusCircle, Home, ClipboardList, TrendingUp, CheckCircle2, Clock, Store, Zap, Blocks, MessageSquare } from 'lucide-react'; import { PlusCircle, Home, ClipboardList, TrendingUp, CheckCircle2, Clock, Store, Zap, Blocks, MessageSquare, CreditCard } from 'lucide-react';
import { AdList } from './AdList'; import { AdList } from './AdList';
import { CreateAd } from './CreateAd'; import { CreateAd } from './CreateAd';
import { NotificationBell } from './NotificationBell'; import { NotificationBell } from './NotificationBell';
@@ -191,6 +191,15 @@ export function P2PDashboard() {
</Badge> </Badge>
)} )}
</button> </button>
<a
href="https://buy-sell.pezkiwi.app"
target="_blank"
rel="noopener noreferrer"
className="relative flex flex-col items-center gap-0.5 px-3 py-1.5 rounded-lg hover:bg-amber-900/30 transition-colors"
>
<CreditCard className="w-5 h-5 text-amber-400" />
<span className="text-[10px] text-amber-300">{t('p2pNav.buyVisa')}</span>
</a>
</div> </div>
</div> </div>
+3 -1
View File
@@ -1561,6 +1561,7 @@ export default {
'p2pNav.orders': 'الطلبات', 'p2pNav.orders': 'الطلبات',
'p2pNav.ads': 'الإعلانات', 'p2pNav.ads': 'الإعلانات',
'p2pNav.messages': 'الرسائل', 'p2pNav.messages': 'الرسائل',
'p2pNav.buyVisa': 'اشترِ بفيزا',
// P2P Messages Inbox // P2P Messages Inbox
'p2pMessages.title': 'الرسائل', 'p2pMessages.title': 'الرسائل',
@@ -3787,7 +3788,7 @@ export default {
'mobile.app.bank': 'البنك', 'mobile.app.bank': 'البنك',
'mobile.app.exchange': 'البورصة', 'mobile.app.exchange': 'البورصة',
'mobile.app.dex': 'Pez-DEX', 'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P', 'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B', 'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'الضريبة/الزكاة', 'mobile.app.bacZekat': 'الضريبة/الزكاة',
'mobile.app.launchpad': 'منصة الإطلاق', 'mobile.app.launchpad': 'منصة الإطلاق',
@@ -3804,6 +3805,7 @@ export default {
'mobile.app.kurdMedia': 'كورد ميديا', 'mobile.app.kurdMedia': 'كورد ميديا',
'mobile.app.events': 'الفعاليات', 'mobile.app.events': 'الفعاليات',
'mobile.app.help': 'المساعدة', 'mobile.app.help': 'المساعدة',
'mobile.app.loto': 'لوتو',
'mobile.app.music': 'الموسيقى', 'mobile.app.music': 'الموسيقى',
'mobile.app.vpn': 'VPN', 'mobile.app.vpn': 'VPN',
'mobile.app.referral': 'الإحالة', 'mobile.app.referral': 'الإحالة',
+3 -1
View File
@@ -1551,6 +1551,7 @@ export default {
'p2pNav.orders': 'داواکاریەکان', 'p2pNav.orders': 'داواکاریەکان',
'p2pNav.ads': 'ڕیکلامەکان', 'p2pNav.ads': 'ڕیکلامەکان',
'p2pNav.messages': 'پەیامەکان', 'p2pNav.messages': 'پەیامەکان',
'p2pNav.buyVisa': 'بە ڤیزا بکڕە',
// P2P Messages Inbox // P2P Messages Inbox
'p2pMessages.title': 'پەیامەکان', 'p2pMessages.title': 'پەیامەکان',
@@ -3777,7 +3778,7 @@ export default {
'mobile.app.bank': 'بانک', 'mobile.app.bank': 'بانک',
'mobile.app.exchange': 'ئاڵوگۆڕ', 'mobile.app.exchange': 'ئاڵوگۆڕ',
'mobile.app.dex': 'Pez-DEX', 'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P', 'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B', 'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'باج/زەکات', 'mobile.app.bacZekat': 'باج/زەکات',
'mobile.app.launchpad': 'دەستپێکردن', 'mobile.app.launchpad': 'دەستپێکردن',
@@ -3794,6 +3795,7 @@ export default {
'mobile.app.kurdMedia': 'کوردمیدیا', 'mobile.app.kurdMedia': 'کوردمیدیا',
'mobile.app.events': 'چالاکی', 'mobile.app.events': 'چالاکی',
'mobile.app.help': 'یارمەتی', 'mobile.app.help': 'یارمەتی',
'mobile.app.loto': 'لۆتۆ',
'mobile.app.music': 'مۆسیقا', 'mobile.app.music': 'مۆسیقا',
'mobile.app.vpn': 'VPN', 'mobile.app.vpn': 'VPN',
'mobile.app.referral': 'ئاماژە', 'mobile.app.referral': 'ئاماژە',
+3 -1
View File
@@ -1915,6 +1915,7 @@ export default {
'p2pNav.orders': 'Orders', 'p2pNav.orders': 'Orders',
'p2pNav.ads': 'Ads', 'p2pNav.ads': 'Ads',
'p2pNav.messages': 'Messages', 'p2pNav.messages': 'Messages',
'p2pNav.buyVisa': 'Buy with Visa',
// P2P Messages Inbox // P2P Messages Inbox
'p2pMessages.title': 'Messages', 'p2pMessages.title': 'Messages',
@@ -3839,7 +3840,7 @@ export default {
'mobile.app.bank': 'Bank', 'mobile.app.bank': 'Bank',
'mobile.app.exchange': 'Exchange', 'mobile.app.exchange': 'Exchange',
'mobile.app.dex': 'Pez-DEX', 'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P', 'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B', 'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'Bac/Zekat', 'mobile.app.bacZekat': 'Bac/Zekat',
'mobile.app.launchpad': 'Launchpad', 'mobile.app.launchpad': 'Launchpad',
@@ -3856,6 +3857,7 @@ export default {
'mobile.app.kurdMedia': 'KurdMedia', 'mobile.app.kurdMedia': 'KurdMedia',
'mobile.app.events': 'Events', 'mobile.app.events': 'Events',
'mobile.app.help': 'Help', 'mobile.app.help': 'Help',
'mobile.app.loto': 'Loto',
'mobile.app.music': 'Music', 'mobile.app.music': 'Music',
'mobile.app.vpn': 'VPN', 'mobile.app.vpn': 'VPN',
'mobile.app.rewshenbir': 'Rewshenbir', 'mobile.app.rewshenbir': 'Rewshenbir',
+3 -1
View File
@@ -1585,6 +1585,7 @@ export default {
'p2pNav.orders': 'سفارشات', 'p2pNav.orders': 'سفارشات',
'p2pNav.ads': 'آگهی‌ها', 'p2pNav.ads': 'آگهی‌ها',
'p2pNav.messages': 'پیام‌ها', 'p2pNav.messages': 'پیام‌ها',
'p2pNav.buyVisa': 'خرید با ویزا',
// P2P Messages Inbox // P2P Messages Inbox
'p2pMessages.title': 'پیام‌ها', 'p2pMessages.title': 'پیام‌ها',
@@ -3821,7 +3822,7 @@ export default {
'mobile.app.bank': 'بانک', 'mobile.app.bank': 'بانک',
'mobile.app.exchange': 'صرافی', 'mobile.app.exchange': 'صرافی',
'mobile.app.dex': 'Pez-DEX', 'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P', 'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B', 'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'مالیات/زکات', 'mobile.app.bacZekat': 'مالیات/زکات',
'mobile.app.launchpad': 'سکوی پرتاب', 'mobile.app.launchpad': 'سکوی پرتاب',
@@ -3838,6 +3839,7 @@ export default {
'mobile.app.kurdMedia': 'کوردمدیا', 'mobile.app.kurdMedia': 'کوردمدیا',
'mobile.app.events': 'رویدادها', 'mobile.app.events': 'رویدادها',
'mobile.app.help': 'کمک', 'mobile.app.help': 'کمک',
'mobile.app.loto': 'لاتاری',
'mobile.app.music': 'موسیقی', 'mobile.app.music': 'موسیقی',
'mobile.app.vpn': 'VPN', 'mobile.app.vpn': 'VPN',
'mobile.app.referral': 'ارجاع', 'mobile.app.referral': 'ارجاع',
+3 -1
View File
@@ -1573,6 +1573,7 @@ export default {
'p2pNav.orders': 'Ferman', 'p2pNav.orders': 'Ferman',
'p2pNav.ads': 'Reklam', 'p2pNav.ads': 'Reklam',
'p2pNav.messages': 'Peyam', 'p2pNav.messages': 'Peyam',
'p2pNav.buyVisa': 'Bi Visa bikire',
// P2P Messages Inbox // P2P Messages Inbox
'p2pMessages.title': 'Peyam', 'p2pMessages.title': 'Peyam',
@@ -3804,7 +3805,7 @@ export default {
'mobile.app.bank': 'Bank', 'mobile.app.bank': 'Bank',
'mobile.app.exchange': 'Danûstandin', 'mobile.app.exchange': 'Danûstandin',
'mobile.app.dex': 'Pez-DEX', 'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P', 'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B', 'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'Bac/Zekat', 'mobile.app.bacZekat': 'Bac/Zekat',
'mobile.app.launchpad': 'Destpêk', 'mobile.app.launchpad': 'Destpêk',
@@ -3821,6 +3822,7 @@ export default {
'mobile.app.kurdMedia': 'KurdMedya', 'mobile.app.kurdMedia': 'KurdMedya',
'mobile.app.events': 'Çalakî', 'mobile.app.events': 'Çalakî',
'mobile.app.help': 'Alîkarî', 'mobile.app.help': 'Alîkarî',
'mobile.app.loto': 'Loto',
'mobile.app.music': 'Muzîk', 'mobile.app.music': 'Muzîk',
'mobile.app.vpn': 'VPN', 'mobile.app.vpn': 'VPN',
'mobile.app.rewshenbir': 'Rewşenbir', 'mobile.app.rewshenbir': 'Rewşenbir',
+3 -1
View File
@@ -1567,6 +1567,7 @@ export default {
'p2pNav.orders': 'Siparişler', 'p2pNav.orders': 'Siparişler',
'p2pNav.ads': 'İlanlar', 'p2pNav.ads': 'İlanlar',
'p2pNav.messages': 'Mesajlar', 'p2pNav.messages': 'Mesajlar',
'p2pNav.buyVisa': 'Visa ile Al',
// P2P Messages Inbox // P2P Messages Inbox
'p2pMessages.title': 'Mesajlar', 'p2pMessages.title': 'Mesajlar',
@@ -3807,7 +3808,7 @@ export default {
'mobile.app.bank': 'Banka', 'mobile.app.bank': 'Banka',
'mobile.app.exchange': 'Borsa', 'mobile.app.exchange': 'Borsa',
'mobile.app.dex': 'Pez-DEX', 'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P', 'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B', 'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'Vergi/Zekat', 'mobile.app.bacZekat': 'Vergi/Zekat',
'mobile.app.launchpad': 'Launchpad', 'mobile.app.launchpad': 'Launchpad',
@@ -3824,6 +3825,7 @@ export default {
'mobile.app.kurdMedia': 'KurdMedya', 'mobile.app.kurdMedia': 'KurdMedya',
'mobile.app.events': 'Etkinlikler', 'mobile.app.events': 'Etkinlikler',
'mobile.app.help': 'Yardım', 'mobile.app.help': 'Yardım',
'mobile.app.loto': 'Loto',
'mobile.app.music': 'Müzik', 'mobile.app.music': 'Müzik',
'mobile.app.vpn': 'VPN', 'mobile.app.vpn': 'VPN',
'mobile.app.rewshenbir': 'Rewshenbir', 'mobile.app.rewshenbir': 'Rewshenbir',
+33 -14
View File
@@ -9,6 +9,7 @@ interface MediaChannel {
descriptionKu: string; descriptionKu: string;
description: string; description: string;
color: string; color: string;
url?: string;
} }
interface SocialPlatform { interface SocialPlatform {
@@ -21,7 +22,7 @@ interface SocialPlatform {
const MEDIA_CHANNELS: MediaChannel[] = [ 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: '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: 'dksgzt', nameKu: 'DKS Rojname', name: 'DKS Gazette', icon: '📰', descriptionKu: 'Nûçe û Daxuyaniyên Fermî', description: 'Official News & Announcements', color: '#1E88E5', url: 'https://news.pex.mom' },
{ id: 'dksradio', nameKu: 'DKS Radyo', name: 'DKS Radio', icon: '📻', descriptionKu: 'Radyoya Dewleta Dijîtal a Kurdistanê', description: 'Digital Kurdistan State Radio', color: '#7B1FA2' }, { 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: '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: 'dkspodcast',nameKu: 'DKS Podcast', name: 'DKS Podcast', icon: '🎙️', descriptionKu: 'Podcast û Gotûbêjên Kurdî', description: 'Kurdish Podcasts & Talks', color: '#F4511E' },
@@ -71,20 +72,38 @@ export default function KurdMediaPage() {
<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-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> <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"> <div className="space-y-3">
{MEDIA_CHANNELS.map(ch => ( {MEDIA_CHANNELS.map(ch => {
<div key={ch.id} className="flex items-center gap-3 bg-gray-800 rounded-xl p-3"> const inner = (
<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 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>
{ch.url ? (
<span className="text-[10px] font-bold text-green-400 bg-green-400/10 px-2 py-1 rounded-full flex-shrink-0">
{t('kurdMedia.open', 'Open')}
</span>
) : (
<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>
)}
</>
);
return ch.url ? (
<a key={ch.id} href={ch.url} target="_blank" rel="noopener noreferrer"
className="flex items-center gap-3 bg-gray-800 rounded-xl p-3 hover:bg-gray-700 transition-colors">
{inner}
</a>
) : (
<div key={ch.id} className="flex items-center gap-3 bg-gray-800 rounded-xl p-3">
{inner}
</div> </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> </div>
</div> </div>