=== 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
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
import { GitFork, Loader2 } from 'lucide-react';
|
|
|
|
interface ForkButtonProps {
|
|
templateId: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function ForkButton({ templateId, className = '' }: ForkButtonProps) {
|
|
const [loading, setLoading] = useState(false);
|
|
const router = useRouter();
|
|
|
|
const handleFork = async () => {
|
|
if (loading) return;
|
|
setLoading(true);
|
|
|
|
try {
|
|
const res = await fetch(`/api/marketplace/${templateId}/fork`, {
|
|
method: 'POST',
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const body = await res.json().catch(() => ({}));
|
|
throw new Error(body.error || `Fork failed (${res.status})`);
|
|
}
|
|
|
|
const { data } = await res.json();
|
|
router.push(`/projects/${data.id}`);
|
|
} catch (err) {
|
|
// Toast notification
|
|
const message = err instanceof Error ? err.message : 'Failed to fork template';
|
|
if (typeof window !== 'undefined') {
|
|
// Try using a global toast if available, fallback to alert
|
|
const toastEvent = new CustomEvent('toast', {
|
|
detail: { message, type: 'error' },
|
|
});
|
|
window.dispatchEvent(toastEvent);
|
|
// Fallback for now
|
|
console.error('[ForkButton]', message);
|
|
}
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<button
|
|
onClick={handleFork}
|
|
disabled={loading}
|
|
className={`
|
|
inline-flex items-center justify-center gap-2 px-6 py-2.5 rounded-lg
|
|
font-medium text-sm transition-all duration-200
|
|
bg-indigo-600 text-white
|
|
hover:bg-indigo-500 active:bg-indigo-700
|
|
disabled:opacity-60 disabled:cursor-not-allowed
|
|
shadow-lg shadow-indigo-600/20 hover:shadow-indigo-500/30
|
|
${className}
|
|
`}
|
|
>
|
|
{loading ? (
|
|
<>
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
Forking...
|
|
</>
|
|
) : (
|
|
<>
|
|
<GitFork className="h-4 w-4" />
|
|
Fork to My Projects
|
|
</>
|
|
)}
|
|
</button>
|
|
);
|
|
}
|