mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
@@ -305,6 +305,21 @@
|
|||||||
"insufficientBalance": "Top up your balance to activate",
|
"insufficientBalance": "Top up your balance to activate",
|
||||||
"unavailable": "Trial is not available"
|
"unavailable": "Trial is not available"
|
||||||
},
|
},
|
||||||
|
"trialBanner": {
|
||||||
|
"title": "Trial period active",
|
||||||
|
"description": "You have {{days}} days left in your trial. Subscribe to continue using the service.",
|
||||||
|
"upgrade": "Choose a plan"
|
||||||
|
},
|
||||||
|
"trialInfo": {
|
||||||
|
"title": "Trial Period",
|
||||||
|
"description": "You are using a trial version. Choose a plan below for full access.",
|
||||||
|
"remaining": "remaining",
|
||||||
|
"upgradeNow": "Choose a plan"
|
||||||
|
},
|
||||||
|
"trialUpgrade": {
|
||||||
|
"title": "Choose a plan to continue",
|
||||||
|
"description": "Your trial period is ending soon. Select a plan to continue using VPN without restrictions."
|
||||||
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Connect VPN",
|
"title": "Connect VPN",
|
||||||
"selectDevice": "Select your device",
|
"selectDevice": "Select your device",
|
||||||
|
|||||||
@@ -327,6 +327,21 @@
|
|||||||
"insufficientBalance": "Пополните баланс для активации",
|
"insufficientBalance": "Пополните баланс для активации",
|
||||||
"unavailable": "Пробный период недоступен"
|
"unavailable": "Пробный период недоступен"
|
||||||
},
|
},
|
||||||
|
"trialBanner": {
|
||||||
|
"title": "Пробный период активен",
|
||||||
|
"description": "У вас осталось {{days}} дней пробного периода. Оформите подписку, чтобы продолжить пользоваться сервисом.",
|
||||||
|
"upgrade": "Выбрать тариф"
|
||||||
|
},
|
||||||
|
"trialInfo": {
|
||||||
|
"title": "Пробный период",
|
||||||
|
"description": "Вы используете пробную версию сервиса. Выберите тариф ниже для полного доступа.",
|
||||||
|
"remaining": "осталось",
|
||||||
|
"upgradeNow": "Выбрать тариф"
|
||||||
|
},
|
||||||
|
"trialUpgrade": {
|
||||||
|
"title": "Выберите тариф для продолжения",
|
||||||
|
"description": "Ваш пробный период скоро закончится. Выберите подходящий тариф, чтобы продолжить пользоваться VPN без ограничений."
|
||||||
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Подключить VPN",
|
"title": "Подключить VPN",
|
||||||
"selectDevice": "Выберите устройство",
|
"selectDevice": "Выберите устройство",
|
||||||
|
|||||||
@@ -300,14 +300,60 @@ export default function Dashboard() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : subscription ? (
|
) : subscription ? (
|
||||||
<div className="bento-card">
|
<div
|
||||||
|
className={`bento-card ${subscription.is_trial ? 'border-warning-500/30 bg-gradient-to-br from-warning-500/5 to-transparent' : ''}`}
|
||||||
|
>
|
||||||
<div className="mb-6 flex items-center justify-between">
|
<div className="mb-6 flex items-center justify-between">
|
||||||
<h2 className="text-lg font-semibold text-dark-100">{t('subscription.status')}</h2>
|
<div>
|
||||||
<span className={subscription.is_active ? 'badge-success' : 'badge-error'}>
|
<h2 className="text-lg font-semibold text-dark-100">{t('subscription.status')}</h2>
|
||||||
{subscription.is_active ? t('subscription.active') : t('subscription.expired')}
|
{subscription.tariff_name && (
|
||||||
|
<div className="mt-1 text-sm text-accent-400">{subscription.tariff_name}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
subscription.is_trial
|
||||||
|
? 'badge-warning'
|
||||||
|
: subscription.is_active
|
||||||
|
? 'badge-success'
|
||||||
|
: 'badge-error'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{subscription.is_trial
|
||||||
|
? t('subscription.trialStatus')
|
||||||
|
: subscription.is_active
|
||||||
|
? t('subscription.active')
|
||||||
|
: t('subscription.expired')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Trial Info Banner */}
|
||||||
|
{subscription.is_trial && subscription.is_active && (
|
||||||
|
<div className="mb-6 rounded-xl border border-warning-500/30 bg-warning-500/10 p-4">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-warning-500/20 text-xl">
|
||||||
|
<SparklesIcon />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<div className="font-medium text-warning-300">
|
||||||
|
{t('subscription.trialBanner.title')}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-sm text-dark-400">
|
||||||
|
{t('subscription.trialBanner.description', { days: subscription.days_left })}
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
to="/subscription"
|
||||||
|
state={{ scrollToExtend: true }}
|
||||||
|
className="mt-3 inline-flex items-center gap-1.5 text-sm font-medium text-warning-400 transition-colors hover:text-warning-300"
|
||||||
|
>
|
||||||
|
{t('subscription.trialBanner.upgrade')}
|
||||||
|
<ArrowRightIcon />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-6 md:grid-cols-4">
|
<div className="grid grid-cols-2 gap-6 md:grid-cols-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-1 text-sm text-dark-500">{t('subscription.expiresAt')}</div>
|
<div className="mb-1 text-sm text-dark-500">{t('subscription.expiresAt')}</div>
|
||||||
|
|||||||
@@ -601,7 +601,9 @@ export default function Subscription() {
|
|||||||
|
|
||||||
{/* Current Subscription */}
|
{/* Current Subscription */}
|
||||||
{subscription ? (
|
{subscription ? (
|
||||||
<div className="bento-card">
|
<div
|
||||||
|
className={`bento-card ${subscription.is_trial ? 'border-warning-500/30 bg-gradient-to-br from-warning-500/5 to-transparent' : ''}`}
|
||||||
|
>
|
||||||
<div className="mb-6 flex items-center justify-between">
|
<div className="mb-6 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-semibold text-dark-100">
|
<h2 className="text-lg font-semibold text-dark-100">
|
||||||
@@ -628,6 +630,57 @@ export default function Subscription() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Trial Period Info Banner */}
|
||||||
|
{subscription.is_trial && subscription.is_active && (
|
||||||
|
<div className="mb-6 rounded-xl border border-warning-500/30 bg-warning-500/10 p-4">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-warning-500/20 text-lg">
|
||||||
|
<svg
|
||||||
|
className="h-5 w-5 text-warning-400"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<div className="font-medium text-warning-300">
|
||||||
|
{t('subscription.trialInfo.title')}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-sm text-dark-400">
|
||||||
|
{t('subscription.trialInfo.description')}
|
||||||
|
</div>
|
||||||
|
<div className="mt-3 flex flex-wrap gap-4 text-sm">
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<span className="text-warning-400">
|
||||||
|
{subscription.days_left > 0
|
||||||
|
? t('subscription.days', { count: subscription.days_left })
|
||||||
|
: `${subscription.hours_left}${t('subscription.hours')} ${subscription.minutes_left}${t('subscription.minutes')}`}
|
||||||
|
</span>
|
||||||
|
<span className="text-dark-500">{t('subscription.trialInfo.remaining')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<span className="text-warning-400">
|
||||||
|
{subscription.traffic_limit_gb || '∞'} GB
|
||||||
|
</span>
|
||||||
|
<span className="text-dark-500">{t('subscription.traffic')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<span className="text-warning-400">{subscription.device_limit}</span>
|
||||||
|
<span className="text-dark-500">{t('subscription.devices')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Connection Data - Top Priority */}
|
{/* Connection Data - Top Priority */}
|
||||||
{subscription.subscription_url && (
|
{subscription.subscription_url && (
|
||||||
<div className="mb-6 rounded-xl border border-accent-500/30 bg-accent-500/10 p-4">
|
<div className="mb-6 rounded-xl border border-accent-500/30 bg-accent-500/10 p-4">
|
||||||
@@ -1871,17 +1924,48 @@ export default function Subscription() {
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Trial upgrade prompt */}
|
||||||
|
{subscription?.is_trial && (
|
||||||
|
<div className="mb-6 rounded-xl border border-warning-500/30 bg-gradient-to-r from-warning-500/10 to-accent-500/10 p-4">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-warning-500/20">
|
||||||
|
<svg
|
||||||
|
className="h-5 w-5 text-warning-400"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="font-medium text-warning-300">
|
||||||
|
{t('subscription.trialUpgrade.title')}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-sm text-dark-400">
|
||||||
|
{t('subscription.trialUpgrade.description')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Legacy subscription notice - if user has subscription without tariff */}
|
{/* Legacy subscription notice - if user has subscription without tariff */}
|
||||||
{subscription && !subscription.is_trial && !subscription.tariff_id && (
|
{subscription && !subscription.is_trial && !subscription.tariff_id && (
|
||||||
<div className="mb-6 rounded-xl border border-accent-500/30 bg-accent-500/10 p-4">
|
<div className="mb-6 rounded-xl border border-accent-500/30 bg-accent-500/10 p-4">
|
||||||
<div className="mb-2 font-medium text-accent-400">
|
<div className="mb-2 font-medium text-accent-400">
|
||||||
📦 {t('subscription.legacy.selectTariffTitle')}
|
{t('subscription.legacy.selectTariffTitle')}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-dark-300">
|
<div className="text-sm text-dark-300">
|
||||||
{t('subscription.legacy.selectTariffDescription')}
|
{t('subscription.legacy.selectTariffDescription')}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 text-xs text-dark-500">
|
<div className="mt-2 text-xs text-dark-500">
|
||||||
⚠️ {t('subscription.legacy.currentSubContinues')}
|
{t('subscription.legacy.currentSubContinues')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -2070,20 +2154,64 @@ export default function Subscription() {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-3 text-sm text-dark-300">
|
<div className="flex flex-wrap gap-4 text-sm">
|
||||||
<span className="flex items-center gap-1">
|
{/* Traffic */}
|
||||||
<span className="text-accent-400">{tariff.traffic_limit_label}</span>
|
<div className="flex items-center gap-1.5">
|
||||||
</span>
|
<svg
|
||||||
<span className="flex items-center gap-1">
|
className="h-4 w-4 text-accent-400"
|
||||||
<span className="text-dark-400">
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="font-medium text-dark-200">
|
||||||
|
{tariff.traffic_limit_label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/* Devices */}
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<svg
|
||||||
|
className="h-4 w-4 text-dark-400"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="text-dark-300">
|
||||||
{t('subscription.devices', { count: tariff.device_limit })}
|
{t('subscription.devices', { count: tariff.device_limit })}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</div>
|
||||||
<span className="flex items-center gap-1">
|
{/* Servers */}
|
||||||
<span className="text-dark-400">
|
<div className="flex items-center gap-1.5">
|
||||||
|
<svg
|
||||||
|
className="h-4 w-4 text-dark-400"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M12 21a9.004 9.004 0 008.716-6.747M12 21a9.004 9.004 0 01-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 017.843 4.582M12 3a8.997 8.997 0 00-7.843 4.582m15.686 0A11.953 11.953 0 0112 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0121 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0112 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 013 12c0-1.605.42-3.113 1.157-4.418"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="text-dark-300">
|
||||||
{t('subscription.servers', { count: tariff.servers_count })}
|
{t('subscription.servers', { count: tariff.servers_count })}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Price info - daily or period-based */}
|
{/* Price info - daily or period-based */}
|
||||||
<div className="mt-3 border-t border-dark-700/50 pt-3 text-sm text-dark-400">
|
<div className="mt-3 border-t border-dark-700/50 pt-3 text-sm text-dark-400">
|
||||||
|
|||||||
Reference in New Issue
Block a user