diff --git a/src/api/tariffs.ts b/src/api/tariffs.ts index 5e4234f..8664f24 100644 --- a/src/api/tariffs.ts +++ b/src/api/tariffs.ts @@ -85,6 +85,8 @@ export interface TariffDetail { daily_price_kopeks: number; // Режим сброса трафика traffic_reset_mode: string | null; // 'DAY', 'WEEK', 'MONTH', 'NO_RESET', null = глобальная настройка + // Внешний сквад RemnaWave + external_squad_uuid: string | null; created_at: string; updated_at: string | null; } @@ -121,6 +123,14 @@ export interface TariffCreateRequest { daily_price_kopeks?: number; // Режим сброса трафика traffic_reset_mode?: string | null; + // Внешний сквад RemnaWave + external_squad_uuid?: string | null; +} + +export interface ExternalSquadInfo { + uuid: string; + name: string; + members_count: number; } export interface TariffUpdateRequest { @@ -156,6 +166,8 @@ export interface TariffUpdateRequest { daily_price_kopeks?: number; // Режим сброса трафика traffic_reset_mode?: string | null; + // Внешний сквад RemnaWave + external_squad_uuid?: string | null; } export interface TariffToggleResponse { @@ -249,4 +261,10 @@ export const tariffsApi = { const response = await apiClient.get('/cabinet/admin/payment-methods/promo-groups'); return response.data; }, + + // Get available external squads from RemnaWave + getAvailableExternalSquads: async (): Promise => { + const response = await apiClient.get('/cabinet/admin/tariffs/available-external-squads'); + return response.data; + }, }; diff --git a/src/locales/en.json b/src/locales/en.json index ea0c06b..042121d 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1923,6 +1923,10 @@ "noPeriodsHint": "No added periods. Add at least one period.", "daysShort": "d.", "serversTitle": "Servers", + "externalSquadTitle": "External Squad", + "externalSquadHint": "Assign a RemnaWave external squad for users on this tariff. When a subscription is created, the user will be automatically added to the selected squad.", + "noExternalSquad": "No external squad", + "externalSquadUsers": "users", "serversTabHint": "Select servers available on this tariff.", "noServersAvailable": "No servers available", "promoGroupsTitle": "Promo Groups", diff --git a/src/locales/fa.json b/src/locales/fa.json index 1a64896..3e84979 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -1567,6 +1567,10 @@ "noPeriodsHint": "هیچ دوره‌ای اضافه نشده. حداقل یک دوره اضافه کنید.", "daysShort": "روز", "serversTitle": "سرورها", + "externalSquadTitle": "گروه خارجی", + "externalSquadHint": "یک گروه خارجی RemnaWave برای کاربران این تعرفه تعیین کنید. هنگام ایجاد اشتراک، کاربر به طور خودکار به گروه انتخاب شده اضافه می‌شود.", + "noExternalSquad": "بدون گروه خارجی", + "externalSquadUsers": "کاربران", "serversTabHint": "سرورهای موجود در این تعرفه را انتخاب کنید.", "noServersAvailable": "هیچ سروری در دسترس نیست", "promoGroupsTitle": "گروه‌های تبلیغاتی", diff --git a/src/locales/ru.json b/src/locales/ru.json index 2c672ed..10dcf2d 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -2437,6 +2437,10 @@ "noPeriodsHint": "Нет добавленных периодов. Добавьте хотя бы один период.", "daysShort": "дн.", "serversTitle": "Серверы", + "externalSquadTitle": "Внешний сквад", + "externalSquadHint": "Назначьте внешний сквад RemnaWave для пользователей этого тарифа. При создании подписки пользователь будет автоматически добавлен в выбранный сквад.", + "noExternalSquad": "Без внешнего сквада", + "externalSquadUsers": "пользователей", "serversTabHint": "Выберите серверы, доступные на этом тарифе.", "noServersAvailable": "Нет доступных серверов", "promoGroupsTitle": "Промо-группы", diff --git a/src/locales/zh.json b/src/locales/zh.json index 7d9a881..2ae4911 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -1604,6 +1604,10 @@ "noPeriodsHint": "没有添加的周期。请至少添加一个周期。", "daysShort": "天", "serversTitle": "服务器", + "externalSquadTitle": "外部小组", + "externalSquadHint": "为此套餐的用户分配RemnaWave外部小组。创建订阅时,用户将自动添加到所选小组。", + "noExternalSquad": "无外部小组", + "externalSquadUsers": "用户", "serversTabHint": "选择此套餐上可用的服务器。", "noServersAvailable": "没有可用的服务器", "promoGroupsTitle": "促销组", diff --git a/src/pages/AdminTariffCreate.tsx b/src/pages/AdminTariffCreate.tsx index 6d62191..f88ccbf 100644 --- a/src/pages/AdminTariffCreate.tsx +++ b/src/pages/AdminTariffCreate.tsx @@ -9,6 +9,7 @@ import { TariffUpdateRequest, PeriodPrice, ServerInfo, + ExternalSquadInfo, } from '../api/tariffs'; import { AdminBackButton } from '../components/admin'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; @@ -105,6 +106,7 @@ export default function AdminTariffCreate() { const [tierLevel, setTierLevel] = useState(1); const [periodPrices, setPeriodPrices] = useState([]); const [selectedSquads, setSelectedSquads] = useState([]); + const [selectedExternalSquad, setSelectedExternalSquad] = useState(null); const [selectedPromoGroups, setSelectedPromoGroups] = useState([]); const [dailyPriceKopeks, setDailyPriceKopeks] = useState(0); @@ -138,6 +140,12 @@ export default function AdminTariffCreate() { queryFn: () => tariffsApi.getAvailableServers(), }); + // Fetch external squads + const { data: externalSquads = [] } = useQuery({ + queryKey: ['admin-tariffs-external-squads'], + queryFn: () => tariffsApi.getAvailableExternalSquads(), + }); + // Fetch promo groups const { data: promoGroups = [] } = useQuery({ queryKey: ['admin-tariffs-promo-groups'], @@ -165,6 +173,7 @@ export default function AdminTariffCreate() { setTierLevel(data.tier_level || 1); setPeriodPrices(data.period_prices?.length ? data.period_prices : []); setSelectedSquads(data.allowed_squads || []); + setSelectedExternalSquad(data.external_squad_uuid || null); setSelectedPromoGroups( data.promo_groups?.filter((pg) => pg.is_selected).map((pg) => pg.id) || [], ); @@ -211,6 +220,7 @@ export default function AdminTariffCreate() { tier_level: toNumber(tierLevel, 1), period_prices: isDaily ? [] : periodPrices.filter((p) => p.price_kopeks >= 0), allowed_squads: selectedSquads, + external_squad_uuid: selectedExternalSquad || null, promo_group_ids: selectedPromoGroups.length > 0 ? selectedPromoGroups : undefined, traffic_topup_enabled: trafficTopupEnabled, traffic_topup_packages: trafficTopupPackages, @@ -660,6 +670,77 @@ export default function AdminTariffCreate() { {activeTab === 'servers' && (
+ {/* External Squad */} + {externalSquads.length > 0 && ( +
+

+ {t('admin.tariffs.externalSquadTitle')} +

+

{t('admin.tariffs.externalSquadHint')}

+
+ + {externalSquads.map((squad: ExternalSquadInfo) => { + const isSelected = selectedExternalSquad === squad.uuid; + return ( + + ); + })} +
+
+ )} + {/* Servers */}

{t('admin.tariffs.serversTitle')}