import { useMemo } from 'react' import { useQuery } from '@tanstack/react-query' import { Copy, ExternalLink, Loader2, RefreshCcw } from 'lucide-react' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@/components/ui/collapsible' import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { Separator } from '@/components/ui/separator' import { getDeployment, listDeploymentContainers } from '../../api' export function ViewDetailsDialog({ open, onOpenChange, deploymentId, }: { open: boolean onOpenChange: (open: boolean) => void deploymentId: string | number | null }) { const { t } = useTranslation() const { data: detailsRes, isLoading: isLoadingDetails, refetch: refetchDetails, isFetching: isFetchingDetails, } = useQuery({ queryKey: ['deployment-details', deploymentId], queryFn: () => (deploymentId ? getDeployment(deploymentId) : null), enabled: open && deploymentId !== null, }) const { data: containersRes, isLoading: isLoadingContainers, refetch: refetchContainers, isFetching: isFetchingContainers, } = useQuery({ queryKey: ['deployment-details-containers', deploymentId], queryFn: () => deploymentId ? listDeploymentContainers(deploymentId) : null, enabled: open && deploymentId !== null, }) const details = detailsRes?.data const containers = useMemo(() => { const items = containersRes?.data?.containers return Array.isArray(items) ? items : [] }, [containersRes?.data?.containers]) const locations = useMemo(() => { const items = details?.locations if (!Array.isArray(items)) return [] return items .map((x) => { if (!x || typeof x !== 'object') return null const name = (x as Record)?.name const iso2 = (x as Record)?.iso2 const id = (x as Record)?.id return `${String(name ?? id ?? '')}${iso2 ? ` (${iso2})` : ''}`.trim() }) .filter(Boolean) as string[] }, [details]) const handleCopyId = async () => { if (deploymentId === null || deploymentId === undefined) return try { await navigator.clipboard.writeText(String(deploymentId)) toast.success(t('Copied')) } catch { toast.error(t('Copy failed')) } } const handleRefresh = () => { refetchDetails() refetchContainers() } const payloadJson = useMemo(() => { if (!details) return '' try { return JSON.stringify(details, null, 2) } catch { return '' } }, [details]) return ( {t('Deployment details')}
{t('Deployment ID')}:{' '} {deploymentId}
{isLoadingDetails || isLoadingContainers ? (
) : !detailsRes?.success ? (
{detailsRes?.message || t('Failed to fetch deployment details')}
) : ( <>
{t('Status')}
{String(details?.status ?? '-')}
{t('Hardware')}
{String(details?.brand_name ?? '')}{' '} {String(details?.hardware_name ?? '')}
{t('Total GPUs')}
{String( details?.total_gpus ?? details?.hardware_qty ?? '-' )}
{t('Containers')}
{containers.length}
{locations.length ? (
{t('Locations')}
{locations.map((x) => ( {x} ))}
) : null} {containers.length ? (
{t('Containers')}
{containers.map((c) => { const id = c?.container_id if (typeof id !== 'string' || !id) return null const status = typeof c?.status === 'string' ? c.status : undefined const url = typeof c?.public_url === 'string' ? c.public_url : '' return (
{id}
{status ? `${t('Status')}: ${status}` : ''}
{url ? ( ) : null}
) })}
) : null} {t('Raw JSON')}
                    {payloadJson || '-'}
                  
)}
) }