mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
feat: tariff selector for trial subscription promo codes
- Add tariff_id/tariff_name to PromoCode types - AdminPromocodeCreate: tariff dropdown for trial_subscription type - Shows default trial tariff or warns if none configured
This commit is contained in:
@@ -25,6 +25,8 @@ export interface PromoCode {
|
|||||||
valid_from: string;
|
valid_from: string;
|
||||||
valid_until: string | null;
|
valid_until: string | null;
|
||||||
promo_group_id: number | null;
|
promo_group_id: number | null;
|
||||||
|
tariff_id: number | null;
|
||||||
|
tariff_name: string | null;
|
||||||
created_by: number | null;
|
created_by: number | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
@@ -63,6 +65,7 @@ export interface PromoCodeCreateRequest {
|
|||||||
is_active?: boolean;
|
is_active?: boolean;
|
||||||
first_purchase_only?: boolean;
|
first_purchase_only?: boolean;
|
||||||
promo_group_id?: number | null;
|
promo_group_id?: number | null;
|
||||||
|
tariff_id?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PromoCodeUpdateRequest {
|
export interface PromoCodeUpdateRequest {
|
||||||
@@ -76,6 +79,7 @@ export interface PromoCodeUpdateRequest {
|
|||||||
is_active?: boolean;
|
is_active?: boolean;
|
||||||
first_purchase_only?: boolean;
|
first_purchase_only?: boolean;
|
||||||
promo_group_id?: number | null;
|
promo_group_id?: number | null;
|
||||||
|
tariff_id?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============== PromoGroup Types ==============
|
// ============== PromoGroup Types ==============
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ export default function AdminPromocodeCreate() {
|
|||||||
const [firstPurchaseOnly, setFirstPurchaseOnly] = useState(false);
|
const [firstPurchaseOnly, setFirstPurchaseOnly] = useState(false);
|
||||||
const [validUntil, setValidUntil] = useState('');
|
const [validUntil, setValidUntil] = useState('');
|
||||||
const [promoGroupId, setPromoGroupId] = useState<number | null>(null);
|
const [promoGroupId, setPromoGroupId] = useState<number | null>(null);
|
||||||
|
const [tariffId, setTariffId] = useState<number | null>(null);
|
||||||
|
|
||||||
// Fetch promo groups (for promo_group type)
|
// Fetch promo groups (for promo_group type)
|
||||||
const { data: promoGroupsData } = useQuery({
|
const { data: promoGroupsData } = useQuery({
|
||||||
@@ -104,6 +105,7 @@ export default function AdminPromocodeCreate() {
|
|||||||
setFirstPurchaseOnly(data.first_purchase_only || false);
|
setFirstPurchaseOnly(data.first_purchase_only || false);
|
||||||
setValidUntil(data.valid_until ? data.valid_until.split('T')[0] : '');
|
setValidUntil(data.valid_until ? data.valid_until.split('T')[0] : '');
|
||||||
setPromoGroupId(data.promo_group_id || null);
|
setPromoGroupId(data.promo_group_id || null);
|
||||||
|
setTariffId(data.tariff_id || null);
|
||||||
return data;
|
return data;
|
||||||
}, []),
|
}, []),
|
||||||
});
|
});
|
||||||
@@ -147,6 +149,7 @@ export default function AdminPromocodeCreate() {
|
|||||||
first_purchase_only: firstPurchaseOnly,
|
first_purchase_only: firstPurchaseOnly,
|
||||||
valid_until: validUntil ? new Date(validUntil).toISOString() : null,
|
valid_until: validUntil ? new Date(validUntil).toISOString() : null,
|
||||||
promo_group_id: type === 'promo_group' ? promoGroupId : null,
|
promo_group_id: type === 'promo_group' ? promoGroupId : null,
|
||||||
|
...(type === 'trial_subscription' && tariffId ? { tariff_id: tariffId } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
@@ -312,24 +315,33 @@ export default function AdminPromocodeCreate() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{type === 'trial_subscription' && (
|
{type === 'trial_subscription' && (
|
||||||
<div className="rounded-lg border border-dark-600 bg-dark-700/50 p-3">
|
<div>
|
||||||
{trialTariff ? (
|
<label className="mb-2 block text-sm font-medium text-dark-300">
|
||||||
<div className="text-sm">
|
{t('admin.promocodes.form.tariff', 'Тариф')}
|
||||||
<span className="text-dark-400">
|
</label>
|
||||||
{t('admin.promocodes.form.trialTariffInfo', 'Будет выдан тариф:')}
|
<select
|
||||||
</span>{' '}
|
value={tariffId || ''}
|
||||||
<span className="font-medium text-accent-400">{trialTariff.name}</span>
|
onChange={(e) => setTariffId(e.target.value ? parseInt(e.target.value) : null)}
|
||||||
<span className="text-dark-500">
|
className="input"
|
||||||
{' '}
|
>
|
||||||
({trialTariff.traffic_limit_gb} GB, {trialTariff.device_limit}{' '}
|
<option value="">
|
||||||
{t('admin.promocodes.form.devices', 'устр.')})
|
{trialTariff
|
||||||
</span>
|
? t('admin.promocodes.form.defaultTrialTariff', 'По умолчанию: {{name}}', {
|
||||||
</div>
|
name: trialTariff.name,
|
||||||
) : (
|
})
|
||||||
<div className="text-sm text-warning-400">
|
: t('admin.promocodes.form.selectTariff', '— Выберите тариф —')}
|
||||||
|
</option>
|
||||||
|
{tariffsData?.tariffs?.map((tariff) => (
|
||||||
|
<option key={tariff.id} value={tariff.id}>
|
||||||
|
{tariff.name} ({tariff.traffic_limit_gb} GB, {tariff.device_limit} устр.)
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{!tariffId && !trialTariff && (
|
||||||
|
<div className="mt-1 text-xs text-warning-400">
|
||||||
{t(
|
{t(
|
||||||
'admin.promocodes.form.noTrialTariff',
|
'admin.promocodes.form.noTrialTariffHint',
|
||||||
'⚠️ Триальный тариф не настроен. Отметьте тариф как «доступен для триала» в настройках тарифов.',
|
'Выберите тариф или отметьте тариф как «доступен для триала» в настройках.',
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user