From b4f9f332cf714717ed52cd18a82af9d2feb22416 Mon Sep 17 00:00:00 2001 From: Fringg Date: Thu, 12 Mar 2026 18:33:37 +0300 Subject: [PATCH 1/2] feat: add LIMITED subscription status support with traffic-exhausted UX - Add is_limited to Subscription type - Show yellow traffic-exhausted badge on Subscription and AdminUsers pages - SubscriptionCardExpired: amber theme with warning icon and buy-traffic CTA for limited - Dashboard: route limited subscriptions to SubscriptionCardExpired - Subscription page: show additional options (buy traffic) for limited subs - Use is_limited boolean instead of status string comparison - Add trafficLimited translations for ru, en, zh, fa - AdminUserDetail StatusBadge: add limited yellow styling --- .../dashboard/SubscriptionCardExpired.tsx | 298 +++++++++++------- src/locales/en.json | 4 + src/locales/fa.json | 4 + src/locales/ru.json | 4 + src/locales/zh.json | 4 + src/pages/AdminUserDetail.tsx | 1 + src/pages/AdminUsers.tsx | 8 +- src/pages/Dashboard.tsx | 4 +- src/pages/Subscription.tsx | 79 ++++- src/types/index.ts | 1 + 10 files changed, 281 insertions(+), 126 deletions(-) diff --git a/src/components/dashboard/SubscriptionCardExpired.tsx b/src/components/dashboard/SubscriptionCardExpired.tsx index 9b13259..7bcfb4e 100644 --- a/src/components/dashboard/SubscriptionCardExpired.tsx +++ b/src/components/dashboard/SubscriptionCardExpired.tsx @@ -38,6 +38,9 @@ export default function SubscriptionCardExpired({ const formattedDate = new Date(subscription.end_date).toLocaleDateString(); + // Detect limited (traffic exhausted) state + const isLimited = subscription.is_limited; + // Detect daily subscription (disabled or expired) const isDaily = subscription.is_daily; const isDisabledDaily = subscription.status === 'disabled' && isDaily; @@ -92,19 +95,38 @@ export default function SubscriptionCardExpired({ navigate(`/balance/top-up?${params.toString()}`); }; + // Color scheme: amber for limited, red for expired/disabled + const accent = isLimited + ? { + r: 255, + g: 184, + b: 0, + hex: '#FFB800', + gradient: 'linear-gradient(135deg, #FFB800, #FF8C00)', + } + : { + r: 255, + g: 59, + b: 92, + hex: '#FF3B5C', + gradient: 'linear-gradient(135deg, #FF3B5C, #FF6B35)', + }; + return (
- {/* Red glow */} + {/* Glow */} diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx index 7564778..d98767f 100644 --- a/src/pages/Dashboard.tsx +++ b/src/pages/Dashboard.tsx @@ -247,7 +247,9 @@ export default function Dashboard() {
- ) : subscription?.is_expired || subscription?.status === 'disabled' ? ( + ) : subscription?.is_expired || + subscription?.status === 'disabled' || + subscription?.is_limited ? ( {subscription.is_active ? subscription.is_trial ? t('subscription.trialStatus') : t('subscription.active') - : subscription.status === 'disabled' - ? t('subscription.pause.suspended') - : t('subscription.expired')} + : subscription.is_limited + ? t('subscription.trafficLimited') + : subscription.status === 'disabled' + ? t('subscription.pause.suspended') + : t('subscription.expired')} + {/* ─── Traffic Limited Banner ─── */} + {subscription.is_limited && ( +
+
+
+ +
+
+

+ {t('subscription.trafficLimitedTitle')} +

+

+ {t('subscription.trafficLimitedDescription')} +

+
+
+
+ )} + {/* ─── Trial Info Banner ─── */} {subscription.is_trial && subscription.is_active && (
- {subscription.status === 'disabled' - ? t('subscription.pause.suspended') - : subscription.is_daily_paused - ? t('subscription.pause.paused') - : t('subscription.pause.active')} + {subscription.is_limited + ? t('subscription.trafficLimited') + : subscription.status === 'disabled' + ? t('subscription.pause.suspended') + : subscription.is_daily_paused + ? t('subscription.pause.paused') + : t('subscription.pause.active')}