diff --git a/app/modules/loyalty/static/store/js/loyalty-terminal.js b/app/modules/loyalty/static/store/js/loyalty-terminal.js index 688e0f7e..e6dcc314 100644 --- a/app/modules/loyalty/static/store/js/loyalty-terminal.js +++ b/app/modules/loyalty/static/store/js/loyalty-terminal.js @@ -275,7 +275,14 @@ function storeLoyaltyTerminal() { await this.loadRecentTransactions(); } catch (error) { - Utils.showToast(I18n.t('loyalty.store.terminal.transaction_failed', {message: error.message}), 'error'); + // Localise well-known errors by error_code instead of + // showing the raw English message from the API. + if (error.errorCode === 'POINTS_COOLDOWN' || error.errorCode === 'STAMP_COOLDOWN') { + const minutes = error.details?.cooldown_minutes ?? this.program?.cooldown_minutes ?? ''; + Utils.showToast(I18n.t('loyalty.store.terminal.cooldown_wait_minutes', {minutes}), 'warning'); + } else { + Utils.showToast(I18n.t('loyalty.store.terminal.transaction_failed', {message: error.message}), 'error'); + } loyaltyTerminalLog.error('Transaction failed:', error); } finally { this.processing = false; diff --git a/static/shared/js/api-client.js b/static/shared/js/api-client.js index 8d44d57d..a3b5fca4 100644 --- a/static/shared/js/api-client.js +++ b/static/shared/js/api-client.js @@ -171,6 +171,10 @@ class APIClient { const apiError = new Error(errorMessage); apiError.status = response.status; apiError.errorCode = data.error_code; + // Propagate the details payload so callers can localise the + // toast (e.g. "cooldown_ends" / "cooldown_minutes" for + // POINTS_COOLDOWN / STAMP_COOLDOWN). + apiError.details = data.details || null; throw apiError; }