4 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
13 changed files with 144 additions and 32 deletions
+6 -6
View File
@@ -5457,9 +5457,9 @@
}
},
"node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": {
"version": "7.5.10",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"version": "7.5.11",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz",
"integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==",
"license": "MIT",
"engines": {
"node": ">=8.3.0"
@@ -7651,9 +7651,9 @@
}
},
"node_modules/dompurify": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz",
"integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==",
"version": "3.4.10",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.10.tgz",
"integrity": "sha512-0xzNv0e7oYC6yyuOGZIABPM4qtg3QxLFniDNPP4ZP90wR8Yq3zgwpRbrNiT4N3IKqDbbYFEJLV+JWEs19aZ//w==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@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.forum', icon: '📰', route: '/forum' },
{ title: 'mobile.app.kurdMedia', icon: '📺', route: '/social/kurdmedia' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', comingSoon: true },
{ title: 'mobile.app.help', icon: '❓', route: '/help' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', href: 'https://kurdishtts.pezkiwi.app' },
{ 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.rewshenbir',icon: '📡', imgIcon: '/rewshenbir-icon.png', route: '/rewshenbir', href: 'https://rewshenbir.pezkuwi.app' },
{ 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.forum', icon: '📰', route: '/forum' },
{ title: 'mobile.app.kurdMedia', icon: '📺', route: '/social/kurdmedia' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', comingSoon: true },
{ title: 'mobile.app.help', icon: '❓', route: '/help' },
{ title: 'mobile.app.events', icon: '📅', route: '/forum', href: 'https://kurdishtts.pezkiwi.app' },
{ 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.rewshenbir', icon: '📡', imgIcon: '/rewshenbir-icon.png', route: '/rewshenbir', href: 'https://rewshenbir.pezkuwi.app' },
{ 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-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-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-music" label={t('landing.pallets.music')} locked />
<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 { Badge } from '@/components/ui/badge';
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 { CreateAd } from './CreateAd';
import { NotificationBell } from './NotificationBell';
@@ -191,6 +191,15 @@ export function P2PDashboard() {
</Badge>
)}
</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>
+3 -1
View File
@@ -1561,6 +1561,7 @@ export default {
'p2pNav.orders': 'الطلبات',
'p2pNav.ads': 'الإعلانات',
'p2pNav.messages': 'الرسائل',
'p2pNav.buyVisa': 'اشترِ بفيزا',
// P2P Messages Inbox
'p2pMessages.title': 'الرسائل',
@@ -3787,7 +3788,7 @@ export default {
'mobile.app.bank': 'البنك',
'mobile.app.exchange': 'البورصة',
'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P',
'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'الضريبة/الزكاة',
'mobile.app.launchpad': 'منصة الإطلاق',
@@ -3804,6 +3805,7 @@ export default {
'mobile.app.kurdMedia': 'كورد ميديا',
'mobile.app.events': 'الفعاليات',
'mobile.app.help': 'المساعدة',
'mobile.app.loto': 'لوتو',
'mobile.app.music': 'الموسيقى',
'mobile.app.vpn': 'VPN',
'mobile.app.referral': 'الإحالة',
+3 -1
View File
@@ -1551,6 +1551,7 @@ export default {
'p2pNav.orders': 'داواکاریەکان',
'p2pNav.ads': 'ڕیکلامەکان',
'p2pNav.messages': 'پەیامەکان',
'p2pNav.buyVisa': 'بە ڤیزا بکڕە',
// P2P Messages Inbox
'p2pMessages.title': 'پەیامەکان',
@@ -3777,7 +3778,7 @@ export default {
'mobile.app.bank': 'بانک',
'mobile.app.exchange': 'ئاڵوگۆڕ',
'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P',
'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'باج/زەکات',
'mobile.app.launchpad': 'دەستپێکردن',
@@ -3794,6 +3795,7 @@ export default {
'mobile.app.kurdMedia': 'کوردمیدیا',
'mobile.app.events': 'چالاکی',
'mobile.app.help': 'یارمەتی',
'mobile.app.loto': 'لۆتۆ',
'mobile.app.music': 'مۆسیقا',
'mobile.app.vpn': 'VPN',
'mobile.app.referral': 'ئاماژە',
+3 -1
View File
@@ -1915,6 +1915,7 @@ export default {
'p2pNav.orders': 'Orders',
'p2pNav.ads': 'Ads',
'p2pNav.messages': 'Messages',
'p2pNav.buyVisa': 'Buy with Visa',
// P2P Messages Inbox
'p2pMessages.title': 'Messages',
@@ -3839,7 +3840,7 @@ export default {
'mobile.app.bank': 'Bank',
'mobile.app.exchange': 'Exchange',
'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P',
'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'Bac/Zekat',
'mobile.app.launchpad': 'Launchpad',
@@ -3856,6 +3857,7 @@ export default {
'mobile.app.kurdMedia': 'KurdMedia',
'mobile.app.events': 'Events',
'mobile.app.help': 'Help',
'mobile.app.loto': 'Loto',
'mobile.app.music': 'Music',
'mobile.app.vpn': 'VPN',
'mobile.app.rewshenbir': 'Rewshenbir',
+3 -1
View File
@@ -1585,6 +1585,7 @@ export default {
'p2pNav.orders': 'سفارشات',
'p2pNav.ads': 'آگهی‌ها',
'p2pNav.messages': 'پیام‌ها',
'p2pNav.buyVisa': 'خرید با ویزا',
// P2P Messages Inbox
'p2pMessages.title': 'پیام‌ها',
@@ -3821,7 +3822,7 @@ export default {
'mobile.app.bank': 'بانک',
'mobile.app.exchange': 'صرافی',
'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P',
'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'مالیات/زکات',
'mobile.app.launchpad': 'سکوی پرتاب',
@@ -3838,6 +3839,7 @@ export default {
'mobile.app.kurdMedia': 'کوردمدیا',
'mobile.app.events': 'رویدادها',
'mobile.app.help': 'کمک',
'mobile.app.loto': 'لاتاری',
'mobile.app.music': 'موسیقی',
'mobile.app.vpn': 'VPN',
'mobile.app.referral': 'ارجاع',
+3 -1
View File
@@ -1573,6 +1573,7 @@ export default {
'p2pNav.orders': 'Ferman',
'p2pNav.ads': 'Reklam',
'p2pNav.messages': 'Peyam',
'p2pNav.buyVisa': 'Bi Visa bikire',
// P2P Messages Inbox
'p2pMessages.title': 'Peyam',
@@ -3804,7 +3805,7 @@ export default {
'mobile.app.bank': 'Bank',
'mobile.app.exchange': 'Danûstandin',
'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P',
'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'Bac/Zekat',
'mobile.app.launchpad': 'Destpêk',
@@ -3821,6 +3822,7 @@ export default {
'mobile.app.kurdMedia': 'KurdMedya',
'mobile.app.events': 'Çalakî',
'mobile.app.help': 'Alîkarî',
'mobile.app.loto': 'Loto',
'mobile.app.music': 'Muzîk',
'mobile.app.vpn': 'VPN',
'mobile.app.rewshenbir': 'Rewşenbir',
+3 -1
View File
@@ -1567,6 +1567,7 @@ export default {
'p2pNav.orders': 'Siparişler',
'p2pNav.ads': 'İlanlar',
'p2pNav.messages': 'Mesajlar',
'p2pNav.buyVisa': 'Visa ile Al',
// P2P Messages Inbox
'p2pMessages.title': 'Mesajlar',
@@ -3807,7 +3808,7 @@ export default {
'mobile.app.bank': 'Banka',
'mobile.app.exchange': 'Borsa',
'mobile.app.dex': 'Pez-DEX',
'mobile.app.p2p': 'P2P',
'mobile.app.p2p': 'P2P/Buy-Sell',
'mobile.app.b2b': 'B2B',
'mobile.app.bacZekat': 'Vergi/Zekat',
'mobile.app.launchpad': 'Launchpad',
@@ -3824,6 +3825,7 @@ export default {
'mobile.app.kurdMedia': 'KurdMedya',
'mobile.app.events': 'Etkinlikler',
'mobile.app.help': 'Yardım',
'mobile.app.loto': 'Loto',
'mobile.app.music': 'Müzik',
'mobile.app.vpn': 'VPN',
'mobile.app.rewshenbir': 'Rewshenbir',
+33 -14
View File
@@ -9,6 +9,7 @@ interface MediaChannel {
descriptionKu: string;
description: string;
color: string;
url?: string;
}
interface SocialPlatform {
@@ -21,7 +22,7 @@ interface SocialPlatform {
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: '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: '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' },
@@ -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-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}
{MEDIA_CHANNELS.map(ch => {
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>
<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 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>