Skip to content

Commit eee6246

Browse files
committed
feat: enhance layout and server discovery UI
- Added GitHubStars component to the layout for improved visibility of project popularity. - Updated the server list empty state message to provide clearer feedback to users. - Refactored the Discovery page to implement a tabbed interface for better organization of server categories, utilizing the ServerList component for displaying discovered servers.
1 parent 1d317c8 commit eee6246

File tree

5 files changed

+92
-89
lines changed

5 files changed

+92
-89
lines changed

src/components/Layout/index.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useClientPathStore } from "@/stores/clientPathStore";
44
import { useTranslation } from "react-i18next";
55
import { Toaster } from "sonner";
66
import { ClientSelector } from "../settings/client-selector";
7+
import GitHubStars from "../settings/GithubStars";
78
import LangSelect from "../settings/LangSelect";
89
import { PathSelector } from "../settings/PathSelector";
910
import { Sidebar } from "./Sidebar";
@@ -21,10 +22,15 @@ const Layout = () => {
2122

2223
<div className="flex-1 flex flex-col overflow-hidden">
2324
{/* Header Controls */}
24-
<div className="flex justify-between pt-2 px-2 shrink-0">
25-
<ClientSelector />
26-
{needspathClient.includes(selectedClient) && <PathSelector />}
27-
<LangSelect />
25+
<div className="flex justify-between pt-2 px-2 shrink-0 items-center">
26+
<div className="flex items-center gap-2">
27+
<ClientSelector />
28+
{needspathClient.includes(selectedClient) && <PathSelector />}
29+
</div>
30+
<div className="flex items-center gap-2">
31+
<LangSelect />
32+
<GitHubStars />
33+
</div>
2834
</div>
2935

3036
{/* Main Content */}

src/components/server/list/ServerList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ export function ServerList({ mcpServers, onDelete }: ServerListProps) {
4444
// Handle empty state
4545
if (mcpServers.length === 0) {
4646
return (
47-
<div className="flex flex-col items-center justify-center p-8 text-gray-500">
48-
<p>No servers match your criteria</p>
47+
<div className="flex flex-col items-center justify-center text-gray-500">
48+
<p>No servers match your criteria, Editor updating</p>
4949
</div>
5050
);
5151
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// src/components/settings/GitHubStars.tsx
2+
import { useQuery } from "@tanstack/react-query";
3+
import { open } from "@tauri-apps/plugin-shell";
4+
import { Github } from "lucide-react";
5+
6+
7+
const fetchStarCount = async () => {
8+
const res = await fetch("https://api.github.com/repos/milisp/mcp-linker");
9+
if (!res.ok) throw new Error("Failed to fetch");
10+
const data = await res.json();
11+
return data.stargazers_count;
12+
};
13+
14+
const GitHubStars = () => {
15+
const { data, isLoading } = useQuery({
16+
queryKey: ["github-stars"],
17+
queryFn: fetchStarCount,
18+
staleTime: 1000 * 60 * 10, // 10 mins
19+
});
20+
21+
return (
22+
<button
23+
onClick={() => open("https://github.com/milisp/mcp-linker")}
24+
rel="noopener noreferrer"
25+
className="flex items-center gap-1 rounded-md bg-gray-100 dark:bg-gray-800 px-2 py-1 text-sm font-medium text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-700 transition"
26+
>
27+
<Github size={14} />
28+
Star
29+
<span className="font-semibold">{isLoading ? "…" : data}</span>
30+
</button>
31+
);
32+
};
33+
34+
export default GitHubStars;

src/pages/Discover.tsx

Lines changed: 39 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,50 @@
11
import { HeroBanner } from "@/components/banner";
2-
import { ServerTemplateDialog } from "@/components/server/dialog/ServerTemplateDialog";
2+
import { ServerList } from "@/components/server";
3+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
4+
import { api } from "@/lib/api";
5+
import { useQuery } from "@tanstack/react-query";
36
import { useState } from "react";
4-
import { useTranslation } from "react-i18next";
57

6-
// Import refactored components
7-
import { DiscoveryHeader } from "@/components/discovery/DiscoveryHeader";
8-
import { InfiniteScrollServers } from "@/components/discovery/InfiniteScrollServers";
9-
import { ScrollToBottomButton } from "@/components/discovery/ScrollToBottomButton";
10-
import { useServerDiscovery } from "@/hooks/useServerDiscovery";
8+
const tabs = [
9+
{ key: "is_official", label: "Official Servers" },
10+
{ key: "github_stars", label: "Most GitHub Stars" },
11+
{ key: "must_have", label: "Must Have" },
12+
{ key: "featured", label: "Featured" },
13+
{ key: "best_new", label: "Best New" },
14+
{ key: "editors_choice", label: "Editors Choice" },
15+
{ key: "developer_tools", label: "Developer Tools" },
16+
];
1117

12-
import { useAuth } from "@/hooks/useAuth";
13-
import { useNavigate } from "react-router-dom";
1418
export default function Discovery() {
15-
const { t } = useTranslation();
16-
const [isSell, setIsSell] = useState(false);
17-
const [isDialogOpen, setIsDialogOpen] = useState(false);
19+
const [selectedTab, setSelectedTab] = useState<string>("is_official");
1820

19-
const navigate = useNavigate();
20-
const { user } = useAuth();
21-
22-
// Use our custom hook for server discovery logic
23-
const {
24-
allServers,
25-
isLoading,
26-
isFetching,
27-
loadMoreRef,
28-
hasNext,
29-
sort,
30-
direction,
31-
handleSortChange,
32-
loadMore,
33-
scrollToLoadMore,
34-
} = useServerDiscovery();
35-
36-
// Dialog handlers
37-
const handleAddServer = () => {
38-
setIsSell(false);
39-
setIsDialogOpen(true);
40-
};
41-
42-
const handleSellServer = () => {
43-
// Check if user is authenticated before allowing server selling
44-
if (!user) {
45-
navigate("/auth");
46-
return;
47-
}
48-
49-
// User is authenticated, proceed with sell server dialog
50-
setIsSell(true);
51-
setIsDialogOpen(true);
52-
};
21+
const { data: discoverServers, isLoading, error } = useQuery({
22+
queryKey: ["discover-servers", selectedTab],
23+
queryFn: async () => {
24+
const res = await api.get(`/servers/discover?tab=${selectedTab}`);
25+
return res.data;
26+
},
27+
});
5328

5429
return (
55-
<div className="p-8">
56-
<h1 className="text-3xl font-bold mb-8 text-gray-900 dark:text-gray-100 sr-only">
57-
{t("nav.discover")}
58-
</h1>
59-
60-
{/* Hero banner */}
30+
<div className="p-8 space-y-4">
6131
<HeroBanner />
62-
63-
{/* Header with sorting and action buttons */}
64-
<DiscoveryHeader
65-
sort={sort}
66-
direction={direction}
67-
onSortChange={handleSortChange}
68-
onAddServer={handleAddServer}
69-
onSellServer={handleSellServer}
70-
isAuthenticated={!!user}
71-
/>
72-
73-
{/* Server list with infinite scrolling */}
74-
<InfiniteScrollServers
75-
servers={allServers}
76-
isLoading={isLoading}
77-
isFetching={isFetching}
78-
hasNext={hasNext}
79-
loadMoreRef={loadMoreRef}
80-
onLoadMore={loadMore}
81-
/>
82-
83-
{/* Scroll to bottom button */}
84-
<ScrollToBottomButton onClick={scrollToLoadMore} />
85-
86-
{/* Server template dialog */}
87-
<ServerTemplateDialog
88-
isOpen={isDialogOpen}
89-
setIsDialogOpen={setIsDialogOpen}
90-
isSell={isSell}
91-
/>
32+
<Tabs defaultValue="is_official" onValueChange={(val) => setSelectedTab(val)}>
33+
<TabsList className="mb-8 flex flex-wrap gap-2">
34+
{tabs.map((tab) => (
35+
<TabsTrigger key={tab.key} value={tab.key}
36+
className="rounded-md border px-4 py-2 text-sm font-medium transition-colors hover:bg-muted data-[state=active]:bg-primary data-[state=active]:text-white"
37+
>
38+
{tab.label}
39+
</TabsTrigger>
40+
))}
41+
</TabsList>
42+
<TabsContent value={selectedTab}>
43+
{isLoading && <div>Loading...</div>}
44+
{error && <div>Error loading servers.</div>}
45+
{!isLoading && !error && <ServerList mcpServers={discoverServers ?? []} />}
46+
</TabsContent>
47+
</Tabs>
9248
</div>
9349
);
94-
}
50+
}

src/pages/TeamPage.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ export default function TeamPage() {
7171
<Plus className="mr-2 h-4 w-4" />
7272
Create Team
7373
</Button>
74+
<Button
75+
onClick={() => {
76+
navigate("/manage")
77+
}}
78+
>
79+
Manage Servers
80+
</Button>
7481
</div>
7582
</div>
7683

0 commit comments

Comments
 (0)