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 ? (
) : (
)}
);
})}
>
);
}