171 lines
5.6 KiB
TypeScript
171 lines
5.6 KiB
TypeScript
'use client'
|
|
import { useState } from 'react'
|
|
import { Button } from '@workspace/ui/components/button'
|
|
import { Input } from '@workspace/ui/components/input'
|
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@workspace/ui/components/card'
|
|
import { Label } from '@workspace/ui/components/label'
|
|
import { useDeployment, type DeploymentConfig } from '@/hooks/useDeployment'
|
|
import { Loader2 } from 'lucide-react'
|
|
|
|
interface DeploymentFormProps {
|
|
organizationSlug: string
|
|
}
|
|
|
|
export function DeploymentForm({ organizationSlug }: DeploymentFormProps) {
|
|
const { deployRepository, isDeploying, deploymentResult } = useDeployment()
|
|
const [formData, setFormData] = useState<Omit<DeploymentConfig, 'organizationSlug'>>({
|
|
projectId: '',
|
|
repository: '',
|
|
branch: 'main',
|
|
name: '',
|
|
environmentVariables: []
|
|
})
|
|
const [envVars, setEnvVars] = useState<Array<{ key: string; value: string }>>([])
|
|
const [currentEnvVar, setCurrentEnvVar] = useState({ key: '', value: '' })
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const { name, value } = e.target
|
|
setFormData(prev => ({ ...prev, [name]: value }))
|
|
}
|
|
|
|
const handleAddEnvVar = () => {
|
|
if (currentEnvVar.key && currentEnvVar.value) {
|
|
setEnvVars(prev => [...prev, { ...currentEnvVar }])
|
|
setCurrentEnvVar({ key: '', value: '' })
|
|
}
|
|
}
|
|
|
|
const handleDeploy = async () => {
|
|
try {
|
|
// Convert the env vars to the format expected by the API
|
|
const environmentVariables = envVars.map(ev => ({
|
|
key: ev.key,
|
|
value: ev.value,
|
|
environments: ['Production', 'Preview'] // Default to both environments
|
|
}))
|
|
|
|
await deployRepository({
|
|
...formData,
|
|
organizationSlug,
|
|
environmentVariables
|
|
})
|
|
} catch (error) {
|
|
console.error('Deployment failed:', error)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Card className="w-full">
|
|
<CardHeader>
|
|
<CardTitle>Deploy Repository</CardTitle>
|
|
<CardDescription>
|
|
Enter the details for deploying a GitHub repository
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="name">Project Name</Label>
|
|
<Input
|
|
id="name"
|
|
name="name"
|
|
value={formData.name}
|
|
onChange={handleChange}
|
|
placeholder="my-awesome-project"
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="repository">Repository URL</Label>
|
|
<Input
|
|
id="repository"
|
|
name="repository"
|
|
value={formData.repository}
|
|
onChange={handleChange}
|
|
placeholder="https://github.com/username/repo"
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="branch">Branch</Label>
|
|
<Input
|
|
id="branch"
|
|
name="branch"
|
|
value={formData.branch}
|
|
onChange={handleChange}
|
|
placeholder="main"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Environment Variables</Label>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
<Input
|
|
placeholder="KEY"
|
|
value={currentEnvVar.key}
|
|
onChange={(e) => setCurrentEnvVar(prev => ({ ...prev, key: e.target.value }))}
|
|
/>
|
|
<Input
|
|
placeholder="value"
|
|
value={currentEnvVar.value}
|
|
onChange={(e) => setCurrentEnvVar(prev => ({ ...prev, value: e.target.value }))}
|
|
/>
|
|
</div>
|
|
<Button
|
|
variant="outline"
|
|
type="button"
|
|
onClick={handleAddEnvVar}
|
|
disabled={!currentEnvVar.key || !currentEnvVar.value}
|
|
className="mt-2"
|
|
>
|
|
Add Environment Variable
|
|
</Button>
|
|
</div>
|
|
|
|
{envVars.length > 0 && (
|
|
<div className="border rounded p-2">
|
|
<h4 className="font-medium mb-2">Environment Variables:</h4>
|
|
<ul className="space-y-1">
|
|
{envVars.map((ev, index) => (
|
|
<li key={index} className="flex justify-between">
|
|
<span className="font-mono">{ev.key}</span>
|
|
<span className="font-mono text-gray-500">{ev.value}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
<CardFooter>
|
|
<Button
|
|
onClick={handleDeploy}
|
|
disabled={isDeploying || !formData.name || !formData.repository}
|
|
className="w-full"
|
|
>
|
|
{isDeploying ? (
|
|
<>
|
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
Deploying...
|
|
</>
|
|
) : 'Deploy Repository'}
|
|
</Button>
|
|
</CardFooter>
|
|
|
|
{deploymentResult && (
|
|
<div className="mt-4 p-4 border-t">
|
|
<h3 className="font-medium mb-2">Deployment Result:</h3>
|
|
<p>Status: <span className="font-medium">{deploymentResult.status}</span></p>
|
|
{deploymentResult.url && (
|
|
<p className="mt-2">
|
|
URL: <a href={deploymentResult.url} target="_blank" rel="noopener noreferrer" className="text-blue-500 underline">{deploymentResult.url}</a>
|
|
</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
</Card>
|
|
)
|
|
} |