import { useState, useEffect, useCallback } from 'react'; import { createLogger } from '@automaker/utils/logger'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { getHttpApiClient } from '@/lib/http-api-client'; import { getErrorMessage } from '@/lib/utils'; import { Download, Upload, RefreshCw, AlertTriangle } from 'lucide-react'; import { Spinner } from '@/components/ui/spinner'; import type { WorktreeInfo } from '../worktree-panel/types'; interface RemoteInfo { name: string; url: string; } const logger = createLogger('SelectRemoteDialog'); export type SelectRemoteOperation = 'pull' | 'push'; interface SelectRemoteDialogProps { open: boolean; onOpenChange: (open: boolean) => void; worktree: WorktreeInfo | null; operation: SelectRemoteOperation; onConfirm: (worktree: WorktreeInfo, remote: string) => void; } export function SelectRemoteDialog({ open, onOpenChange, worktree, operation, onConfirm, }: SelectRemoteDialogProps) { const [remotes, setRemotes] = useState([]); const [selectedRemote, setSelectedRemote] = useState(''); const [isLoading, setIsLoading] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false); const [error, setError] = useState(null); const fetchRemotes = useCallback(async () => { if (!worktree) return; setIsLoading(true); setError(null); try { const api = getHttpApiClient(); const result = await api.worktree.listRemotes(worktree.path); if (result.success && result.result) { const remoteInfos = result.result.remotes.map((r: { name: string; url: string }) => ({ name: r.name, url: r.url, })); setRemotes(remoteInfos); setSelectedRemote((prev) => { if (prev && remoteInfos.some((r) => r.name === prev)) { return prev; } return remoteInfos.find((r) => r.name === 'origin')?.name ?? remoteInfos[0]?.name ?? ''; }); } else { setError(result.error || 'Failed to fetch remotes'); } } catch (err) { logger.error('Failed to fetch remotes:', err); setError(getErrorMessage(err)); } finally { setIsLoading(false); } }, [worktree]); // Fetch remotes when dialog opens useEffect(() => { if (open && worktree) { fetchRemotes(); } }, [open, worktree, fetchRemotes]); // Reset state when dialog closes useEffect(() => { if (!open) { setSelectedRemote(''); setError(null); } }, [open]); // Auto-select default remote when remotes are loaded useEffect(() => { if (remotes.length > 0 && !selectedRemote) { // Default to 'origin' if available, otherwise first remote const defaultRemote = remotes.find((r) => r.name === 'origin') || remotes[0]; setSelectedRemote(defaultRemote.name); } }, [remotes, selectedRemote]); const handleRefresh = async () => { if (!worktree) return; setIsRefreshing(true); setError(null); try { const api = getHttpApiClient(); const result = await api.worktree.listRemotes(worktree.path); if (result.success && result.result) { const remoteInfos = result.result.remotes.map((r: { name: string; url: string }) => ({ name: r.name, url: r.url, })); setRemotes(remoteInfos); setSelectedRemote((prev) => { if (prev && remoteInfos.some((r) => r.name === prev)) { return prev; } return remoteInfos.find((r) => r.name === 'origin')?.name ?? remoteInfos[0]?.name ?? ''; }); } else { setError(result.error || 'Failed to refresh remotes'); } } catch (err) { logger.error('Failed to refresh remotes:', err); setError(getErrorMessage(err)); } finally { setIsRefreshing(false); } }; const handleConfirm = () => { if (!worktree || !selectedRemote) return; onConfirm(worktree, selectedRemote); onOpenChange(false); }; const isPull = operation === 'pull'; const Icon = isPull ? Download : Upload; const title = isPull ? 'Pull from Remote' : 'Push to Remote'; const actionLabel = isPull ? `Pull from ${selectedRemote || 'Remote'}` : `Push to ${selectedRemote || 'Remote'}`; const description = isPull ? ( <> Select a remote to pull changes into{' '} {worktree?.branch || 'current branch'} ) : ( <> Select a remote to push{' '} {worktree?.branch || 'current branch'} to ); return ( {title} {description} {isLoading ? (
) : error ? (
{error}
) : (
{selectedRemote && (

{isPull ? ( <> This will pull changes from{' '} {selectedRemote}/{worktree?.branch} {' '} into your local branch. ) : ( <> This will push your local changes to{' '} {selectedRemote}/{worktree?.branch} . )}

)}
)}
); }