fix(sbp-recurring): компактный layout СБП-блока на десктопе

Кнопки растягивались w-full на всю ширину карточки подписки (~1600px на
десктопе) — гигантская плашка вместо контрола. Теперь заголовок и статус
слева, компактное действие справа — зеркально соседнему тогглу
«Автопродление»; на мобиле кнопка по-прежнему на всю ширину
(w-full sm:w-auto).
This commit is contained in:
Fringg
2026-07-24 17:45:11 +03:00
parent 6c6901db66
commit faf4c450b0

View File

@@ -1177,57 +1177,25 @@ export default function Subscription() {
border: `1px solid ${g.innerBorder}`, border: `1px solid ${g.innerBorder}`,
}} }}
> >
{/* Заголовок и статус слева, компактное действие справа —
зеркально соседнему тогглу «Автопродление». На мобиле
кнопка падает вниз на всю ширину (w-full sm:w-auto). */}
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<div className="text-sm font-semibold text-dark-50"> <div className="text-sm font-semibold text-dark-50">
{t('subscription.sbpRecurring.title')} {t('subscription.sbpRecurring.title')}
</div> </div>
{sbpUiStateValue === 'off' && ( {sbpUiStateValue === 'off' && (
<>
<div className="mt-0.5 text-[11px] text-dark-50/30"> <div className="mt-0.5 text-[11px] text-dark-50/30">
{t('subscription.sbpRecurring.autopayHint')} {t('subscription.sbpRecurring.autopayHint')}
</div> </div>
<button
onClick={() => enableSbpMutation.mutate()}
disabled={enableSbpMutation.isPending}
className="mt-3 w-full rounded-xl bg-accent-500 px-4 py-2.5 text-sm font-medium text-on-accent transition-opacity disabled:opacity-50"
>
{enableSbpMutation.isPending ? (
<span className="mx-auto block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
) : (
t('subscription.sbpRecurring.connect')
)} )}
</button>
</>
)}
{sbpUiStateValue === 'pending' && ( {sbpUiStateValue === 'pending' && (
<>
<div className="mt-0.5 text-[11px] text-dark-50/30"> <div className="mt-0.5 text-[11px] text-dark-50/30">
{t('subscription.sbpRecurring.statusPending')} {t('subscription.sbpRecurring.statusPending')}
</div> </div>
{sbpInfo?.redirect_url && (
<button
onClick={() => {
if (sbpInfo.redirect_url) {
openPaymentUrl(sbpInfo.redirect_url, platform, openLink);
}
}}
className="mt-3 w-full rounded-xl bg-accent-500 px-4 py-2.5 text-sm font-medium text-on-accent transition-opacity"
>
{t('subscription.sbpRecurring.confirmInBank')}
</button>
)} )}
<button
onClick={handleCancelSbp}
disabled={cancelSbpMutation.isPending}
className="mt-2 text-[11px] font-medium transition-colors disabled:opacity-50"
style={{ color: 'rgb(var(--color-critical-500))' }}
>
{t('subscription.sbpRecurring.cancel')}
</button>
</>
)}
{sbpUiStateValue === 'active' && sbpInfo && ( {sbpUiStateValue === 'active' && sbpInfo && (
<> <>
<div className="mt-0.5 text-[11px] text-dark-50/30"> <div className="mt-0.5 text-[11px] text-dark-50/30">
@@ -1239,39 +1207,78 @@ export default function Subscription() {
{sbpInfo.next_charge_at && ( {sbpInfo.next_charge_at && (
<div className="mt-0.5 text-[11px] text-dark-50/30"> <div className="mt-0.5 text-[11px] text-dark-50/30">
{t('subscription.sbpRecurring.nextCharge', { {t('subscription.sbpRecurring.nextCharge', {
date: new Date(sbpInfo.next_charge_at).toLocaleDateString(uiLocale(), { date: new Date(sbpInfo.next_charge_at).toLocaleDateString(
uiLocale(),
{
day: '2-digit', day: '2-digit',
month: '2-digit', month: '2-digit',
year: 'numeric', year: 'numeric',
}), },
),
})} })}
</div> </div>
)} )}
</>
)}
{sbpUiStateValue === 'past_due' && (
<div className="mt-0.5 text-[11px] font-medium text-warning-400">
{t('subscription.sbpRecurring.statusPastDue')}
</div>
)}
</div>
<div className="flex shrink-0 flex-col gap-2 sm:items-end">
{sbpUiStateValue === 'off' && (
<button
onClick={() => enableSbpMutation.mutate()}
disabled={enableSbpMutation.isPending}
className="w-full whitespace-nowrap rounded-xl bg-accent-500 px-5 py-2.5 text-sm font-medium text-on-accent transition-opacity disabled:opacity-50 sm:w-auto"
>
{enableSbpMutation.isPending ? (
<span className="mx-auto block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
) : (
t('subscription.sbpRecurring.connect')
)}
</button>
)}
{sbpUiStateValue === 'pending' && (
<>
{sbpInfo?.redirect_url && (
<button
onClick={() => {
if (sbpInfo.redirect_url) {
openPaymentUrl(sbpInfo.redirect_url, platform, openLink);
}
}}
className="w-full whitespace-nowrap rounded-xl bg-accent-500 px-5 py-2.5 text-sm font-medium text-on-accent transition-opacity sm:w-auto"
>
{t('subscription.sbpRecurring.confirmInBank')}
</button>
)}
<button <button
onClick={handleCancelSbp} onClick={handleCancelSbp}
disabled={cancelSbpMutation.isPending} disabled={cancelSbpMutation.isPending}
className="mt-3 w-full rounded-xl border border-error-500/30 bg-error-500/10 px-4 py-2.5 text-sm font-medium text-error-400 transition-colors hover:bg-error-500/20 disabled:opacity-50" className="text-[11px] font-medium transition-colors disabled:opacity-50 sm:text-right"
style={{ color: 'rgb(var(--color-critical-500))' }}
> >
{t('subscription.sbpRecurring.cancel')} {t('subscription.sbpRecurring.cancel')}
</button> </button>
</> </>
)} )}
{sbpUiStateValue === 'past_due' && ( {(sbpUiStateValue === 'active' || sbpUiStateValue === 'past_due') && (
<>
<div className="mt-0.5 text-[11px] font-medium text-warning-400">
{t('subscription.sbpRecurring.statusPastDue')}
</div>
<button <button
onClick={handleCancelSbp} onClick={handleCancelSbp}
disabled={cancelSbpMutation.isPending} disabled={cancelSbpMutation.isPending}
className="mt-3 w-full rounded-xl border border-error-500/30 bg-error-500/10 px-4 py-2.5 text-sm font-medium text-error-400 transition-colors hover:bg-error-500/20 disabled:opacity-50" className="w-full whitespace-nowrap rounded-xl border border-error-500/30 bg-error-500/10 px-5 py-2.5 text-sm font-medium text-error-400 transition-colors hover:bg-error-500/20 disabled:opacity-50 sm:w-auto"
> >
{t('subscription.sbpRecurring.cancel')} {t('subscription.sbpRecurring.cancel')}
</button> </button>
</>
)} )}
</div> </div>
</div>
</div>
)} )}
</div> </div>
); );