import React, { useState, useEffect, useCallback } from 'react'
import appLauncherService from '../services/appLauncherService'
interface LaunchControlsProps {
appId: string
appName: string
projectPath?: boolean
onStatusChange?: (running: boolean) => void
}
export default function LaunchControls({
appId,
appName,
projectPath = false,
onStatusChange
}: LaunchControlsProps) {
const [appRunning, setAppRunning] = useState(false)
const [selectedDesktop, setSelectedDesktop] = useState(1)
const [selectedMonitor, setSelectedMonitor] = useState(1)
const [projectPathValue, setProjectPathValue] = useState('')
const [launching, setLaunching] = useState(false)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
const checkAppStatus = async () => {
const status = await appLauncherService.getStatus()
const running = status[appId]?.running || false
setAppRunning(running)
if (onStatusChange) {
onStatusChange(running)
}
}
checkAppStatus()
const interval = setInterval(checkAppStatus, 5000)
return () => clearInterval(interval)
}, [appId, onStatusChange])
const handleStart = useCallback(async () => {
setLaunching(true)
setError(null)
try {
const options: any = {
desktop_number: selectedDesktop,
monitor: selectedMonitor
}
if (projectPath && projectPathValue) {
options.project_path = projectPathValue
}
const result = await appLauncherService.launchApp(appId, options)
if (result.success) {
setAppRunning(true)
if (onStatusChange) {
onStatusChange(true)
}
} else {
setError(result.error || result.message || 'Failed to launch application')
}
} catch (error) {
console.error(`Failed to launch ${appId}:`, error)
setError(error instanceof Error ? error.message : 'Failed to launch application')
} finally {
setLaunching(false)
}
}, [appId, selectedDesktop, selectedMonitor, projectPathValue, projectPath, onStatusChange])
const handleStop = useCallback(async () => {
try {
const result = await appLauncherService.stopApp(appId)
if (result.success) {
setAppRunning(false)
if (onStatusChange) {
onStatusChange(false)
}
}
} catch (error) {
console.error(`Failed to stop ${appId}:`, error)
}
}, [appId, onStatusChange])
return (
<div style={{
backgroundColor: '#1e293b',
borderRadius: '12px',
border: '1px solid #334155',
padding: '24px'
}}>
<h3 style={{ fontSize: '18px', fontWeight: '600', color: '#f8fafc', marginBottom: '16px' }}>
🚀 Launch {appName}
</h3>
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
{projectPath && (
<div>
<label style={{ display: 'block', fontSize: '12px', color: '#94a3b8', marginBottom: '4px' }}>
Project Path (optional)
</label>
<input
type="text"
value={projectPathValue}
onChange={(e) => setProjectPathValue(e.target.value)}
placeholder="C:/Projects/MyProject"
disabled={appRunning}
style={{
width: '100%',
padding: '8px 12px',
backgroundColor: '#0f172a',
border: '1px solid #334155',
borderRadius: '6px',
color: '#f8fafc',
fontSize: '12px',
opacity: appRunning ? 0.6 : 1
}}
/>
</div>
)}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
<div>
<label style={{ display: 'block', fontSize: '12px', color: '#94a3b8', marginBottom: '4px' }}>
Desktop
</label>
<select
value={selectedDesktop}
onChange={(e) => setSelectedDesktop(parseInt(e.target.value))}
disabled={appRunning}
style={{
width: '100%',
padding: '8px 12px',
backgroundColor: '#0f172a',
border: '1px solid #334155',
borderRadius: '6px',
color: '#f8fafc',
fontSize: '12px',
opacity: appRunning ? 0.6 : 1,
cursor: appRunning ? 'not-allowed' : 'pointer'
}}
>
{[1, 2, 3, 4].map(num => (
<option key={num} value={num}>Desktop {num}</option>
))}
</select>
</div>
<div>
<label style={{ display: 'block', fontSize: '12px', color: '#94a3b8', marginBottom: '4px' }}>
Monitor
</label>
<select
value={selectedMonitor}
onChange={(e) => setSelectedMonitor(parseInt(e.target.value))}
disabled={appRunning}
style={{
width: '100%',
padding: '8px 12px',
backgroundColor: '#0f172a',
border: '1px solid #334155',
borderRadius: '6px',
color: '#f8fafc',
fontSize: '12px',
opacity: appRunning ? 0.6 : 1,
cursor: appRunning ? 'not-allowed' : 'pointer'
}}
>
{[1, 2, 3, 4].map(num => (
<option key={num} value={num}>Monitor {num}</option>
))}
</select>
</div>
</div>
{error && (
<div style={{
padding: '12px 16px',
backgroundColor: '#dc2626',
borderRadius: '6px',
fontSize: '13px',
color: '#ffffff',
border: '1px solid #991b1b',
marginBottom: '8px'
}}>
<strong style={{ display: 'block', marginBottom: '4px' }}>Error:</strong>
{error}
</div>
)}
{!appRunning ? (
<button
onClick={handleStart}
disabled={launching}
style={{
width: '100%',
padding: '12px 16px',
backgroundColor: launching ? '#6b7280' : '#10b981',
color: 'white',
border: 'none',
borderRadius: '6px',
fontSize: '14px',
fontWeight: '600',
cursor: launching ? 'not-allowed' : 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px'
}}
>
{launching ? '🔄 Launching...' : `▶️ Start ${appName}`}
</button>
) : (
<>
<div style={{
padding: '8px 12px',
backgroundColor: '#10b981',
borderRadius: '6px',
fontSize: '12px',
color: 'white',
textAlign: 'center',
marginBottom: '8px'
}}>
✅ {appName} Running (Desktop {selectedDesktop}, Monitor {selectedMonitor})
</div>
<button
onClick={handleStop}
style={{
width: '100%',
padding: '12px 16px',
backgroundColor: '#dc2626',
color: 'white',
border: 'none',
borderRadius: '6px',
fontSize: '14px',
fontWeight: '600',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px'
}}
>
⏹️ Stop {appName}
</button>
</>
)}
</div>
</div>
)
}