Merge pull request #2 from BEDOLAGA-DEV/dev

Dev
This commit is contained in:
Egor
2026-01-16 08:51:27 +03:00
committed by GitHub
2 changed files with 90 additions and 0 deletions

View File

@@ -83,6 +83,8 @@ export interface TariffDetail {
// Дневной тариф // Дневной тариф
is_daily: boolean is_daily: boolean
daily_price_kopeks: number daily_price_kopeks: number
// Режим сброса трафика
traffic_reset_mode: string | null // 'DAY', 'WEEK', 'MONTH', 'NO_RESET', null = глобальная настройка
created_at: string created_at: string
updated_at: string | null updated_at: string | null
} }
@@ -117,6 +119,8 @@ export interface TariffCreateRequest {
// Дневной тариф // Дневной тариф
is_daily?: boolean is_daily?: boolean
daily_price_kopeks?: number daily_price_kopeks?: number
// Режим сброса трафика
traffic_reset_mode?: string | null
} }
export interface TariffUpdateRequest { export interface TariffUpdateRequest {
@@ -150,6 +154,8 @@ export interface TariffUpdateRequest {
// Дневной тариф // Дневной тариф
is_daily?: boolean is_daily?: boolean
daily_price_kopeks?: number daily_price_kopeks?: number
// Режим сброса трафика
traffic_reset_mode?: string | null
} }
export interface TariffToggleResponse { export interface TariffToggleResponse {

View File

@@ -155,6 +155,9 @@ function PeriodTariffModal({ tariff, servers, onSave, onClose, isLoading }: Peri
tariff?.traffic_topup_packages || {} tariff?.traffic_topup_packages || {}
) )
// Режим сброса трафика
const [trafficResetMode, setTrafficResetMode] = useState<string | null>(tariff?.traffic_reset_mode || null)
// Новый период для добавления // Новый период для добавления
const [newPeriodDays, setNewPeriodDays] = useState(30) const [newPeriodDays, setNewPeriodDays] = useState(30)
const [newPeriodPrice, setNewPeriodPrice] = useState(300) const [newPeriodPrice, setNewPeriodPrice] = useState(300)
@@ -185,6 +188,7 @@ function PeriodTariffModal({ tariff, servers, onSave, onClose, isLoading }: Peri
max_topup_traffic_gb: maxTopupTrafficGb, max_topup_traffic_gb: maxTopupTrafficGb,
is_daily: false, is_daily: false,
daily_price_kopeks: 0, daily_price_kopeks: 0,
traffic_reset_mode: trafficResetMode,
} }
onSave(data) onSave(data)
} }
@@ -579,6 +583,44 @@ function PeriodTariffModal({ tariff, servers, onSave, onClose, isLoading }: Peri
</div> </div>
)} )}
</div> </div>
{/* Режим сброса трафика */}
<div className="p-4 bg-dark-700/50 rounded-lg">
<h4 className="text-sm font-medium text-dark-200 mb-3">Режим сброса трафика</h4>
<p className="text-xs text-dark-500 mb-3">
Определяет, когда сбрасывается использованный трафик у подписчиков этого тарифа
</p>
<div className="space-y-2">
{[
{ value: null, label: '🌐 Глобальная настройка', desc: 'Использовать значение из конфига бота' },
{ value: 'DAY', label: '📅 Ежедневно', desc: 'Сброс каждый день' },
{ value: 'WEEK', label: '📆 Еженедельно', desc: 'Сброс каждую неделю' },
{ value: 'MONTH', label: '🗓️ Ежемесячно', desc: 'Сброс каждый месяц' },
{ value: 'NO_RESET', label: '🚫 Никогда', desc: 'Трафик не сбрасывается' },
].map(option => (
<button
key={option.value || 'global'}
type="button"
onClick={() => setTrafficResetMode(option.value)}
className={`w-full p-3 rounded-lg text-left transition-colors ${
trafficResetMode === option.value
? 'bg-accent-500/20 border border-accent-500'
: 'bg-dark-600 border border-dark-500 hover:border-dark-400'
}`}
>
<div className="flex items-center justify-between">
<div>
<span className="text-sm text-dark-100">{option.label}</span>
<p className="text-xs text-dark-400 mt-0.5">{option.desc}</p>
</div>
{trafficResetMode === option.value && (
<span className="text-accent-400"><CheckIcon /></span>
)}
</div>
</button>
))}
</div>
</div>
</div> </div>
)} )}
</div> </div>
@@ -635,6 +677,9 @@ function DailyTariffModal({ tariff, servers, onSave, onClose, isLoading }: Daily
tariff?.traffic_topup_packages || {} tariff?.traffic_topup_packages || {}
) )
// Режим сброса трафика
const [trafficResetMode, setTrafficResetMode] = useState<string | null>(tariff?.traffic_reset_mode || null)
const [activeTab, setActiveTab] = useState<'basic' | 'servers' | 'extra'>('basic') const [activeTab, setActiveTab] = useState<'basic' | 'servers' | 'extra'>('basic')
const handleSubmit = () => { const handleSubmit = () => {
@@ -661,6 +706,7 @@ function DailyTariffModal({ tariff, servers, onSave, onClose, isLoading }: Daily
max_topup_traffic_gb: maxTopupTrafficGb, max_topup_traffic_gb: maxTopupTrafficGb,
is_daily: true, is_daily: true,
daily_price_kopeks: dailyPriceKopeks, daily_price_kopeks: dailyPriceKopeks,
traffic_reset_mode: trafficResetMode,
} }
onSave(data) onSave(data)
} }
@@ -969,6 +1015,44 @@ function DailyTariffModal({ tariff, servers, onSave, onClose, isLoading }: Daily
</div> </div>
)} )}
</div> </div>
{/* Режим сброса трафика */}
<div className="p-4 bg-dark-700/50 rounded-lg">
<h4 className="text-sm font-medium text-dark-200 mb-3">Режим сброса трафика</h4>
<p className="text-xs text-dark-500 mb-3">
Определяет, когда сбрасывается использованный трафик у подписчиков этого тарифа
</p>
<div className="space-y-2">
{[
{ value: null, label: '🌐 Глобальная настройка', desc: 'Использовать значение из конфига бота' },
{ value: 'DAY', label: '📅 Ежедневно', desc: 'Сброс каждый день' },
{ value: 'WEEK', label: '📆 Еженедельно', desc: 'Сброс каждую неделю' },
{ value: 'MONTH', label: '🗓️ Ежемесячно', desc: 'Сброс каждый месяц' },
{ value: 'NO_RESET', label: '🚫 Никогда', desc: 'Трафик не сбрасывается' },
].map(option => (
<button
key={option.value || 'global'}
type="button"
onClick={() => setTrafficResetMode(option.value)}
className={`w-full p-3 rounded-lg text-left transition-colors ${
trafficResetMode === option.value
? 'bg-amber-500/20 border border-amber-500'
: 'bg-dark-600 border border-dark-500 hover:border-dark-400'
}`}
>
<div className="flex items-center justify-between">
<div>
<span className="text-sm text-dark-100">{option.label}</span>
<p className="text-xs text-dark-400 mt-0.5">{option.desc}</p>
</div>
{trafficResetMode === option.value && (
<span className="text-amber-400"><CheckIcon /></span>
)}
</div>
</button>
))}
</div>
</div>
</div> </div>
)} )}
</div> </div>