diff --git a/src/components/subscription/sheets/ServerManagementSheet.tsx b/src/components/subscription/sheets/ServerManagementSheet.tsx new file mode 100644 index 0000000..8617948 --- /dev/null +++ b/src/components/subscription/sheets/ServerManagementSheet.tsx @@ -0,0 +1,328 @@ +import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { subscriptionApi } from '../../../api/subscription'; +import { getErrorMessage, getFlagEmoji } from '../../../utils/subscriptionHelpers'; +import InsufficientBalancePrompt from '../../InsufficientBalancePrompt'; +import type { PurchaseOptions, Subscription } from '../../../types'; + +// ────────────────────────────────────────────────────────────────── +// Manage-servers sheet (classic-mode only — caller decides whether to +// render). Self-owns the countries query + update mutation; parent +// holds the selected-uuid set so the global "close all modals" can +// reset it. +// +// Extracted from Subscription.tsx — ~280 lines off the god page. +// ────────────────────────────────────────────────────────────────── + +export interface ServerManagementSheetProps { + open: boolean; + onOpen: () => void; + onClose: () => void; + subscription: Subscription; + subscriptionId: number | undefined; + selectedServers: string[]; + onSelectedServersChange: (uuids: string[] | ((prev: string[]) => string[])) => void; + purchaseOptions: PurchaseOptions | undefined; + isDark: boolean; +} + +export function ServerManagementSheet({ + open, + onOpen, + onClose, + subscription, + subscriptionId, + selectedServers, + onSelectedServersChange, + purchaseOptions, + isDark, +}: ServerManagementSheetProps) { + const { t } = useTranslation(); + const queryClient = useQueryClient(); + + const formatPrice = (kopeks: number) => { + const rubles = kopeks / 100; + return rubles % 1 === 0 ? `${rubles} ₽` : `${rubles.toFixed(2)} ₽`; + }; + + const { data: countriesData, isLoading: countriesLoading } = useQuery({ + queryKey: ['countries', subscriptionId], + queryFn: () => subscriptionApi.getCountries(subscriptionId), + enabled: open && !!subscription && !subscription.is_trial, + }); + + // Seed selected = currently connected once the data loads. + useEffect(() => { + if (countriesData && open) { + const connected = countriesData.countries.filter((c) => c.is_connected).map((c) => c.uuid); + onSelectedServersChange(connected); + } + // Intentionally narrow — the setter is stable and we don't want to + // re-seed every time the user toggles a server. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [countriesData, open]); + + const updateMutation = useMutation({ + mutationFn: (countries: string[]) => subscriptionApi.updateCountries(countries, subscriptionId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['subscription', subscriptionId] }); + queryClient.invalidateQueries({ queryKey: ['subscriptions-list'] }); + queryClient.invalidateQueries({ queryKey: ['countries', subscriptionId] }); + onClose(); + }, + }); + + if (!open) { + return ( + + ); + } + + return ( +