laconic-deployer-frontend/apps/deploy-fe/src/hooks/useRepoSelection.tsx

164 lines
4.7 KiB
TypeScript

'use client'
// src/hooks/useRepoSelection.ts
import { useState, useEffect } from 'react'
import { useOctokit } from '@/context/OctokitContext'
import { adaptRepositories, type GitHubRepo } from '../utils/typeAdapters';
interface Repository {
id: string;
name: string;
full_name: string;
default_branch: string;
html_url: string;
description?: string;
owner?: {
login: string;
avatar_url: string;
};
}
interface UseRepoSelectionResult {
repositories: Repository[];
isLoading: boolean;
error: Error | null;
fetchBranches: (repoFullName: string) => Promise<string[]>;
}
export function useRepoSelection(): UseRepoSelectionResult {
const [repositories, setRepositories] = useState<Repository[]>([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState<Error | null>(null)
const { octokit, isAuth } = useOctokit()
// Fetch repositories on component mount
useEffect(() => {
const fetchRepositories = async () => {
setIsLoading(true)
setError(null)
try {
if (isAuth && octokit) {
try {
// Try to fetch repositories from GitHub
const response = await octokit.request('GET /user/repos', {
sort: 'updated',
per_page: 100
});
if (response.data && Array.isArray(response.data)) {
const repoData = response.data.map(repo => ({
id: repo.id.toString(),
name: repo.name,
full_name: repo.full_name,
default_branch: repo.default_branch,
html_url: repo.html_url,
description: repo.description,
owner: {
login: repo.owner.login,
avatar_url: repo.owner.avatar_url
}
}));
setRepositories(adaptRepositories(repoData as GitHubRepo[]));
}
} catch (err) {
console.error('Failed to fetch repositories:', err);
// Fall back to mock data
setRepositories(getMockRepositories());
}
} else {
// If not authenticated, use mock data
setRepositories(getMockRepositories());
}
} catch (err) {
const fetchError = err instanceof Error ? err : new Error('Failed to fetch repositories');
setError(fetchError);
console.error('Error in useRepoSelection hook:', fetchError);
setRepositories(getMockRepositories());
} finally {
setIsLoading(false);
}
};
fetchRepositories();
}, [octokit, isAuth]);
// Function to fetch branches for a selected repository
const fetchBranches = async (repoFullName: string): Promise<string[]> => {
if (!repoFullName) return ['main'];
try {
if (isAuth && octokit) {
const [owner, repo] = repoFullName.split('/');
if (!owner || !repo) {
throw new Error('Invalid repository format');
}
const response = await octokit.request('GET /repos/{owner}/{repo}/branches', {
owner,
repo
});
if (response.data && Array.isArray(response.data)) {
return response.data.map(branch => branch.name);
}
}
// Return mock data if unable to fetch
return ['main', 'develop', 'feature/new-ui'];
} catch (err) {
console.error('Failed to fetch branches:', err);
// Return some default branches
return ['main', 'develop', 'feature/new-ui'];
}
};
return {
repositories,
isLoading,
error,
fetchBranches
};
}
// Mock repository data for fallback
function getMockRepositories(): Repository[] {
return [
{
id: '1',
name: 'my-next-app',
full_name: 'yourusername/my-next-app',
default_branch: 'main',
html_url: 'https://github.com/yourusername/my-next-app',
description: 'A Next.js application',
owner: {
login: 'yourusername',
avatar_url: 'https://github.com/github.png'
}
},
{
id: '2',
name: 'react-portfolio',
full_name: 'yourusername/react-portfolio',
default_branch: 'master',
html_url: 'https://github.com/yourusername/react-portfolio',
description: 'Personal portfolio website',
owner: {
login: 'yourusername',
avatar_url: 'https://github.com/github.png'
}
},
{
id: '3',
name: 'node-api',
full_name: 'yourusername/node-api',
default_branch: 'main',
html_url: 'https://github.com/yourusername/node-api',
description: 'RESTful API with Node.js',
owner: {
login: 'yourusername',
avatar_url: 'https://github.com/github.png'
}
}
];
}