import { useCallback, useEffect, useState } from 'react'; import { apiGitHubRepos, type GitHubRepoItem } from '../api'; export function GitHubReposPanel({ connected, canDeleteRepos = true }: { connected: boolean; canDeleteRepos?: boolean }) { const [repos, setRepos] = useState([]); const [githubLogin, setGithubLogin] = useState(''); const [selected, setSelected] = useState>(new Set()); const [loading, setLoading] = useState(false); const [deleting, setDeleting] = useState(false); const [msg, setMsg] = useState(''); const [err, setErr] = useState(''); const load = useCallback(async () => { if (!connected) { setRepos([]); return; } setLoading(true); setErr(''); try { const res = await apiGitHubRepos.list(); setRepos(res.data || []); setGithubLogin(res.githubLogin || ''); setSelected(new Set()); } catch (e: any) { setErr(e?.message || 'Không tải repo'); } finally { setLoading(false); } }, [connected]); useEffect(() => { load().catch(console.error); }, [load]); const toggle = (key: string) => { setSelected((prev) => { const next = new Set(prev); if (next.has(key)) next.delete(key); else next.add(key); return next; }); }; const toggleAll = () => { if (selected.size === repos.length) setSelected(new Set()); else setSelected(new Set(repos.map((r) => r.key))); }; const deleteSelected = async () => { if (selected.size === 0) return; if (!canDeleteRepos) { setErr('Chưa có quyền xóa repo — bấm Cấp quyền xóa repo ở trên.'); return; } if (!confirm(`Xóa ${selected.size} repo trên GitHub? Hành động không hoàn tác.`)) return; setErr(''); setMsg(''); setDeleting(true); try { const res = await apiGitHubRepos.bulkDelete([...selected]); if (res.deleted > 0) { setMsg(res.message || `Đã xóa ${res.deleted} repo`); if (res.failures?.length) setErr(res.failures.join('; ')); } else { setMsg(''); setErr(res.failures?.join('; ') || 'Không xóa được repo nào — thử ngắt kết nối rồi kết nối lại GitHub.'); } await load(); } catch (e: any) { setErr(e?.message || 'Xóa thất bại'); } finally { setDeleting(false); } }; const deleteOne = async (repo: GitHubRepoItem) => { if (!canDeleteRepos) { setErr('Chưa có quyền xóa repo — bấm Cấp quyền xóa repo ở trên.'); return; } if (!confirm(`Xóa repo "${repo.repoName}" trên GitHub?`)) return; setErr(''); setMsg(''); setDeleting(true); try { const res = await apiGitHubRepos.bulkDelete([repo.key]); if (res.deleted > 0) { setMsg(res.message || 'Đã xóa repo'); } else { setMsg(''); setErr(res.failures?.join('; ') || 'Không xóa được repo — thử ngắt kết nối rồi kết nối lại GitHub.'); } await load(); } catch (e: any) { setErr(e?.message || 'Xóa thất bại'); } finally { setDeleting(false); } }; if (!connected) return null; return (

Toàn bộ repo trên tài khoản GitHub{githubLogin ? ` @${githubLogin}` : ''} — có thể chọn và xóa nhiều repo cùng lúc.

{repos.length > 0 && ( <> )}
{err &&
{err}
} {msg &&
{msg}
} {repos.length === 0 && !loading ? (

Không có repo nào trên tài khoản GitHub (hoặc token thiếu quyền đọc repo).

) : (
{repos.map((r) => ( ))}
Repo Loại Phòng / SV Cập nhật
toggle(r.key)} /> {r.repoName} {r.private && private} {r.publishMode === 'student' ? ( Từng SV ) : r.publishMode === 'room' ? ( Gộp phòng ) : r.fromSimpleCare ? ( Simple Care ) : ( Khác )} {r.examRoomName &&
{r.examRoomName}
} {r.studentLabel &&
{r.studentLabel}
} {!r.examRoomName && !r.studentLabel && '—'}
{r.updatedAt ? new Date(r.updatedAt).toLocaleString('vi-VN') : new Date(r.createdAt).toLocaleString('vi-VN')}
)}
); }