import { useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import type { SkillSource } from '@paperclipai/shared'; import { skillSourcesApi } from '@/api/skillSources'; import { ApiError } from '@/api/client'; import { queryKeys } from '@/lib/queryKeys'; import { Link } from '@/lib/router'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { RadioCardGroup } from '@/components/ui/radio-card'; import { SkillSourceBranchRepair } from './SkillSourceBranchRepair'; export function SkillSourceConnectionRepair({ companyId, source, onClose, onSaved, onReturnFocus }: { companyId: string; source: SkillSource; onClose: () => void; onSaved: () => Promise; onReturnFocus?: () => void; }) { const [connectionId, setConnectionId] = useState(source.connectionId ?? ''); const [chooseBranch, setChooseBranch] = useState(false); const client = useQueryClient(); const query = useQuery({ queryKey: queryKeys.skillSources.repositories(companyId), queryFn: () => skillSourcesApi.repositories(companyId), refetchOnMount: 'always', retry: false }); const save = useMutation({ mutationFn: () => skillSourcesApi.settings(companyId, source.id, { revision: source.revision, connectionId }), onError: async error => { if (error instanceof ApiError && error.status === 409 && (error.body as { code?: string } | null)?.code === 'skill_source_settings_changed') { await client.invalidateQueries({ queryKey: queryKeys.skillSources.all(companyId) }); } }, onSuccess: async () => { await onSaved(); onClose(); } }); const connections = query.data?.connections ?? []; const branchMissing = save.error instanceof ApiError && (save.error.body as { code?: string } | null)?.code === 'skill_source_ref_unavailable'; const canSave = connections.some(connection => connection.id === connectionId); if (chooseBranch) return setChooseBranch(false)} onReturnFocus={onReturnFocus} onSaved={async () => { await onSaved(); onClose(); }} />; return { if (!open && !save.isPending) onClose(); }}> { if (onReturnFocus) { event.preventDefault(); onReturnFocus(); } }}> Choose GitHub connection Automatic updates will use your access to this connection. Installed skills and selections stay in place.
{query.isPending &&

Loading connections…

} {query.error &&

{query.error.message}

} ({ value: connection.id, title: connection.name }))} /> {query.isSuccess && connections.length === 0 &&

Connect GitHub to continue.

} {save.error &&

{save.error instanceof ApiError && save.error.status === 409 && (save.error.body as { code?: string } | null)?.code === 'skill_source_settings_changed' ? 'This source was updated. Your connection is still selected. Save again to apply it.' : save.error.message}

} {branchMissing && source.accessScope !== 'projects' && !source.projects?.some(project => project.active) && }
; }