Skip to main content
Glama
category-showcase.tsx3.22 kB
"use client"; import { McpApp } from "@repo/db/types"; import { Alert, AlertDescription, AlertTitle } from "@repo/ui/components/ui/alert"; import { Button } from "@repo/ui/components/ui/button"; import { Skeleton } from "@repo/ui/components/ui/skeleton"; import { AlertCircle, RefreshCw } from "lucide-react"; import { useState } from "react"; import { AppGrid } from "@/components/web/app-grid"; import { LoadMoreButton } from "@/components/web/load-more-button"; import { trpc } from "@/lib/trpc/client"; interface CategoryShowcaseProps { category: "client" | "server" | "application"; selectedTag?: string | null; selectedCategory?: string | null; limit?: number; } const AppCardSkeleton = () => ( <div className="space-y-3"> <Skeleton className="h-48 w-full rounded-lg" /> <div className="space-y-2"> <Skeleton className="h-6 w-3/4" /> <Skeleton className="h-4 w-1/2" /> </div> <div className="flex gap-2"> <Skeleton className="h-6 w-16" /> <Skeleton className="h-6 w-16" /> </div> <div className="flex items-center gap-2"> <Skeleton className="h-8 w-8 rounded-full" /> <div className="space-y-1"> <Skeleton className="h-4 w-24" /> <Skeleton className="h-3 w-16" /> </div> </div> </div> ); export function CategoryShowcase({ category, selectedTag, selectedCategory, limit = 21, }: CategoryShowcaseProps) { const [visibleCount, setVisibleCount] = useState(limit); const { data: apps, isLoading, error, refetch } = trpc.mcpApps.getByTypeCategoryAndTag.useQuery( { type: category, category: selectedCategory || undefined, tag: selectedTag || undefined, }, { enabled: true, } ); const loadMore = () => { setVisibleCount((prev) => prev + limit); }; // 加载状态 if (isLoading) { return ( <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3"> {Array.from({ length: 6 }).map((_, i) => ( <AppCardSkeleton key={i} /> ))} </div> ); } // 错误状态 if (error) { return ( <Alert variant="destructive"> <AlertCircle className="h-4 w-4" /> <AlertTitle>加载失败</AlertTitle> <AlertDescription> <p className="mb-2">获取应用数据时出错。请稍后再试。</p> <Button variant="outline" size="sm" onClick={() => refetch()} className="mt-2"> <RefreshCw className="mr-2 h-4 w-4" /> 重试 </Button> </AlertDescription> </Alert> ); } // 空状态 if (!apps || apps.length === 0) { return ( <div className="text-center py-12"> <h3 className="text-xl font-medium mb-2">没有找到应用</h3> <p className="text-muted-foreground"> {selectedTag ? "没有与所选标签匹配的应用。" : selectedCategory ? "没有与所选分类匹配的应用。" : "此分类下暂无应用。"} </p> </div> ); } // 显示应用列表 return ( <div> <AppGrid apps={apps} /> {visibleCount < apps.length && <LoadMoreButton onClick={loadMore} />} </div> ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/metacode0602/open-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server