diff --git a/src/app/onboarding/components/create-workspace-form.tsx b/src/app/onboarding/components/create-workspace-form.tsx index dafb9e2..ecc5df6 100644 --- a/src/app/onboarding/components/create-workspace-form.tsx +++ b/src/app/onboarding/components/create-workspace-form.tsx @@ -1,21 +1,30 @@ "use client"; import { useActionState } from "react"; -import { Building2, Loader2, ShieldCheck } from "lucide-react"; +import { Building2, Loader2, ShieldCheck, ArrowRight } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Logo } from "@/components/logo"; -import { createWorkspaceAction } from "@/lib/appwrite/tenant-actions"; +import { createWorkspaceAction, importWorkspaceAction } from "@/lib/appwrite/tenant-actions"; import { initialWorkspaceState } from "@/lib/appwrite/tenant-types"; -export function CreateWorkspaceForm({ userName }: { userName?: string }) { +interface Props { + userName?: string; + crossAppTeams?: Array<{ $id: string; name: string }>; +} + +export function CreateWorkspaceForm({ userName, crossAppTeams = [] }: Props) { const [state, formAction, isPending] = useActionState( createWorkspaceAction, initialWorkspaceState, ); + const [, importFormAction, isImporting] = useActionState( + importWorkspaceAction, + initialWorkspaceState, + ); return (
@@ -26,6 +35,51 @@ export function CreateWorkspaceForm({ userName }: { userName?: string }) { İşletmem
+ {/* Cross-app import section */} + {crossAppTeams.length > 0 && ( + + + Mevcut şirketinizi ekleyin + + Diğer bir KovakSoft uygulamasında kayıtlı şirketinizi tek tıkla buraya ekleyebilirsiniz. + + + + {crossAppTeams.map((team) => ( +
+ + +
+ ))} +
+
+ )} + + {crossAppTeams.length > 0 && ( +
+
+ +
+
+ veya yeni oluştur +
+
+ )} +
diff --git a/src/app/onboarding/page.tsx b/src/app/onboarding/page.tsx index 5cbcead..486657c 100644 --- a/src/app/onboarding/page.tsx +++ b/src/app/onboarding/page.tsx @@ -2,7 +2,7 @@ import type { Metadata } from "next"; import { redirect } from "next/navigation"; import { getCurrentUser } from "@/lib/appwrite/server"; -import { getUserTeams } from "@/lib/appwrite/tenant"; +import { getUserTeams, getCrossAppTeams } from "@/lib/appwrite/tenant"; import { CreateWorkspaceForm } from "./components/create-workspace-form"; export const metadata: Metadata = { @@ -15,14 +15,17 @@ export default async function OnboardingPage() { if (!user) redirect("/sign-in"); const teams = await getUserTeams(); - if (teams && teams.total > 0) { - redirect("/dashboard"); - } + if (teams && teams.total > 0) redirect("/dashboard"); + + const crossAppTeams = await getCrossAppTeams(); return (
- +
); diff --git a/src/lib/appwrite/tenant-actions.ts b/src/lib/appwrite/tenant-actions.ts index 7e29d35..f55757e 100644 --- a/src/lib/appwrite/tenant-actions.ts +++ b/src/lib/appwrite/tenant-actions.ts @@ -89,6 +89,59 @@ export async function createWorkspaceAction( redirect("/dashboard"); } +export async function importWorkspaceAction( + _prev: WorkspaceState, + formData: FormData, +): Promise { + const teamId = String(formData.get("teamId") ?? "").trim(); + if (!teamId) return { ok: false, error: "Geçersiz istek." }; + + try { + const { account, teams, tablesDB } = await createSessionClient(); + const user = await account.get(); + + const allTeams = await teams.list(); + const team = allTeams.teams.find((t) => t.$id === teamId); + if (!team) return { ok: false, error: "Çalışma alanı bulunamadı." }; + + const existing = await tablesDB.listRows({ + databaseId: DATABASE_ID, + tableId: TABLES.tenantSettings, + queries: [Query.equal("tenantId", teamId), Query.limit(1)], + }); + if (existing.total > 0) return { ok: false, error: "Bu çalışma alanı zaten mevcut." }; + + const admin = createAdminClient(); + await admin.tablesDB.createRow( + DATABASE_ID, + TABLES.tenantSettings, + ID.unique(), + { + tenantId: teamId, + companyName: team.name, + plan: "free", + planStartedAt: new Date().toISOString(), + defaultVatRate: 20, + invoicePrefix: "INV", + invoiceCounter: 0, + }, + [ + Permission.read(Role.team(teamId)), + Permission.update(Role.team(teamId, "owner")), + Permission.update(Role.team(teamId, "admin")), + Permission.delete(Role.team(teamId, "owner")), + ], + ); + + await account.updatePrefs({ ...(user.prefs ?? {}), activeTenant: teamId }); + await setActiveTenantCookie(teamId); + } catch (e) { + return { ok: false, error: appwriteError(e) }; + } + + redirect("/dashboard"); +} + export async function setActiveTenantAction(tenantId: string) { try { const { account, teams, tablesDB } = await createSessionClient(); diff --git a/src/lib/appwrite/tenant.ts b/src/lib/appwrite/tenant.ts index adb7227..b84345b 100644 --- a/src/lib/appwrite/tenant.ts +++ b/src/lib/appwrite/tenant.ts @@ -30,6 +30,29 @@ export async function getUserTeams() { } } +export async function getCrossAppTeams(): Promise> { + try { + const { teams, tablesDB } = await createSessionClient(); + const allTeams = await teams.list(); + + if (allTeams.teams.length === 0) return []; + + const teamIds = allTeams.teams.map((t) => t.$id); + const settings = await tablesDB.listRows({ + databaseId: DATABASE_ID, + tableId: TABLES.tenantSettings, + queries: [Query.equal("tenantId", teamIds), Query.limit(100)], + }); + const thisAppIds = new Set(settings.rows.map((r) => r.tenantId as string)); + + return allTeams.teams + .filter((t) => !thisAppIds.has(t.$id)) + .map((t) => ({ $id: t.$id, name: t.name })); + } catch { + return []; + } +} + export async function getActiveTenantId(): Promise { const cookie = (await cookies()).get(ACTIVE_TENANT_COOKIE)?.value; if (cookie) return cookie;