import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { GitBranch, Plus, Settings, Trash2, Play, Pause, Rocket, TestTube, Package, Loader2, ArrowRight, GitCommit } from 'lucide-react'; import { formatDistanceToNow } from 'date-fns'; interface DeploymentTrigger { id: string; webhook_id: string; service_id: string; branch: string; environment: 'production' | 'preview' | 'development'; auto_deploy: boolean; build_command?: string; start_command?: string; created_at: string; service?: { name: string; type: string; }; } interface DeploymentTriggersProps { repositoryId: string; repositoryName: string; projectId: string; } export default function DeploymentTriggers({ repositoryId, repositoryName, projectId }: DeploymentTriggersProps) { const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [triggerForm, setTriggerForm] = useState({ webhook_id: '', service_id: '', branch: 'main', environment: 'preview' as 'production' | 'preview' | 'development', auto_deploy: false, build_command: '', start_command: '' }); const queryClient = useQueryClient(); // Mock data for triggers - in real implementation, this would come from API const { data: triggersData, isLoading } = useQuery({ queryKey: ['deployment-triggers', repositoryId], queryFn: async () => { // TODO: Replace with actual API call return { triggers: [ { id: 'trigger-1', webhook_id: 'webhook-1', service_id: 'service-1', branch: 'main', environment: 'production', auto_deploy: true, build_command: 'npm run build', start_command: 'npm start', created_at: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), service: { name: 'web-app', type: 'web' } }, { id: 'trigger-2', webhook_id: 'webhook-1', service_id: 'service-2', branch: 'develop', environment: 'preview', auto_deploy: true, build_command: 'npm run build', start_command: 'npm start', created_at: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), service: { name: 'api-server', type: 'api' } } ] as DeploymentTrigger[] }; }, }); // Mock services data - in real implementation, this would come from servicesApi const { data: servicesData } = useQuery({ queryKey: ['services', projectId], queryFn: async () => { // TODO: Replace with actual API call return { services: [ { id: 'service-1', name: 'web-app', type: 'web' }, { id: 'service-2', name: 'api-server', type: 'api' }, { id: 'service-3', name: 'worker', type: 'worker' } ] }; }, }); // Mock webhooks data - in real implementation, this would come from gitApi const { data: webhooksData } = useQuery({ queryKey: ['webhooks', repositoryId], queryFn: async () => { // TODO: Replace with actual API call return { webhooks: [ { id: 'webhook-1', events: ['push'], active: true } ] }; }, }); const createTriggerMutation = useMutation({ mutationFn: async (data: typeof triggerForm) => { // TODO: Replace with actual API call return { id: 'new-trigger', ...data }; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['deployment-triggers', repositoryId] }); setIsCreateModalOpen(false); setTriggerForm({ webhook_id: '', service_id: '', branch: 'main', environment: 'preview', auto_deploy: false, build_command: '', start_command: '' }); }, }); const triggers = triggersData?.triggers || []; const services = servicesData?.services || []; const webhooks = webhooksData?.webhooks || []; const handleCreateTrigger = () => { createTriggerMutation.mutate(triggerForm); }; const getEnvironmentIcon = (environment: string) => { switch (environment) { case 'production': return ; case 'preview': return ; case 'development': return ; default: return ; } }; const getEnvironmentColor = (environment: string) => { switch (environment) { case 'production': return 'bg-red-100 text-red-800'; case 'preview': return 'bg-blue-100 text-blue-800'; case 'development': return 'bg-gray-100 text-gray-800'; default: return 'bg-gray-100 text-gray-800'; } }; if (isLoading) { return (
{[1, 2].map(i => (
))}
); } return (
{/* Header */}

Deployment Triggers

Configure branch-based deployment triggers for your services

{/* Triggers List */} {triggers.length === 0 ? (

No deployment triggers configured

Create triggers to automatically deploy your services when code is pushed to specific branches

) : (
{triggers.map((trigger) => (
{trigger.auto_deploy ? ( ) : ( )}
{trigger.branch} {trigger.service?.name}
{formatDistanceToNow(new Date(trigger.created_at), { addSuffix: true })} Trigger ID: {trigger.id.substring(0, 8)}
{getEnvironmentIcon(trigger.environment)} {trigger.environment} {trigger.auto_deploy ? 'Auto Deploy' : 'Manual'}
{/* Service Info */}
{trigger.service?.name} {trigger.service?.type}
{trigger.branch}
{/* Commands */} {(trigger.build_command || trigger.start_command) && (
{trigger.build_command && (
Build: {trigger.build_command}
)} {trigger.start_command && (
Start: {trigger.start_command}
)}
)} {/* Deployment Flow */}
Push to {trigger.branch} Trigger webhook Deploy to {trigger.environment} {trigger.auto_deploy ? ( <> Auto deploy ) : ( <> Manual approval )}
))}
)} {/* Create Trigger Modal */} {isCreateModalOpen && (
Create Deployment Trigger

for {repositoryName}

setTriggerForm({ ...triggerForm, branch: e.target.value })} placeholder="main" className="mt-1" />
setTriggerForm({ ...triggerForm, build_command: e.target.value })} placeholder="npm run build" className="mt-1" />
setTriggerForm({ ...triggerForm, start_command: e.target.value })} placeholder="npm start" className="mt-1" />
setTriggerForm({ ...triggerForm, auto_deploy: e.target.checked })} className="rounded" />
)}
); }