mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
@@ -216,6 +216,7 @@
|
||||
"pausedMessage": "Subscription paused",
|
||||
"resumedMessage": "Subscription resumed",
|
||||
"dailyOnly": "Pause is only available for daily tariffs",
|
||||
"insufficientBalance": "Insufficient balance to resume subscription",
|
||||
"pausedInfo": "Subscription paused",
|
||||
"pausedDescription": "Charges stopped. Subscription will be active until",
|
||||
"nextCharge": "Until next charge",
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
"pausedMessage": "Подписка приостановлена",
|
||||
"resumedMessage": "Подписка возобновлена",
|
||||
"dailyOnly": "Пауза доступна только для суточных тарифов",
|
||||
"insufficientBalance": "Недостаточно средств для возобновления подписки",
|
||||
"pausedInfo": "Подписка приостановлена",
|
||||
"pausedDescription": "Списания остановлены. Подписка будет действовать до",
|
||||
"nextCharge": "До следующего списания",
|
||||
|
||||
@@ -136,7 +136,7 @@ function PeriodTariffModal({ tariff, servers, onSave, onClose, isLoading }: Peri
|
||||
|
||||
const [name, setName] = useState(tariff?.name || '')
|
||||
const [description, setDescription] = useState(tariff?.description || '')
|
||||
const [trafficLimitGb, setTrafficLimitGb] = useState(tariff?.traffic_limit_gb || 100)
|
||||
const [trafficLimitGb, setTrafficLimitGb] = useState(tariff?.traffic_limit_gb ?? 100)
|
||||
const [deviceLimit, setDeviceLimit] = useState(tariff?.device_limit || 1)
|
||||
const [devicePriceKopeks, setDevicePriceKopeks] = useState(tariff?.device_price_kopeks || 0)
|
||||
const [maxDeviceLimit, setMaxDeviceLimit] = useState(tariff?.max_device_limit || 0)
|
||||
@@ -182,7 +182,7 @@ function PeriodTariffModal({ tariff, servers, onSave, onClose, isLoading }: Peri
|
||||
device_price_kopeks: devicePriceKopeks > 0 ? devicePriceKopeks : undefined,
|
||||
max_device_limit: maxDeviceLimit > 0 ? maxDeviceLimit : undefined,
|
||||
tier_level: tierLevel,
|
||||
period_prices: periodPrices.filter(p => p.price_kopeks > 0),
|
||||
period_prices: periodPrices.filter(p => p.price_kopeks >= 0),
|
||||
allowed_squads: selectedSquads,
|
||||
traffic_topup_enabled: trafficTopupEnabled,
|
||||
traffic_topup_packages: trafficTopupPackages,
|
||||
@@ -757,7 +757,7 @@ function DailyTariffModal({ tariff, servers, onSave, onClose, isLoading }: Daily
|
||||
|
||||
const [name, setName] = useState(tariff?.name || '')
|
||||
const [description, setDescription] = useState(tariff?.description || '')
|
||||
const [trafficLimitGb, setTrafficLimitGb] = useState(tariff?.traffic_limit_gb || 100)
|
||||
const [trafficLimitGb, setTrafficLimitGb] = useState(tariff?.traffic_limit_gb ?? 100)
|
||||
const [deviceLimit, setDeviceLimit] = useState(tariff?.device_limit || 1)
|
||||
const [devicePriceKopeks, setDevicePriceKopeks] = useState(tariff?.device_price_kopeks || 0)
|
||||
const [maxDeviceLimit, setMaxDeviceLimit] = useState(tariff?.max_device_limit || 0)
|
||||
|
||||
@@ -21,6 +21,20 @@ const getErrorMessage = (error: unknown): string => {
|
||||
return 'Произошла ошибка'
|
||||
}
|
||||
|
||||
// Helper to extract insufficient balance error details
|
||||
const getInsufficientBalanceError = (error: unknown): { required: number; balance: number } | null => {
|
||||
if (error instanceof AxiosError) {
|
||||
const detail = error.response?.data?.detail
|
||||
if (typeof detail === 'object' && detail?.code === 'insufficient_balance') {
|
||||
return {
|
||||
required: detail.required || 0,
|
||||
balance: detail.balance || 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Icons
|
||||
const CopyIcon = () => (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||
@@ -742,11 +756,26 @@ export default function Subscription() {
|
||||
</div>
|
||||
|
||||
{/* Pause mutation error */}
|
||||
{pauseMutation.isError && (
|
||||
<div className="mt-4 text-sm text-error-400 bg-error-500/10 px-4 py-3 rounded-lg text-center">
|
||||
{getErrorMessage(pauseMutation.error)}
|
||||
</div>
|
||||
)}
|
||||
{pauseMutation.isError && (() => {
|
||||
const balanceError = getInsufficientBalanceError(pauseMutation.error)
|
||||
if (balanceError) {
|
||||
const missingAmount = balanceError.required - balanceError.balance
|
||||
return (
|
||||
<div className="mt-4">
|
||||
<InsufficientBalancePrompt
|
||||
missingAmountKopeks={missingAmount}
|
||||
message={t('subscription.pause.insufficientBalance')}
|
||||
compact
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="mt-4 text-sm text-error-400 bg-error-500/10 px-4 py-3 rounded-lg text-center">
|
||||
{getErrorMessage(pauseMutation.error)}
|
||||
</div>
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Paused info or Next charge progress bar */}
|
||||
{subscription.is_daily_paused ? (
|
||||
@@ -2276,10 +2305,17 @@ export default function Subscription() {
|
||||
<div className="text-sm text-success-400 text-center">{preview.discount_label}</div>
|
||||
)}
|
||||
|
||||
{!preview.can_purchase && preview.status_message && (
|
||||
<div className="text-sm text-error-400 bg-error-500/10 px-4 py-3 rounded-lg text-center">
|
||||
{preview.status_message}
|
||||
</div>
|
||||
{!preview.can_purchase && (
|
||||
preview.missing_amount_kopeks > 0 ? (
|
||||
<InsufficientBalancePrompt
|
||||
missingAmountKopeks={preview.missing_amount_kopeks}
|
||||
compact
|
||||
/>
|
||||
) : preview.status_message ? (
|
||||
<div className="text-sm text-error-400 bg-error-500/10 px-4 py-3 rounded-lg text-center">
|
||||
{preview.status_message}
|
||||
</div>
|
||||
) : null
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user