fix(sbp-recurring): toast ошибки отмены + per-sub ключ inline-confirm в админке

- cancelSbpMutation: onError-тост с detail бэкенда (зеркально enable) —
  молчаливый провал отмены выглядел как успех
- SubscriptionTab: ключ подтверждения cancelSbpRecurring_{subId} —
  взведённый confirm не переживает переключение подписки в пикере
- Локали: subscription.sbpRecurring.cancelError (en/ru/zh/fa)
This commit is contained in:
Fringg
2026-07-24 07:28:50 +03:00
parent 9fb80a6af4
commit 42a7190241
6 changed files with 21 additions and 3 deletions

View File

@@ -408,15 +408,19 @@ export function SubscriptionTab(props: SubscriptionTabProps) {
</div> </div>
{hasPermission('users:subscription') && ( {hasPermission('users:subscription') && (
<button <button
onClick={() => onInlineConfirm('cancelSbpRecurring', onCancelSbpRecurring)} // Per-subscription confirm key: an armed confirm must not
// survive switching to another subscription in the picker.
onClick={() =>
onInlineConfirm(`cancelSbpRecurring_${selectedSub.id}`, onCancelSbpRecurring)
}
disabled={actionLoading} disabled={actionLoading}
className={`rounded-lg px-3 py-2 text-sm font-medium transition-all disabled:opacity-50 ${ className={`rounded-lg px-3 py-2 text-sm font-medium transition-all disabled:opacity-50 ${
confirmingAction === 'cancelSbpRecurring' confirmingAction === `cancelSbpRecurring_${selectedSub.id}`
? 'bg-warning-500 text-white' ? 'bg-warning-500 text-white'
: 'bg-warning-500/15 text-warning-400 hover:bg-warning-500/25' : 'bg-warning-500/15 text-warning-400 hover:bg-warning-500/25'
}`} }`}
> >
{confirmingAction === 'cancelSbpRecurring' {confirmingAction === `cancelSbpRecurring_${selectedSub.id}`
? t('admin.users.detail.actions.areYouSure') ? t('admin.users.detail.actions.areYouSure')
: t('admin.users.detail.subscription.sbpCancel')} : t('admin.users.detail.subscription.sbpCancel')}
</button> </button>

View File

@@ -683,6 +683,7 @@
"confirmCancel": "Disable SBP auto-payment? Your subscription will no longer renew automatically via SBP.", "confirmCancel": "Disable SBP auto-payment? Your subscription will no longer renew automatically via SBP.",
"cancelled": "SBP auto-payment disabled", "cancelled": "SBP auto-payment disabled",
"enableError": "Failed to connect SBP auto-payment", "enableError": "Failed to connect SBP auto-payment",
"cancelError": "Failed to cancel SBP auto-payment",
"statusPending": "Waiting for confirmation in your banking app", "statusPending": "Waiting for confirmation in your banking app",
"statusActive": "Active", "statusActive": "Active",
"statusPastDue": "Payment failed — please retry", "statusPastDue": "Payment failed — please retry",

View File

@@ -582,6 +582,7 @@
"confirmCancel": "پرداخت خودکار SBP غیرفعال شود؟ اشتراک شما دیگر به‌صورت خودکار از طریق SBP تمدید نخواهد شد.", "confirmCancel": "پرداخت خودکار SBP غیرفعال شود؟ اشتراک شما دیگر به‌صورت خودکار از طریق SBP تمدید نخواهد شد.",
"cancelled": "پرداخت خودکار SBP غیرفعال شد", "cancelled": "پرداخت خودکار SBP غیرفعال شد",
"enableError": "اتصال پرداخت خودکار SBP ناموفق بود", "enableError": "اتصال پرداخت خودکار SBP ناموفق بود",
"cancelError": "لغو پرداخت خودکار SBP ناموفق بود",
"statusPending": "در انتظار تأیید در اپلیکیشن بانک", "statusPending": "در انتظار تأیید در اپلیکیشن بانک",
"statusActive": "فعال", "statusActive": "فعال",
"statusPastDue": "پرداخت ناموفق بود — دوباره تلاش کنید", "statusPastDue": "پرداخت ناموفق بود — دوباره تلاش کنید",

View File

@@ -702,6 +702,7 @@
"confirmCancel": "Отключить автоплатёж по СБП? Подписка больше не будет продлеваться автоматически через СБП.", "confirmCancel": "Отключить автоплатёж по СБП? Подписка больше не будет продлеваться автоматически через СБП.",
"cancelled": "Автоплатёж по СБП отключён", "cancelled": "Автоплатёж по СБП отключён",
"enableError": "Не удалось подключить автоплатёж по СБП", "enableError": "Не удалось подключить автоплатёж по СБП",
"cancelError": "Не удалось отменить автоплатёж по СБП",
"statusPending": "Ожидает подтверждения в приложении банка", "statusPending": "Ожидает подтверждения в приложении банка",
"statusActive": "Активен", "statusActive": "Активен",
"statusPastDue": "Платёж не прошёл — попробуйте снова", "statusPastDue": "Платёж не прошёл — попробуйте снова",

View File

@@ -582,6 +582,7 @@
"confirmCancel": "关闭 SBP 自动扣款?您的订阅将不再通过 SBP 自动续订。", "confirmCancel": "关闭 SBP 自动扣款?您的订阅将不再通过 SBP 自动续订。",
"cancelled": "SBP 自动扣款已关闭", "cancelled": "SBP 自动扣款已关闭",
"enableError": "开通 SBP 自动扣款失败", "enableError": "开通 SBP 自动扣款失败",
"cancelError": "取消 SBP 自动扣款失败",
"statusPending": "等待银行应用确认", "statusPending": "等待银行应用确认",
"statusActive": "已启用", "statusActive": "已启用",
"statusPastDue": "扣款失败 — 请重试", "statusPastDue": "扣款失败 — 请重试",

View File

@@ -354,6 +354,16 @@ export default function Subscription() {
duration: 3000, duration: 3000,
}); });
}, },
onError: (error: unknown) => {
const detail = (error as { response?: { data?: { detail?: unknown } } })?.response?.data
?.detail;
showToast({
type: 'error',
title: typeof detail === 'string' ? detail : t('subscription.sbpRecurring.cancelError'),
message: '',
duration: 3000,
});
},
}); });
const handleCancelSbp = async () => { const handleCancelSbp = async () => {