Files
spoon/apps/next/src/components/integrations/github-integration-panel.tsx
T

115 lines
3.6 KiB
TypeScript

'use client';
import { useAction, useQuery } from 'convex/react';
import { makeFunctionReference } from 'convex/server';
import { Github, RefreshCw } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@spoon/backend/convex/_generated/api.js';
import { Button, Card, CardContent, CardHeader, CardTitle } from '@spoon/ui';
const listReposRef = makeFunctionReference<
'action',
Record<string, never>,
{
id: number;
name: string;
fullName: string;
owner: string;
private: boolean;
fork: boolean;
url: string;
defaultBranch: string;
description?: string;
}[]
>('githubNode:listInstallationRepositories');
export const GithubIntegrationPanel = () => {
const connection = useQuery(api.github.getConnection, {});
const installUrl = useQuery(api.github.getInstallUrl, {});
const listRepos = useAction(listReposRef);
const refresh = async () => {
try {
const repos = await listRepos({});
toast.success(`GitHub can access ${repos.length} repositories.`);
} catch (error) {
console.error(error);
toast.error('Could not list GitHub repositories.');
}
};
return (
<Card className='shadow-none'>
<CardHeader>
<CardTitle className='flex items-center gap-2 text-base'>
<Github className='size-4' />
GitHub App
</CardTitle>
</CardHeader>
<CardContent className='space-y-4'>
{connection && connection.status !== 'active' ? (
<div
className={
connection.status === 'revoked'
? 'rounded-md border border-red-500/40 bg-red-500/10 p-3 text-sm text-red-600'
: 'rounded-md border border-amber-500/40 bg-amber-500/10 p-3 text-sm text-amber-600'
}
>
<p className='font-medium'>
{connection.status === 'revoked'
? 'GitHub App installation removed'
: 'GitHub access needs re-authorization'}
</p>
<p className='mt-1'>
{connection.status === 'revoked'
? 'Reinstall the app to resume syncing.'
: 'Reconnect the app to resume syncing.'}
</p>
{installUrl ? (
<a
className='mt-2 inline-block underline'
href={installUrl}
target='_blank'
rel='noreferrer'
>
Reconnect GitHub App
</a>
) : null}
</div>
) : null}
{connection ? (
<div className='grid gap-2 text-sm'>
<div>
<p className='text-muted-foreground'>Connected account</p>
<p className='font-medium'>{connection.displayName}</p>
</div>
<div>
<p className='text-muted-foreground'>Installation ID</p>
<p className='font-mono text-xs'>{connection.installationId}</p>
</div>
</div>
) : (
<p className='text-muted-foreground text-sm'>
Install the GitHub App to let Spoon create forks and refresh
repository state.
</p>
)}
<div className='flex flex-wrap gap-2'>
{installUrl ? (
<Button asChild>
<a href={installUrl} target='_blank' rel='noreferrer'>
Configure GitHub App
</a>
</Button>
) : null}
<Button variant='outline' onClick={refresh} disabled={!connection}>
<RefreshCw className='size-4' />
Check repository access
</Button>
</div>
</CardContent>
</Card>
);
};