import { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/button"; import { RefreshCw, Settings } from "lucide-react"; import { toast } from "sonner"; import { SkillCard } from "./SkillCard"; import { RepoManager } from "./RepoManager"; import { skillsApi, type Skill, type SkillRepo } from "@/lib/api/skills"; interface SkillsPageProps { onClose?: () => void; } export function SkillsPage({ onClose: _onClose }: SkillsPageProps = {}) { const { t } = useTranslation(); const [skills, setSkills] = useState([]); const [repos, setRepos] = useState([]); const [loading, setLoading] = useState(true); const [repoManagerOpen, setRepoManagerOpen] = useState(false); const loadSkills = async (afterLoad?: (data: Skill[]) => void) => { try { setLoading(true); const data = await skillsApi.getAll(); setSkills(data); if (afterLoad) { afterLoad(data); } } catch (error) { toast.error(t("skills.loadFailed"), { description: error instanceof Error ? error.message : t("common.error"), }); } finally { setLoading(false); } }; const loadRepos = async () => { try { const data = await skillsApi.getRepos(); setRepos(data); } catch (error) { console.error("Failed to load repos:", error); } }; useEffect(() => { Promise.all([loadSkills(), loadRepos()]); }, []); const handleInstall = async (directory: string) => { try { await skillsApi.install(directory); toast.success(t("skills.installSuccess", { name: directory })); await loadSkills(); } catch (error) { toast.error(t("skills.installFailed"), { description: error instanceof Error ? error.message : t("common.error"), }); } }; const handleUninstall = async (directory: string) => { try { await skillsApi.uninstall(directory); toast.success(t("skills.uninstallSuccess", { name: directory })); await loadSkills(); } catch (error) { toast.error(t("skills.uninstallFailed"), { description: error instanceof Error ? error.message : t("common.error"), }); } }; const handleAddRepo = async (repo: SkillRepo) => { await skillsApi.addRepo(repo); let repoSkillCount = 0; await Promise.all([ loadRepos(), loadSkills((data) => { repoSkillCount = data.filter( (skill) => skill.repoOwner === repo.owner && skill.repoName === repo.name && (skill.repoBranch || "main") === (repo.branch || "main"), ).length; }), ]); toast.success( t("skills.repo.addSuccess", { owner: repo.owner, name: repo.name, count: repoSkillCount, }), ); }; const handleRemoveRepo = async (owner: string, name: string) => { await skillsApi.removeRepo(owner, name); toast.success(t("skills.repo.removeSuccess", { owner, name })); await Promise.all([loadRepos(), loadSkills()]); }; return (
{/* 顶部操作栏(固定区域) */}

{t("skills.title")}

{/* 描述 */}

{t("skills.description")}

{/* 技能网格(可滚动详情区域) */}
{loading ? (
) : skills.length === 0 ? (

{t("skills.empty")}

{t("skills.emptyDescription")}

) : (
{skills.map((skill) => ( ))}
)}
{/* 仓库管理对话框 */}
); }