mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-05 13:29:44 +02:00
refactor(views): extract shared NewWorkspacePage shell
The web (/new-workspace) and desktop (NewWorkspaceRoute) pages had identical outer layout — same container, heading, and copy — with only the onSuccess navigation primitive differing. That's exactly the No-Duplication Rule pattern: extract the shared UI, inject the platform-specific behavior. The apps now only own the thin auth guard (web needs it, desktop routes below WorkspaceRouteLayout already handle it) and the onSuccess → navigate call. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ import { DaemonRuntimeCard } from "./components/daemon-runtime-card";
|
||||
import { AgentsPage } from "@multica/views/agents";
|
||||
import { InboxPage } from "@multica/views/inbox";
|
||||
import { SettingsPage } from "@multica/views/settings";
|
||||
import { CreateWorkspaceForm } from "@multica/views/workspace/create-workspace-form";
|
||||
import { NewWorkspacePage } from "@multica/views/workspace/new-workspace-page";
|
||||
import { InvitePage } from "@multica/views/invite";
|
||||
import { useNavigation } from "@multica/views/navigation";
|
||||
import { paths } from "@multica/core/paths";
|
||||
@@ -62,21 +62,9 @@ function PageShell() {
|
||||
function NewWorkspaceRoute() {
|
||||
const nav = useNavigation();
|
||||
return (
|
||||
<div className="flex min-h-svh flex-col items-center justify-center bg-background px-6 py-12">
|
||||
<div className="flex w-full max-w-md flex-col items-center gap-6">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl font-semibold tracking-tight">
|
||||
Welcome to Multica
|
||||
</h1>
|
||||
<p className="mt-2 text-muted-foreground">
|
||||
Create your workspace to get started.
|
||||
</p>
|
||||
</div>
|
||||
<CreateWorkspaceForm
|
||||
onSuccess={(ws) => nav.push(paths.workspace(ws.slug).issues())}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<NewWorkspacePage
|
||||
onSuccess={(ws) => nav.push(paths.workspace(ws.slug).issues())}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import { useRouter } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
import { useAuthStore } from "@multica/core/auth";
|
||||
import { paths } from "@multica/core/paths";
|
||||
import { CreateWorkspaceForm } from "@multica/views/workspace/create-workspace-form";
|
||||
import { NewWorkspacePage } from "@multica/views/workspace/new-workspace-page";
|
||||
|
||||
export default function NewWorkspacePage() {
|
||||
export default function Page() {
|
||||
const router = useRouter();
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const isLoading = useAuthStore((s) => s.isLoading);
|
||||
@@ -18,20 +18,8 @@ export default function NewWorkspacePage() {
|
||||
if (isLoading || !user) return null;
|
||||
|
||||
return (
|
||||
<div className="flex min-h-svh flex-col items-center justify-center bg-background px-6 py-12">
|
||||
<div className="flex w-full max-w-md flex-col items-center gap-6">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl font-semibold tracking-tight">
|
||||
Welcome to Multica
|
||||
</h1>
|
||||
<p className="mt-2 text-muted-foreground">
|
||||
Create your workspace to get started.
|
||||
</p>
|
||||
</div>
|
||||
<CreateWorkspaceForm
|
||||
onSuccess={(ws) => router.push(paths.workspace(ws.slug).issues())}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<NewWorkspacePage
|
||||
onSuccess={(ws) => router.push(paths.workspace(ws.slug).issues())}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"./workspace/workspace-avatar": "./workspace/workspace-avatar.tsx",
|
||||
"./workspace/create-workspace-form": "./workspace/create-workspace-form.tsx",
|
||||
"./workspace/no-access-page": "./workspace/no-access-page.tsx",
|
||||
"./workspace/new-workspace-page": "./workspace/new-workspace-page.tsx",
|
||||
"./workspace/use-workspace-seen": "./workspace/use-workspace-seen.ts",
|
||||
"./layout": "./layout/index.ts",
|
||||
"./auth": "./auth/index.ts",
|
||||
|
||||
32
packages/views/workspace/new-workspace-page.tsx
Normal file
32
packages/views/workspace/new-workspace-page.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import type { Workspace } from "@multica/core/types";
|
||||
import { CreateWorkspaceForm } from "./create-workspace-form";
|
||||
|
||||
/**
|
||||
* Full-page shell for the /new-workspace route. Shared between web
|
||||
* (Next.js) and desktop (react-router) so the two apps can't drift.
|
||||
* Callers provide the onSuccess handler — that's the only app-specific
|
||||
* piece, because each app uses its own navigation primitive.
|
||||
*/
|
||||
export function NewWorkspacePage({
|
||||
onSuccess,
|
||||
}: {
|
||||
onSuccess: (workspace: Workspace) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex min-h-svh flex-col items-center justify-center bg-background px-6 py-12">
|
||||
<div className="flex w-full max-w-md flex-col items-center gap-6">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl font-semibold tracking-tight">
|
||||
Welcome to Multica
|
||||
</h1>
|
||||
<p className="mt-2 text-muted-foreground">
|
||||
Create your workspace to get started.
|
||||
</p>
|
||||
</div>
|
||||
<CreateWorkspaceForm onSuccess={onSuccess} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user