Skip to content

Commit cb88c9c

Browse files
committed
✨ feat(tracker): Improve Tracker page UI/UX & add Repositories tab
1 parent 4ae0ef6 commit cb88c9c

2 files changed

Lines changed: 1082 additions & 306 deletions

File tree

src/hooks/useGitHubRepos.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useState, useCallback } from 'react';
2+
import { Octokit } from '@octokit/core';
3+
4+
export interface GitHubRepo {
5+
id: number;
6+
name: string;
7+
full_name: string;
8+
html_url: string;
9+
description: string | null;
10+
language: string | null;
11+
stargazers_count: number;
12+
forks_count: number;
13+
open_issues_count: number;
14+
visibility: string;
15+
fork: boolean;
16+
pushed_at: string;
17+
created_at: string;
18+
updated_at: string;
19+
topics: string[];
20+
license: { name: string } | null;
21+
default_branch: string;
22+
size: number;
23+
}
24+
25+
export const useGitHubRepos = (getOctokit: () => Octokit | null) => {
26+
const [repos, setRepos] = useState<GitHubRepo[]>([]);
27+
const [totalRepos, setTotalRepos] = useState(0);
28+
const [loading, setLoading] = useState(false);
29+
const [error, setError] = useState('');
30+
31+
const fetchRepos = useCallback(
32+
async (username: string, page = 1, perPage = 12) => {
33+
const octokit = getOctokit();
34+
if (!octokit || !username.trim()) return;
35+
36+
setLoading(true);
37+
setError('');
38+
39+
try {
40+
const response = await octokit.request('GET /users/{username}/repos', {
41+
username,
42+
per_page: perPage,
43+
page,
44+
sort: 'pushed',
45+
direction: 'desc',
46+
type: 'owner',
47+
});
48+
49+
const linkHeader = (response.headers as any)?.link ?? '';
50+
const lastMatch = linkHeader.match(/page=(\d+)>; rel="last"/);
51+
const total = lastMatch
52+
? parseInt(lastMatch[1], 10) * perPage
53+
: (page - 1) * perPage + response.data.length;
54+
55+
setRepos(response.data as GitHubRepo[]);
56+
setTotalRepos(total);
57+
} catch (err: any) {
58+
const status = err?.status;
59+
const message = err?.message?.toLowerCase() ?? '';
60+
61+
if (status === 403) {
62+
setError('GitHub API rate limit exceeded. Please provide a PAT to continue.');
63+
} else if (status === 404 || message.includes('not found')) {
64+
setError('User not found. Please check the GitHub username.');
65+
} else if (status === 401) {
66+
setError('Invalid token. Please check your Personal Access Token.');
67+
} else {
68+
setError('Unable to fetch repositories. Please verify the username or network connection.');
69+
}
70+
} finally {
71+
setLoading(false);
72+
}
73+
},
74+
[getOctokit]
75+
);
76+
77+
return { repos, totalRepos, loading, error, fetchRepos };
78+
};

0 commit comments

Comments
 (0)