fix: remove duplicate back buttons, improve multi-subscription UX

- Remove custom back buttons from Subscription detail and SubscriptionPurchase
  pages — native Telegram mini-app back button already handles navigation
- SubscriptionListCard: distinct trial badge with star icon and amber styling,
  trial cards get amber border/background for visual differentiation
- SubscriptionPurchase: change "Купить тариф" to "Новый тариф" when adding
  a new tariff in multi-subscription mode
- Subscription detail: show tariff name as title in multi-tariff mode
This commit is contained in:
c0mrade
2026-03-23 21:38:04 +03:00
parent 376e1bb56d
commit 9d3fb37d60
3 changed files with 50 additions and 103 deletions

View File

@@ -19,15 +19,28 @@ function formatDate(iso: string | null, locale?: string): string {
function StatusBadge({
status,
isTrial,
t,
}: {
status: string;
isTrial: boolean;
t: (key: string, fallback: string) => string;
}) {
const isActive = status === 'active' || status === 'trial';
const isLimited = status === 'limited';
const isExpired = status === 'expired' || status === 'disabled';
if (isTrial) {
return (
<span className="inline-flex items-center gap-1 rounded-full border border-amber-400/25 bg-amber-400/10 px-2 py-0.5 text-[10px] font-semibold text-amber-400">
<svg className="h-2.5 w-2.5" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" />
</svg>
{t('subscription.statusTrial', 'Тестовая')}
</span>
);
}
const color = isActive
? 'bg-emerald-400/15 text-emerald-400 border-emerald-400/20'
: isLimited
@@ -35,9 +48,7 @@ function StatusBadge({
: 'bg-red-400/15 text-red-400 border-red-400/20';
const label = isActive
? status === 'trial'
? t('subscription.statusTrial', 'Тестовая')
: t('subscription.statusActive', 'Активна')
? t('subscription.statusActive', 'Активна')
: isLimited
? t('subscription.statusLimited', 'Ограничена')
: isExpired
@@ -70,6 +81,7 @@ export default function SubscriptionListCard({
onClick();
};
const isTrial = subscription.is_trial;
const isActive = subscription.status === 'active' || subscription.status === 'trial';
const isExpired = subscription.status === 'expired' || subscription.status === 'disabled';
const trafficLimit = subscription.traffic_limit_gb;
@@ -83,18 +95,27 @@ export default function SubscriptionListCard({
const trafficColor =
trafficPercent >= 90 ? 'bg-red-400' : trafficPercent >= 70 ? 'bg-amber-400' : 'bg-emerald-400';
const borderColor = isTrial
? 'rgba(251,191,36,0.2)'
: isExpired
? 'rgba(255,59,92,0.15)'
: g.cardBorder;
const bgColor = isTrial
? isDark
? 'rgba(251,191,36,0.04)'
: 'rgba(251,191,36,0.03)'
: isExpired
? isDark
? 'rgba(255,59,92,0.04)'
: 'rgba(255,59,92,0.03)'
: g.cardBg;
return (
<button
onClick={handleClick}
className="w-full rounded-2xl border p-4 text-left transition-all duration-200 hover:scale-[1.01] active:scale-[0.99]"
style={{
background: isExpired
? isDark
? 'rgba(255,59,92,0.04)'
: 'rgba(255,59,92,0.03)'
: g.cardBg,
borderColor: isExpired ? 'rgba(255,59,92,0.15)' : g.cardBorder,
}}
style={{ background: bgColor, borderColor }}
>
{/* Header: tariff name + status badge + chevron */}
<div className="flex items-center justify-between gap-2">
@@ -102,7 +123,7 @@ export default function SubscriptionListCard({
<span className="truncate text-base font-semibold" style={{ color: g.text }}>
{subscription.tariff_name || t('subscription.defaultName', 'Подписка')}
</span>
<StatusBadge status={subscription.status} t={t} />
<StatusBadge status={subscription.status} isTrial={isTrial} t={t} />
</div>
<svg
className="h-4 w-4 shrink-0 opacity-30"

View File

@@ -479,34 +479,12 @@ export default function Subscription() {
return (
<div className="space-y-6">
{/* Multi-tariff: back navigation + tariff name */}
{isMultiTariff && subscriptionId ? (
<div>
<button
onClick={() => navigate('/subscriptions')}
className="mb-2 flex items-center gap-1.5 text-sm text-dark-50/50 transition-colors hover:text-dark-50/80"
>
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M15 18l-6-6 6-6" />
</svg>
{t('subscription.backToList', 'Мои подписки')}
</button>
{/* Page title — native Telegram back button handles navigation */}
<h1 className="text-2xl font-bold text-dark-50 sm:text-3xl">
{subscription?.tariff_name || t('subscription.title')}
{isMultiTariff && subscription?.tariff_name
? subscription.tariff_name
: t('subscription.title')}
</h1>
</div>
) : (
<h1 className="text-2xl font-bold text-dark-50 sm:text-3xl">{t('subscription.title')}</h1>
)}
{/* Current Subscription */}
{subscription ? (

View File

@@ -383,34 +383,7 @@ export default function SubscriptionPurchase() {
if (optionsError || (!purchaseOptions && !optionsLoading)) {
return (
<div className="space-y-6">
<div className="flex items-center gap-3">
<button
onClick={() => navigate('/subscription')}
aria-label="Back"
className="flex h-9 w-9 items-center justify-center rounded-xl transition-colors"
style={{
background: g.innerBg,
border: `1px solid ${g.innerBorder}`,
}}
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="text-dark-50/60"
>
<path d="M19 12H5M12 19l-7-7 7-7" />
</svg>
</button>
<h1 className="text-2xl font-bold text-dark-50 sm:text-3xl">
{t('subscription.extend')}
</h1>
</div>
<h1 className="text-2xl font-bold text-dark-50 sm:text-3xl">{t('subscription.extend')}</h1>
<div
className="rounded-3xl p-6 text-center"
style={{
@@ -434,41 +407,16 @@ export default function SubscriptionPurchase() {
return (
<div className="space-y-6">
{/* Header with back link */}
<div className="flex items-center gap-3">
<button
onClick={() => navigate('/subscriptions')}
aria-label="Back"
className="flex h-9 w-9 items-center justify-center rounded-xl transition-colors"
style={{
background: g.innerBg,
border: `1px solid ${g.innerBorder}`,
}}
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="text-dark-50/60"
>
<path d="M19 12H5M12 19l-7-7 7-7" />
</svg>
</button>
{/* Header — native Telegram back button handles navigation */}
<h1 className="text-2xl font-bold text-dark-50 sm:text-3xl">
{isMultiTariff && !subscriptionId
? t('subscription.buyTariff', 'Купить тариф')
? t('subscription.newTariff', 'Новый тариф')
: subscription?.is_daily && !subscription?.is_trial
? t('subscription.switchTariff.title')
: subscription && !subscription.is_trial
? t('subscription.extend')
: t('subscription.getSubscription')}
</h1>
</div>
{/* Tariffs Section */}
{isTariffsMode && tariffs.length > 0 && (