import { Fragment, useState, useEffect } from 'react' import { Dialog, Transition } from '@headlessui/react' import { IconX, IconCheck, IconInfoCircle } from '@tabler/icons-react' import { CuratedCategory, CategoryTier, CategoryResource } from '../../types/downloads' import { formatBytes } from '~/lib/util' import classNames from 'classnames' import DynamicIcon, { DynamicIconName } from './DynamicIcon' interface TierSelectionModalProps { isOpen: boolean onClose: () => void category: CuratedCategory | null selectedTierSlug?: string | null onSelectTier: (category: CuratedCategory, tier: CategoryTier) => void } const TierSelectionModal: React.FC = ({ isOpen, onClose, category, selectedTierSlug, onSelectTier, }) => { // Local selection state - initialized from prop const [localSelectedSlug, setLocalSelectedSlug] = useState(null) // Reset local selection when modal opens or category changes useEffect(() => { if (isOpen && category) { setLocalSelectedSlug(selectedTierSlug || null) } }, [isOpen, category, selectedTierSlug]) if (!category) return null // Get all resources for a tier (including inherited resources) const getAllResourcesForTier = (tier: CategoryTier): CategoryResource[] => { const resources = [...tier.resources] if (tier.includesTier) { const includedTier = category.tiers.find(t => t.slug === tier.includesTier) if (includedTier) { resources.unshift(...getAllResourcesForTier(includedTier)) } } return resources } const getTierTotalSize = (tier: CategoryTier): number => { return getAllResourcesForTier(tier).reduce((acc, r) => acc + r.size_mb * 1024 * 1024, 0) } const handleTierClick = (tier: CategoryTier) => { // Toggle selection: if clicking the same tier, deselect it if (localSelectedSlug === tier.slug) { setLocalSelectedSlug(null) } else { setLocalSelectedSlug(tier.slug) } } const handleSubmit = () => { if (!localSelectedSlug) return const selectedTier = category.tiers.find(t => t.slug === localSelectedSlug) if (selectedTier) { onSelectTier(category, selectedTier) } onClose() } return (
{/* Header */}
{category.name}

{category.description}

{/* Content */}

Select a tier based on your storage capacity and needs. Higher tiers include all content from lower tiers.

{category.tiers.map((tier) => { const allResources = getAllResourcesForTier(tier) const totalSize = getTierTotalSize(tier) const isSelected = localSelectedSlug === tier.slug return (
handleTierClick(tier)} className={classNames( 'border-2 rounded-lg p-5 cursor-pointer transition-all', isSelected ? 'border-desert-green bg-desert-green/5 shadow-md' : 'border-gray-200 hover:border-desert-green/50 hover:shadow-sm' )} >

{tier.name}

{tier.includesTier && ( (includes {category.tiers.find(t => t.slug === tier.includesTier)?.name}) )}

{tier.description}

{/* Resources preview */}

{allResources.length} resources included:

{allResources.map((resource, idx) => (
{resource.title} ({formatBytes(resource.size_mb * 1024 * 1024, 0)})
))}
{formatBytes(totalSize, 1)}
{isSelected && }
) })}
{/* Info note */}

You can change your selection at any time. Click Submit to confirm your choice.

{/* Footer */}
) } export default TierSelectionModal