import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router'; import { useTheme } from '../../../hooks/useTheme'; import { useCurrency } from '../../../hooks/useCurrency'; import { usePromoDiscount } from '../../../hooks/usePromoDiscount'; import { getGlassColors } from '../../../utils/glassTheme'; import type { Tariff, Subscription, PurchaseOptions } from '../../../types'; // ────────────────────────────────────────────────────────────────── // TariffPickerGrid // // The tariff selection surface inside SubscriptionPurchase. Renders: // - an optional promo-group banner when any tariff carries a // promo_group_name // - the "all tariffs purchased" empty state (multi-tariff mode) // - the grid itself (1 col mobile, 2 cols sm+) with promo prices, // per-tariff CTAs differentiated by user state (extend / switch / // purchase / legacy renewal) // // Owns nothing — pure presentation that calls back into the parent // for selection (`onSelectTariff`) and switch (`onSwitchTariff`). // ────────────────────────────────────────────────────────────────── export interface TariffPickerGridProps { tariffs: Tariff[]; subscription: Subscription | null; purchaseOptions: PurchaseOptions | undefined; isTariffsMode: boolean; isMultiTariff: boolean; onSelectTariff: (tariff: Tariff) => void; onSwitchTariff: (tariffId: number) => void; } export function TariffPickerGrid({ tariffs, subscription, purchaseOptions, isTariffsMode, isMultiTariff, onSelectTariff, onSwitchTariff, }: TariffPickerGridProps) { const { t } = useTranslation(); const navigate = useNavigate(); const { isDark } = useTheme(); const g = getGlassColors(isDark); const { formatAmount, currencySymbol } = useCurrency(); const { applyPromoDiscount } = usePromoDiscount(); const formatPrice = (kopeks: number) => kopeks === 0 ? t('subscription.free', 'Бесплатно') : `${formatAmount(kopeks / 100)} ${currencySymbol}`; return ( <> {/* Promo group discount banner */} {tariffs.some((tariff) => tariff.promo_group_name) && (
{t('subscription.promoGroup.title', { name: tariffs.find((tariff) => tariff.promo_group_name)?.promo_group_name, })}
{t('subscription.promoGroup.personalDiscountsApplied')}
)} {/* Tariff Grid */} {isMultiTariff && purchaseOptions && 'all_tariffs_purchased' in purchaseOptions && purchaseOptions.all_tariffs_purchased && (

{t('subscription.allTariffsPurchased', 'Все тарифы подключены')}

{t( 'subscription.allTariffsPurchasedDesc', 'Вы уже приобрели все доступные тарифы. Продлить подписку можно на странице тарифа.', )}

)}
{[...tariffs] .filter((tariff) => { // In multi-tariff mode: hide already purchased tariffs if (isMultiTariff && tariff.is_purchased) return false; if (subscription?.is_trial && tariff.name.toLowerCase().includes('trial')) { return false; } return true; }) .sort((a, b) => { const aIsCurrent = a.is_current || a.id === subscription?.tariff_id; const bIsCurrent = b.is_current || b.id === subscription?.tariff_id; if (aIsCurrent && !bIsCurrent) return -1; if (!aIsCurrent && bIsCurrent) return 1; return 0; }) .map((tariff) => { const isCurrentTariff = tariff.is_current || tariff.id === subscription?.tariff_id; const isSubscriptionExpired = isTariffsMode && purchaseOptions && 'subscription_is_expired' in purchaseOptions && purchaseOptions.subscription_is_expired === true; const canSwitch = !isMultiTariff && subscription && subscription.tariff_id && !isCurrentTariff && !subscription.is_trial && !isSubscriptionExpired && (subscription.is_active || subscription.is_limited); const isLegacySubscription = subscription && !subscription.is_trial && !subscription.tariff_id; return (
{tariff.name}
{tariff.description && (
{tariff.description}
)}
{isCurrentTariff && ( {t('subscription.currentTariff')} )}
{tariff.traffic_limit_label}
{tariff.device_limit === 0 ? '∞' : t('subscription.devices', { count: tariff.device_limit })}
{tariff.traffic_reset_mode && tariff.traffic_reset_mode !== 'NO_RESET' && (
{t(`subscription.trafficReset.${tariff.traffic_reset_mode}`)}
)}
{/* Price info */}
{(() => { const dailyPrice = tariff.daily_price_kopeks ?? tariff.price_per_day_kopeks ?? 0; const originalDailyPrice = tariff.original_daily_price_kopeks || 0; if (dailyPrice > 0 || originalDailyPrice > 0) { const promoDaily = applyPromoDiscount( dailyPrice, originalDailyPrice > dailyPrice ? originalDailyPrice : undefined, ); return ( {formatPrice(promoDaily.price)} {promoDaily.original && promoDaily.original > promoDaily.price && ( {formatPrice(promoDaily.original)} )} {t('subscription.tariff.perDay')} {promoDaily.percent && promoDaily.percent > 0 && ( -{promoDaily.percent}% )} ); } if (tariff.periods.length > 0) { const firstPeriod = tariff.periods[0]; const promoPeriod = applyPromoDiscount( firstPeriod?.price_kopeks || 0, firstPeriod?.original_price_kopeks, ); return ( {t('subscription.from')} {formatPrice(promoPeriod.price)} {promoPeriod.original && promoPeriod.original > promoPeriod.price && ( {formatPrice(promoPeriod.original)} )} {promoPeriod.percent && promoPeriod.percent > 0 && ( -{promoPeriod.percent}% )} ); } return ( {t('subscription.tariff.flexiblePayment')} ); })()}
{/* Action Buttons */}
{isCurrentTariff ? ( subscription?.is_daily ? (
{t('subscription.currentTariff')}
) : ( ) ) : isLegacySubscription ? ( ) : canSwitch ? ( ) : ( )}
); })}
); }