From a72042d8075000db204b0f57c893928cadc68cef Mon Sep 17 00:00:00 2001 From: Fringg Date: Tue, 17 Feb 2026 10:54:36 +0300 Subject: [PATCH] fix: show all campaigns in assign list, add dual links and bonus details 1. Remove is_active filter from campaign assign page so inactive campaigns are also visible (with badge) 2. Redesign partner campaign cards with separate bot/cabinet links, detailed bonus descriptions, and per-link copy buttons --- src/locales/en.json | 10 +- src/locales/fa.json | 10 +- src/locales/ru.json | 10 +- src/locales/zh.json | 10 +- src/pages/AdminPartnerCampaignAssign.tsx | 12 +- src/pages/Referral.tsx | 156 ++++++++++++++--------- 6 files changed, 138 insertions(+), 70 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index c67989b..97f7365 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -671,10 +671,18 @@ "submitApplication": "Submit Application", "applyError": "Failed to submit application. Please try again.", "yourCampaigns": "Your campaigns", + "campaignLinks": { + "bot": "Bot link", + "web": "Cabinet link" + }, "campaignBonus": { + "title": "Referral bonus", "balance": "+{{amount}} to balance", + "balanceDesc": "{{amount}} credited on signup", "subscription": "{{days}} days subscription", - "tariff": "Bonus tariff" + "subscriptionDesc": "{{days}} days free subscription", + "tariff": "Bonus tariff", + "tariffDesc": "Free tariff plan" }, "fields": { "companyName": "Company Name", diff --git a/src/locales/fa.json b/src/locales/fa.json index 64d47b6..d93c078 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -562,10 +562,18 @@ "submitApplication": "ارسال درخواست", "applyError": "ارسال درخواست ناموفق بود. لطفاً دوباره تلاش کنید.", "yourCampaigns": "کمپین‌های شما", + "campaignLinks": { + "bot": "لینک ربات", + "web": "لینک کابینت" + }, "campaignBonus": { + "title": "جایزه معرفی", "balance": "+{{amount}} به موجودی", + "balanceDesc": "{{amount}} هنگام ثبت‌نام", "subscription": "{{days}} روز اشتراک", - "tariff": "تعرفه جایزه" + "subscriptionDesc": "{{days}} روز اشتراک رایگان", + "tariff": "تعرفه جایزه", + "tariffDesc": "طرح تعرفه رایگان" }, "fields": { "companyName": "نام شرکت", diff --git a/src/locales/ru.json b/src/locales/ru.json index c36eab4..5824309 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -698,10 +698,18 @@ "submitApplication": "Отправить заявку", "applyError": "Не удалось отправить заявку. Попробуйте снова.", "yourCampaigns": "Ваши кампании", + "campaignLinks": { + "bot": "Ссылка в бот", + "web": "Ссылка в кабинет" + }, "campaignBonus": { + "title": "Бонус для реферала", "balance": "+{{amount}} на баланс", + "balanceDesc": "{{amount}} на баланс при регистрации", "subscription": "{{days}} дн. подписки", - "tariff": "Бонусный тариф" + "subscriptionDesc": "{{days}} дней бесплатной подписки", + "tariff": "Бонусный тариф", + "tariffDesc": "Бесплатный тарифный план" }, "fields": { "companyName": "Название компании", diff --git a/src/locales/zh.json b/src/locales/zh.json index 00d2b79..7b68f65 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -562,10 +562,18 @@ "submitApplication": "提交申请", "applyError": "提交申请失败,请重试。", "yourCampaigns": "您的活动", + "campaignLinks": { + "bot": "机器人链接", + "web": "网页链接" + }, "campaignBonus": { + "title": "推荐奖励", "balance": "+{{amount}} 余额", + "balanceDesc": "注册时充值 {{amount}}", "subscription": "{{days}} 天订阅", - "tariff": "奖励套餐" + "subscriptionDesc": "{{days}} 天免费订阅", + "tariff": "奖励套餐", + "tariffDesc": "免费套餐方案" }, "fields": { "companyName": "公司名称", diff --git a/src/pages/AdminPartnerCampaignAssign.tsx b/src/pages/AdminPartnerCampaignAssign.tsx index d45a086..1dc924e 100644 --- a/src/pages/AdminPartnerCampaignAssign.tsx +++ b/src/pages/AdminPartnerCampaignAssign.tsx @@ -33,8 +33,7 @@ export default function AdminPartnerCampaignAssign() { }); const assignedIds = new Set(partner?.campaigns.map((c) => c.id) ?? []); - const available = - campaignsData?.campaigns.filter((c) => !assignedIds.has(c.id) && c.is_active) ?? []; + const available = campaignsData?.campaigns.filter((c) => !assignedIds.has(c.id)) ?? []; const partnerName = partner ? partner.first_name || partner.username || `#${partner.user_id}` @@ -75,7 +74,14 @@ export default function AdminPartnerCampaignAssign() {
-
{campaign.name}
+
+ {campaign.name} + {!campaign.is_active && ( + + {t('admin.campaigns.status.inactive')} + + )} +
?start={campaign.start_parameter} diff --git a/src/pages/Referral.tsx b/src/pages/Referral.tsx index 8682615..5003775 100644 --- a/src/pages/Referral.tsx +++ b/src/pages/Referral.tsx @@ -93,7 +93,7 @@ export default function Referral() { const { formatAmount, currencySymbol, formatPositive, formatWithCurrency } = useCurrency(); const queryClient = useQueryClient(); const [copied, setCopied] = useState(false); - const [copiedCampaignId, setCopiedCampaignId] = useState(null); + const [copiedLink, setCopiedLink] = useState(null); const { data: info, isLoading } = useQuery({ queryKey: ['referral-info'], @@ -522,8 +522,8 @@ export default function Referral() { {/* ==================== Partner Campaigns Section ==================== */} {isPartner && partnerStatus?.campaigns && partnerStatus.campaigns.length > 0 && ( -
-
+
+
@@ -532,69 +532,99 @@ export default function Referral() {
-
- {partnerStatus.campaigns.map((campaign) => { - const shareUrl = campaign.deep_link || campaign.web_link || ''; - const isCopied = copiedCampaignId === campaign.id; + {partnerStatus.campaigns.map((campaign) => { + const copyLink = (url: string, key: string) => { + navigator.clipboard.writeText(url); + setCopiedLink(key); + setTimeout(() => setCopiedLink(null), 2000); + }; - const copyCampaignLink = () => { - if (!shareUrl) return; - navigator.clipboard.writeText(shareUrl); - setCopiedCampaignId(campaign.id); - setTimeout(() => setCopiedCampaignId(null), 2000); - }; + const botKey = `${campaign.id}-bot`; + const webKey = `${campaign.id}-web`; - const bonusBadge = (() => { - switch (campaign.bonus_type) { - case 'balance': - return { - label: t('referral.partner.campaignBonus.balance', { - amount: formatWithCurrency(campaign.balance_bonus_kopeks / 100, 0), - }), - className: 'badge-success', - }; - case 'subscription': - return { - label: t('referral.partner.campaignBonus.subscription', { - days: campaign.subscription_duration_days ?? 0, - }), - className: 'badge-info', - }; - case 'tariff': - return { - label: t('referral.partner.campaignBonus.tariff'), - className: 'badge-info', - }; - default: - return null; - } - })(); - - return ( -
-
- {campaign.name} - {bonusBadge && {bonusBadge.label}} -
-
- - -
+ return ( +
+ {/* Campaign header */} +
+

{campaign.name}

- ); - })} -
+ + {/* Bonus info */} + {campaign.bonus_type !== 'none' && ( +
+
+ {t('referral.partner.campaignBonus.title')} +
+
+ {campaign.bonus_type === 'balance' && + t('referral.partner.campaignBonus.balanceDesc', { + amount: formatWithCurrency(campaign.balance_bonus_kopeks / 100, 0), + })} + {campaign.bonus_type === 'subscription' && + t('referral.partner.campaignBonus.subscriptionDesc', { + days: campaign.subscription_duration_days ?? 0, + ...(campaign.subscription_traffic_gb + ? { traffic: campaign.subscription_traffic_gb } + : {}), + })} + {campaign.bonus_type === 'tariff' && + t('referral.partner.campaignBonus.tariffDesc')} +
+
+ )} + + {/* Bot link */} + {campaign.deep_link && ( +
+
+ {t('referral.partner.campaignLinks.bot')} +
+
+ + +
+
+ )} + + {/* Web link */} + {campaign.web_link && ( +
+
+ {t('referral.partner.campaignLinks.web')} +
+
+ + +
+
+ )} +
+ ); + })}
)}