import { useState, useEffect, useMemo } from 'react'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { SystemSheet, SheetSection } from '@/components/ui/system-sheet'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Search, Rocket, Loader2, Info, ExternalLink, Star, ShieldCheck } from 'lucide-react'; import { toast } from '@/components/ui/toast-store'; import { cn } from '@/lib/utils'; import { apiFetch, withDeploySession } from '@/lib/api'; import { useDeployFeedback } from '@/context/DeployFeedbackContext'; import { useNodes } from '@/context/NodeContext'; import { useAuth } from '@/context/AuthContext'; import { CategorySidebar } from '@/components/appstore/CategorySidebar'; import { FeaturedHero } from '@/components/appstore/FeaturedHero'; import { TemplateTile } from '@/components/appstore/TemplateTile'; import type { Template } from '@/components/appstore/types'; function isValidPort(value: string): boolean { if (!value) return true; const num = Number(value); return Number.isInteger(num) && num >= 1 && num <= 65535; } interface PortInUseInfo { stack: string | null; container: string; } interface AppStoreViewProps { onDeploySuccess: (stackName: string) => void; } export function AppStoreView({ onDeploySuccess }: AppStoreViewProps) { const { can } = useAuth(); const { activeNode } = useNodes(); const { runWithLog } = useDeployFeedback(); const [templates, setTemplates] = useState([]); const [searchQuery, setSearchQuery] = useState(''); const [selectedTemplate, setSelectedTemplate] = useState