// src/components/onboarding/deploy-step/deploy-step.tsx 'use client' import { useState, useEffect } from 'react' import { useTheme } from 'next-themes' import { Github, Loader2, AlertTriangle, CheckCircle2 } from 'lucide-react' import { useOnboarding } from '@/components/onboarding/useOnboarding' import { useGQLClient } from '@/context' import { useWallet } from '@/context/WalletContext' import { useDeployment } from '@/hooks/useDeployment' import { useTemplateDeployment } from '@/hooks/useTemplate' import { Button } from '@workspace/ui/components/button' import { Progress } from '@workspace/ui/components/progress' import { Dialog, DialogContent, DialogTitle, DialogDescription, DialogFooter } from '@workspace/ui/components/dialog' import { Alert, AlertDescription } from '@workspace/ui/components/alert' import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card' import { Badge } from '@workspace/ui/components/badge' import { toast } from 'sonner' export function DeployStep() { const { previousStep, nextStep, formData, setFormData } = useOnboarding() const { resolvedTheme } = useTheme() const [mounted, setMounted] = useState(false) // State const [showConfirmDialog, setShowConfirmDialog] = useState(false) const [deploymentError, setDeploymentError] = useState(null) const [deploymentSuccess, setDeploymentSuccess] = useState(false) // Contexts and hooks const { wallet } = useWallet() const { deployRepository, isDeploying: isRepoDeploying } = useDeployment() const { deployTemplate, isDeploying: isTemplateDeploying } = useTemplateDeployment() // Determine deployment type and get the right deploying state const isTemplateMode = formData.deploymentMode === 'template' const isDeploying = isTemplateMode ? isTemplateDeploying : isRepoDeploying // Handle hydration mismatch by waiting for mount useEffect(() => { setMounted(true) }, []) // Get deployment info const getDeploymentInfo = () => { if (isTemplateMode) { return { name: formData.template?.name || 'Template Project', source: formData.template?.repoFullName || 'Unknown Template', projectName: formData.projectName || 'New Project', type: 'Template' } } else { return { name: formData.githubRepo?.split('/').pop() || 'Repository', source: formData.githubRepo || 'Unknown Repository', projectName: formData.projectName || formData.githubRepo?.split('/').pop() || 'New Project', type: 'Repository' } } } const deploymentInfo = getDeploymentInfo() // Open the confirmation modal const handlePayAndDeploy = () => { if (!wallet?.address) { toast.error('Wallet not connected') return } if (!formData.selectedOrg) { toast.error('No organization selected') return } if (isTemplateMode && (!formData.template || !formData.projectName)) { toast.error('Template or project name missing') return } if (!isTemplateMode && !formData.githubRepo) { toast.error('Repository not selected') return } setShowConfirmDialog(true) } // Close the confirmation modal const handleCancelConfirm = () => { setShowConfirmDialog(false) } // Handle confirmed deployment const handleConfirmDeploy = async () => { setShowConfirmDialog(false) setDeploymentError(null) setDeploymentSuccess(false) try { if (isTemplateMode) { await deployTemplateProject() } else { await deployRepositoryProject() } } catch (error) { console.error('Deployment failed:', error) setDeploymentError(error instanceof Error ? error.message : 'Deployment failed') } } // Deploy template project const deployTemplateProject = async () => { if (!formData.template || !formData.projectName || !formData.selectedOrg) { throw new Error('Missing required template deployment data') } const config = { template: formData.template, projectName: formData.projectName, organizationSlug: formData.selectedOrg, environmentVariables: formData.environmentVariables || [], deployerLrn: formData.selectedLrn } console.log('Deploying template with config:', config) const result = await deployTemplate(config) // Save deployment results setFormData({ deploymentId: result.deploymentId, deploymentUrl: result.deploymentUrl, projectId: result.projectId, repositoryUrl: result.repositoryUrl }) setDeploymentSuccess(true) toast.success('Template deployed successfully!') // Move to success step after short delay setTimeout(() => { nextStep() }, 2000) } // Deploy repository project const deployRepositoryProject = async () => { if (!formData.githubRepo || !formData.selectedOrg) { throw new Error('Missing required repository deployment data') } const config = { projectId: '', // Will be generated by backend organizationSlug: formData.selectedOrg, repository: formData.githubRepo, branch: 'main', // Default branch name: formData.projectName || formData.githubRepo.split('/').pop() || 'New Project', environmentVariables: formData.environmentVariables || [] } console.log('Deploying repository with config:', config) const result = await deployRepository(config) // Save deployment results setFormData({ deploymentId: result.id, deploymentUrl: result.url, projectId: result.id }) setDeploymentSuccess(true) toast.success('Repository deployed successfully!') // Move to success step after short delay setTimeout(() => { nextStep() }, 2000) } // Don't render UI until after mount to prevent hydration mismatch if (!mounted) { return null } // Determine if dark mode is active const isDarkMode = resolvedTheme === 'dark' return ( <>
{/* Deploy icon */}
{/* Deploy header */}

{isDeploying ? 'Deploying...' : 'Deploy'}

{isDeploying ? 'Your project is being deployed. This may take a few minutes.' : 'Review and confirm deployment'}

{/* Deployment Summary */} Deployment Summary {deploymentInfo.type}
{deploymentInfo.projectName}
{deploymentInfo.source}
Organization
{formData.selectedOrg}
Deployer
{formData.selectedLrn ? 'LRN' : 'Auction'}
{formData.environmentVariables && formData.environmentVariables.length > 0 && (
Environment Variables
{formData.environmentVariables.length} variable{formData.environmentVariables.length !== 1 ? 's' : ''} configured
)}
{/* Error Display */} {deploymentError && (
Deployment Failed
{deploymentError}
)} {/* Success Display */} {deploymentSuccess && (
Deployment Successful!
Your project has been deployed successfully. You'll be redirected to the project dashboard.
)} {/* Deployment Progress - Only show while deploying */} {isDeploying && (
{isTemplateMode ? 'Creating repository from template...' : 'Deploying repository...'}
This process may take several minutes. Please do not close this window.
)} {/* Navigation buttons */}
{deploymentSuccess ? ( ) : isDeploying ? ( ) : ( )}
{/* Transaction Confirmation Dialog */} Confirm Deployment Review the deployment details before proceeding.
{/* Project Info */}

Project Details

Name: {deploymentInfo.projectName}
Type: {deploymentInfo.type}
Source: {deploymentInfo.source}
{/* Wallet Info */}

Payment Address

{wallet?.address}
{/* Deployer Info */} {formData.selectedLrn && (

Deployer

{formData.selectedLrn}
)} {/* Cost Info */} {formData.deploymentType === 'auction' && (

Auction Details

Max Price: {formData.maxPrice} aint
Deployers: {formData.deployerCount}
)}
) }