import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { promoApi, PromoOffer } from '../api/promo' // Icons const GiftIcon = () => ( ) const ClockIcon = () => ( ) const SparklesIcon = () => ( ) const CheckIcon = () => ( ) const ServerIcon = () => ( ) // Helper functions const formatTimeLeft = (expiresAt: string): string => { const now = new Date() // Ensure UTC parsing - if no timezone specified, assume UTC let expires: Date if (expiresAt.includes('Z') || expiresAt.includes('+') || expiresAt.includes('-', 10)) { expires = new Date(expiresAt) } else { // No timezone - treat as UTC expires = new Date(expiresAt + 'Z') } const diffMs = expires.getTime() - now.getTime() if (diffMs <= 0) return 'Истекло' const hours = Math.floor(diffMs / (1000 * 60 * 60)) const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)) if (hours > 24) { const days = Math.floor(hours / 24) return `${days} дн.` } if (hours > 0) { return `${hours}ч ${minutes}м` } return `${minutes}м` } const getOfferIcon = (effectType: string) => { if (effectType === 'test_access') return return } const getOfferTitle = (offer: PromoOffer): string => { if (offer.effect_type === 'test_access') { return 'Тестовый доступ' } if (offer.discount_percent) { return `Скидка ${offer.discount_percent}%` } return 'Специальное предложение' } const getOfferDescription = (offer: PromoOffer): string => { if (offer.effect_type === 'test_access') { const squads = offer.extra_data?.test_squad_uuids?.length || 0 return squads > 0 ? `Доступ к ${squads} серверам` : 'Доступ к дополнительным серверам' } return 'Активируйте скидку на покупку подписки' } interface PromoOffersSectionProps { className?: string } export default function PromoOffersSection({ className = '' }: PromoOffersSectionProps) { const queryClient = useQueryClient() const [claimingId, setClaimingId] = useState(null) const [successMessage, setSuccessMessage] = useState(null) const [errorMessage, setErrorMessage] = useState(null) // Fetch available offers const { data: offers = [], isLoading: offersLoading } = useQuery({ queryKey: ['promo-offers'], queryFn: promoApi.getOffers, staleTime: 30000, }) // Fetch active discount const { data: activeDiscount } = useQuery({ queryKey: ['active-discount'], queryFn: promoApi.getActiveDiscount, staleTime: 30000, }) // Claim offer mutation const claimMutation = useMutation({ mutationFn: promoApi.claimOffer, onSuccess: (result) => { queryClient.invalidateQueries({ queryKey: ['promo-offers'] }) queryClient.invalidateQueries({ queryKey: ['active-discount'] }) queryClient.invalidateQueries({ queryKey: ['subscription'] }) setSuccessMessage(result.message) setClaimingId(null) setTimeout(() => setSuccessMessage(null), 5000) }, onError: (error: any) => { setErrorMessage(error.response?.data?.detail || 'Не удалось активировать предложение') setClaimingId(null) setTimeout(() => setErrorMessage(null), 5000) }, }) const handleClaim = (offerId: number) => { setClaimingId(offerId) setErrorMessage(null) setSuccessMessage(null) claimMutation.mutate(offerId) } // Filter unclaimed and active offers const availableOffers = offers.filter(o => o.is_active && !o.is_claimed) // Don't render if no offers and no active discount if (!offersLoading && availableOffers.length === 0 && (!activeDiscount || !activeDiscount.is_active)) { return null } return (
{/* Active Discount Banner */} {activeDiscount && activeDiscount.is_active && activeDiscount.discount_percent > 0 && (

Скидка {activeDiscount.discount_percent}% активна

Действует
{activeDiscount.expires_at && (
Истекает: {formatTimeLeft(activeDiscount.expires_at)}
)}
)} {/* Success/Error Messages */} {successMessage && (
{successMessage}
)} {errorMessage && (
{errorMessage}
)} {/* Available Offers */} {availableOffers.length > 0 && (
{availableOffers.map((offer) => (
{getOfferIcon(offer.effect_type)}

{getOfferTitle(offer)}

{offer.effect_type === 'test_access' && ( Тест )}

{getOfferDescription(offer)}

Осталось: {formatTimeLeft(offer.expires_at)}
))}
)} {/* Loading State */} {offersLoading && (
)}
) }