CoolFace
Apppublic

Leon4gr45/builder

sourceHugging Facemitupdated 2d agoView on Hugging Face
0likes
deployment-selector.tsx136 linesDownload Raw Back to workspace
1'use client';2 3import React, { useEffect, useState } from 'react';4import { Deployment } from '@/lib/vfs/types';5import { Server, Loader2 } from 'lucide-react';6import {7  Select,8  SelectContent,9  SelectItem,10  SelectTrigger,11  SelectValue,12} from '@/components/ui/select';13import { cn } from '@/lib/utils';14 15interface DeploymentSelectorProps {16  projectId: string;17  selectedDeploymentId: string | null;18  onDeploymentChange: (deploymentId: string | null, deploymentName: string | null) => void;19  className?: string;20  workspaceId?: string;21}22 23export function DeploymentSelector({24  projectId,25  selectedDeploymentId,26  onDeploymentChange,27  className,28  workspaceId,29}: DeploymentSelectorProps) {30  const apiBase = workspaceId ? `/api/w/${workspaceId}` : '/api';31  const [deployments, setDeployments] = useState<Deployment[]>([]);32  const [loading, setLoading] = useState(true);33  const [error, setError] = useState<string | null>(null);34 35  // Fetch deployments for this project36  useEffect(() => {37    const fetchDeployments = async () => {38      // Only fetch in server mode39      if (process.env.NEXT_PUBLIC_SERVER_MODE !== 'true') {40        setLoading(false);41        return;42      }43 44      try {45        setLoading(true);46        setError(null);47 48        const response = await fetch(`${apiBase}/projects/${projectId}/deployments`);49        if (!response.ok) {50          throw new Error('Failed to fetch deployments');51        }52 53        const data = await response.json();54        setDeployments(data.deployments || []);55 56        // Auto-select first deployment if only one exists and nothing is selected57        if (data.deployments?.length === 1 && !selectedDeploymentId) {58          const deployment = data.deployments[0];59          if (deployment.databaseEnabled) {60            onDeploymentChange(deployment.id, deployment.name);61          }62        }63      } catch {64        // Expected in browser mode or when project hasn't been synced to server yet65        // Don't show error — deployments are optional66      } finally {67        setLoading(false);68      }69    };70 71    fetchDeployments();72  }, [projectId]); // Only refetch when project changes73 74  // Don't render in browser mode75  if (process.env.NEXT_PUBLIC_SERVER_MODE !== 'true') {76    return null;77  }78 79  // Don't render if no deployments with database enabled80  const databaseEnabledDeployments = deployments.filter(s => s.databaseEnabled);81  if (!loading && databaseEnabledDeployments.length === 0) {82    return null;83  }84 85  if (loading) {86    return (87      <div className={cn('flex items-center gap-2 text-sm text-muted-foreground', className)}>88        <Loader2 className="h-4 w-4 animate-spin" />89        <span>Loading deployments...</span>90      </div>91    );92  }93 94  if (error) {95    return (96      <div className={cn('flex items-center gap-2 text-sm text-destructive', className)}>97        <Server className="h-4 w-4" />98        <span>{error}</span>99      </div>100    );101  }102 103  return (104    <div className={cn('flex items-center gap-2', className)}>105      <Select106        value={selectedDeploymentId || 'none'}107        onValueChange={(value) => {108          if (value === 'none') {109            onDeploymentChange(null, null);110          } else {111            const deployment = deployments.find(s => s.id === value);112            onDeploymentChange(value, deployment?.name || null);113          }114        }}115      >116        <SelectTrigger size="sm" className="w-[180px] h-8">117          <SelectValue placeholder="No deployment" />118        </SelectTrigger>119        <SelectContent>120          <SelectItem value="none">121            <span className="text-muted-foreground">No deployment</span>122          </SelectItem>123          {databaseEnabledDeployments.map((deployment) => (124            <SelectItem key={deployment.id} value={deployment.id}>125              <div className="flex items-center gap-2">126                <Server className="h-3.5 w-3.5" />127                <span>{deployment.name}</span>128              </div>129            </SelectItem>130          ))}131        </SelectContent>132      </Select>133    </div>134  );135}136