diff --git a/src/pages/AdminPromocodes.tsx b/src/pages/AdminPromocodes.tsx index 3d5255b..c04fb86 100644 --- a/src/pages/AdminPromocodes.tsx +++ b/src/pages/AdminPromocodes.tsx @@ -398,6 +398,11 @@ interface PromoGroupModalProps { isLoading?: boolean } +interface PeriodDiscount { + days: number + percent: number +} + function PromoGroupModal({ group, onSave, onClose, isLoading }: PromoGroupModalProps) { const isEdit = !!group @@ -410,12 +415,46 @@ function PromoGroupModal({ group, onSave, onClose, isLoading }: PromoGroupModalP group?.auto_assign_total_spent_kopeks ? group.auto_assign_total_spent_kopeks / 100 : 0 ) + // Period discounts state + const [periodDiscounts, setPeriodDiscounts] = useState(() => { + if (group?.period_discounts && typeof group.period_discounts === 'object') { + return Object.entries(group.period_discounts).map(([days, percent]) => ({ + days: parseInt(days), + percent: typeof percent === 'number' ? percent : 0, + })) + } + return [] + }) + + const addPeriodDiscount = () => { + setPeriodDiscounts([...periodDiscounts, { days: 30, percent: 0 }]) + } + + const removePeriodDiscount = (index: number) => { + setPeriodDiscounts(periodDiscounts.filter((_, i) => i !== index)) + } + + const updatePeriodDiscount = (index: number, field: 'days' | 'percent', value: number) => { + const updated = [...periodDiscounts] + updated[index][field] = value + setPeriodDiscounts(updated) + } + const handleSubmit = () => { + // Convert periodDiscounts array to Record + const periodDiscountsRecord: Record = {} + periodDiscounts.forEach(pd => { + if (pd.days > 0 && pd.percent > 0) { + periodDiscountsRecord[pd.days] = pd.percent + } + }) + const data: PromoGroupCreateRequest | PromoGroupUpdateRequest = { name, server_discount_percent: serverDiscount, traffic_discount_percent: trafficDiscount, device_discount_percent: deviceDiscount, + period_discounts: Object.keys(periodDiscountsRecord).length > 0 ? periodDiscountsRecord : undefined, apply_discounts_to_addons: applyToAddons, auto_assign_total_spent_kopeks: autoAssignSpent > 0 ? Math.round(autoAssignSpent * 100) : null, } @@ -449,9 +488,9 @@ function PromoGroupModal({ group, onSave, onClose, isLoading }: PromoGroupModalP /> - {/* Discounts */} + {/* Category Discounts */}
-

Скидки

+

Скидки по категориям

На серверы: @@ -493,6 +532,61 @@ function PromoGroupModal({ group, onSave, onClose, isLoading }: PromoGroupModalP
+ {/* Period Discounts */} +
+
+

Скидки по периодам

+ +
+

+ Скидка применяется при покупке подписки на указанное кол-во дней +

+ + {periodDiscounts.length === 0 ? ( +

Нет скидок по периодам

+ ) : ( +
+ {periodDiscounts.map((pd, index) => ( +
+ updatePeriodDiscount(index, 'days', Math.max(1, parseInt(e.target.value) || 1))} + className="w-20 px-2 py-1 bg-dark-600 border border-dark-500 rounded text-dark-100 focus:outline-none focus:border-accent-500" + min={1} + placeholder="Дни" + /> + дней → + updatePeriodDiscount(index, 'percent', Math.min(100, Math.max(0, parseInt(e.target.value) || 0)))} + className="w-20 px-2 py-1 bg-dark-600 border border-dark-500 rounded text-dark-100 focus:outline-none focus:border-accent-500" + min={0} + max={100} + placeholder="%" + /> + % + +
+ ))} +
+ )} +
+ {/* Auto-assign */}
@@ -1071,6 +1165,18 @@ export default function AdminPromocodes() { {group.device_discount_percent > 0 && ( Устройства: -{group.device_discount_percent}% )} + {group.period_discounts && Object.keys(group.period_discounts).length > 0 && ( + Object.entries(group.period_discounts).map(([days, percent]) => ( + + {days} дн.: -{percent}% + + )) + )} + {group.auto_assign_total_spent_kopeks && group.auto_assign_total_spent_kopeks > 0 && ( + + Авто от {group.auto_assign_total_spent_kopeks / 100} руб. + + )} {group.members_count} участников