=== NEW === - studio/ — MCPEngine Studio scaffold (Next.js monorepo, build plan) - docs/FACTORY-V2.md — Factory v2 architecture doc - docs/CALENDLY_MCP_BUILD_SUMMARY.md — Calendly MCP build report === UPDATED SERVERS === - fieldedge: Added jobs-tools, UI build script, main entry update - lightspeed: Updated main + server entry points - squarespace: Added collection-browser + page-manager apps - toast: Added main + server entry points === INFRA === - infra/command-center/state.json — Updated pipeline state - infra/command-center/FACTORY-V2.md — Factory v2 operator playbook
106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
'use client';
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
import { Wrench, LayoutGrid, GitFork, Star, BadgeCheck } from 'lucide-react';
|
|
import type { MarketplaceTemplate } from '@mcpengine/ai-pipeline/types';
|
|
|
|
const CATEGORY_COLORS: Record<string, string> = {
|
|
CRM: 'bg-blue-600',
|
|
eCommerce: 'bg-emerald-600',
|
|
HR: 'bg-violet-600',
|
|
Finance: 'bg-amber-600',
|
|
Marketing: 'bg-pink-600',
|
|
Support: 'bg-teal-600',
|
|
ProjectMgmt: 'bg-orange-600',
|
|
Scheduling: 'bg-cyan-600',
|
|
Analytics: 'bg-rose-600',
|
|
DevTools: 'bg-lime-600',
|
|
Social: 'bg-fuchsia-600',
|
|
Communication: 'bg-sky-600',
|
|
Storage: 'bg-indigo-600',
|
|
'AI/ML': 'bg-purple-600',
|
|
};
|
|
|
|
function getCategoryColor(category?: string): string {
|
|
return (category && CATEGORY_COLORS[category]) || 'bg-gray-600';
|
|
}
|
|
|
|
interface TemplateCardProps {
|
|
template: MarketplaceTemplate;
|
|
}
|
|
|
|
export function TemplateCard({ template }: TemplateCardProps) {
|
|
const router = useRouter();
|
|
|
|
return (
|
|
<div
|
|
onClick={() => router.push(`/marketplace/${template.id}`)}
|
|
className="
|
|
group relative flex flex-col rounded-xl border border-gray-800
|
|
bg-gray-900/80 p-5 cursor-pointer
|
|
transition-all duration-200
|
|
hover:scale-[1.02] hover:border-gray-600 hover:shadow-xl hover:shadow-indigo-900/10
|
|
"
|
|
>
|
|
{/* Official badge */}
|
|
{template.isOfficial && (
|
|
<div className="absolute top-3 right-3 flex items-center gap-1 text-xs font-medium
|
|
text-indigo-400 bg-indigo-500/10 px-2 py-0.5 rounded-full">
|
|
<BadgeCheck className="h-3.5 w-3.5" />
|
|
Official
|
|
</div>
|
|
)}
|
|
|
|
{/* Icon + name */}
|
|
<div className="flex items-start gap-3 mb-3">
|
|
<div
|
|
className={`
|
|
flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center
|
|
text-white font-bold text-sm ${getCategoryColor(template.category)}
|
|
`}
|
|
>
|
|
{template.name.charAt(0).toUpperCase()}
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<h3 className="font-semibold text-gray-100 truncate group-hover:text-white transition-colors">
|
|
{template.name}
|
|
</h3>
|
|
<span className="text-xs text-gray-500">{template.category}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Description */}
|
|
<p className="text-sm text-gray-400 line-clamp-2 mb-4 flex-1">
|
|
{template.description || 'No description provided.'}
|
|
</p>
|
|
|
|
{/* Star rating placeholder */}
|
|
<div className="flex items-center gap-0.5 mb-3">
|
|
{[1, 2, 3, 4, 5].map((i) => (
|
|
<Star
|
|
key={i}
|
|
className={`h-3.5 w-3.5 ${i <= 4 ? 'text-amber-400 fill-amber-400' : 'text-gray-700'}`}
|
|
/>
|
|
))}
|
|
<span className="text-xs text-gray-500 ml-1.5">4.0</span>
|
|
</div>
|
|
|
|
{/* Bottom stats row */}
|
|
<div className="flex items-center gap-3 pt-3 border-t border-gray-800/60">
|
|
<span className="flex items-center gap-1 text-xs text-gray-500">
|
|
<Wrench className="h-3.5 w-3.5" />
|
|
{template.toolCount} tools
|
|
</span>
|
|
<span className="flex items-center gap-1 text-xs text-gray-500">
|
|
<LayoutGrid className="h-3.5 w-3.5" />
|
|
{template.appCount} apps
|
|
</span>
|
|
<span className="flex items-center gap-1 text-xs text-gray-500 ml-auto">
|
|
<GitFork className="h-3.5 w-3.5" />
|
|
{template.forkCount}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|