fix: mobile layout and period label translations for quick purchase landing

- Add i18n period labels (ru/en/zh/fa) instead of backend English-only labels
- Period tabs wrap on mobile instead of horizontal scroll
- Prevent horizontal overflow shifting the layout
This commit is contained in:
Fringg
2026-03-07 04:04:39 +03:00
parent dfa7a09a7c
commit 6d5c6fb9b3
5 changed files with 99 additions and 9 deletions

View File

@@ -3995,6 +3995,24 @@
"giftSentSuccess": "Gift sent!",
"giftSentDesc": "Recipient will be notified by email",
"autoLoginFailed": "Auto-login failed",
"autoLoginProcessing": "Signing in..."
"autoLoginProcessing": "Signing in...",
"periodLabels": {
"d1": "1 day",
"d2": "2 days",
"d3": "3 days",
"d5": "5 days",
"d7": "1 week",
"d14": "2 weeks",
"d30": "1 month",
"d60": "2 months",
"d90": "3 months",
"d180": "6 months",
"d365": "1 year",
"d456": "1 year + 3 mo.",
"nDays_one": "{{count}} day",
"nDays_other": "{{count}} days",
"nMonths_one": "{{count}} month",
"nMonths_other": "{{count}} months"
}
}
}

View File

@@ -3546,6 +3546,22 @@
"giftSentSuccess": "هدیه ارسال شد!",
"giftSentDesc": "گیرنده از طریق ایمیل مطلع خواهد شد",
"autoLoginFailed": "ورود خودکار ناموفق بود",
"autoLoginProcessing": "در حال ورود..."
"autoLoginProcessing": "در حال ورود...",
"periodLabels": {
"d1": "۱ روز",
"d2": "۲ روز",
"d3": "۳ روز",
"d5": "۵ روز",
"d7": "۱ هفته",
"d14": "۲ هفته",
"d30": "۱ ماه",
"d60": "۲ ماه",
"d90": "۳ ماه",
"d180": "۶ ماه",
"d365": "۱ سال",
"d456": "۱ سال و ۳ ماه",
"nDays": "{{count}} روز",
"nMonths": "{{count}} ماه"
}
}
}

View File

@@ -4554,6 +4554,26 @@
"giftSentSuccess": "Подарок отправлен!",
"giftSentDesc": "Получатель получит уведомление на email",
"autoLoginFailed": "Не удалось выполнить автоматический вход",
"autoLoginProcessing": "Выполняется вход..."
"autoLoginProcessing": "Выполняется вход...",
"periodLabels": {
"d1": "1 день",
"d2": "2 дня",
"d3": "3 дня",
"d5": "5 дней",
"d7": "1 неделя",
"d14": "2 недели",
"d30": "1 месяц",
"d60": "2 месяца",
"d90": "3 месяца",
"d180": "6 месяцев",
"d365": "1 год",
"d456": "1 год + 3 мес.",
"nDays_one": "{{count}} день",
"nDays_few": "{{count}} дня",
"nDays_many": "{{count}} дней",
"nMonths_one": "{{count}} месяц",
"nMonths_few": "{{count}} месяца",
"nMonths_many": "{{count}} месяцев"
}
}
}

View File

@@ -3545,6 +3545,22 @@
"giftSentSuccess": "礼物已发送!",
"giftSentDesc": "收件人将通过邮件收到通知",
"autoLoginFailed": "自动登录失败",
"autoLoginProcessing": "正在登录..."
"autoLoginProcessing": "正在登录...",
"periodLabels": {
"d1": "1天",
"d2": "2天",
"d3": "3天",
"d5": "5天",
"d7": "1周",
"d14": "2周",
"d30": "1个月",
"d60": "2个月",
"d90": "3个月",
"d180": "6个月",
"d365": "1年",
"d456": "1年3个月",
"nDays": "{{count}}天",
"nMonths": "{{count}}个月"
}
}
}

View File

@@ -31,6 +31,22 @@ function isValidContact(value: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed);
}
function formatPeriodLabel(
days: number,
t: (key: string, options?: Record<string, unknown>) => string,
): string {
const key = `landing.periodLabels.d${days}`;
const result = t(key);
if (result !== key) return result;
const months = Math.floor(days / 30);
const remainder = days % 30;
if (months > 0 && remainder === 0) {
return t('landing.periodLabels.nMonths', { count: months });
}
return t('landing.periodLabels.nDays', { count: days });
}
// ============================================================
// Sub-components
// ============================================================
@@ -82,21 +98,23 @@ function PeriodTabs({
selectedDays: number;
onSelect: (days: number) => void;
}) {
const { t } = useTranslation();
return (
<div className="scrollbar-none flex gap-2 overflow-x-auto pb-1">
<div className="flex flex-wrap gap-2">
{periods.map((period) => (
<button
key={period.days}
type="button"
onClick={() => onSelect(period.days)}
className={cn(
'whitespace-nowrap rounded-full px-5 py-2.5 text-sm font-medium transition-all duration-200',
'whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium transition-all duration-200',
selectedDays === period.days
? 'bg-accent-500 text-white shadow-lg shadow-accent-500/25'
: 'bg-dark-800/50 text-dark-300 hover:bg-dark-700/50 hover:text-dark-100',
)}
>
{period.label}
{formatPeriodLabel(period.days, t)}
</button>
))}
</div>
@@ -469,7 +487,9 @@ function SummaryCard({
<p className="text-xs font-medium uppercase tracking-wider text-dark-500">
{t('landing.period', 'Period')}
</p>
<p className="mt-1 text-sm text-dark-200">{selectedPeriod.label}</p>
<p className="mt-1 text-sm text-dark-200">
{formatPeriodLabel(selectedPeriod.days, t)}
</p>
</div>
)}
<div className="border-t border-dark-800/50 pt-4">
@@ -788,7 +808,7 @@ export default function QuickPurchase() {
const showTariffCards = visibleTariffs.length > 1;
return (
<div className="min-h-dvh bg-dark-950">
<div className="min-h-dvh overflow-x-hidden bg-dark-950">
<div className="mx-auto max-w-5xl px-4 py-8 sm:px-6 lg:px-8">
{/* Language switcher */}
<div className="mb-4 flex justify-end">