init: kovakemlak-crm project scaffold
- Next.js 16 + Appwrite multi-tenant emlak CRM - Database: kovakemlak-db (properties, customers, customer_searches, property_matches, presentations, investors, activities, tenant_settings) - Same stack as isletmem-kovakcrm (shadcn/ui template base) - Modules: portföy, müşteri takibi, arama kriterleri, otomatik eşleştirme, sunum linki, yatırımcı portalı
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
"use server";
|
||||
|
||||
import { cookies } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import { AppwriteException, ID, Permission, Role } from "node-appwrite";
|
||||
|
||||
import { createAdminClient, createSessionClient } from "./server";
|
||||
import { DATABASE_ID, TABLES } from "./schema";
|
||||
import { ACTIVE_TENANT_COOKIE, type WorkspaceState } from "./tenant-types";
|
||||
|
||||
function appwriteError(e: unknown): string {
|
||||
if (e instanceof AppwriteException) {
|
||||
if (e.type === "team_already_exists") return "Bu isimde bir çalışma alanı zaten var.";
|
||||
if (e.type === "general_unauthorized_scope") return "Yetki hatası. Tekrar giriş yapın.";
|
||||
return e.message || "Beklenmeyen bir hata oluştu.";
|
||||
}
|
||||
return "Bağlantı hatası. Tekrar deneyin.";
|
||||
}
|
||||
|
||||
async function setActiveTenantCookie(tenantId: string) {
|
||||
(await cookies()).set(ACTIVE_TENANT_COOKIE, tenantId, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
sameSite: "strict",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
maxAge: 60 * 60 * 24 * 365,
|
||||
});
|
||||
}
|
||||
|
||||
export async function createWorkspaceAction(
|
||||
_prev: WorkspaceState,
|
||||
formData: FormData,
|
||||
): Promise<WorkspaceState> {
|
||||
const companyName = String(formData.get("companyName") ?? "").trim();
|
||||
const companyTaxId = String(formData.get("companyTaxId") ?? "").trim() || undefined;
|
||||
const companyPhone = String(formData.get("companyPhone") ?? "").trim() || undefined;
|
||||
|
||||
if (!companyName) {
|
||||
return { ok: false, error: "Şirket adı zorunlu." };
|
||||
}
|
||||
|
||||
let teamId: string | null = null;
|
||||
const admin = createAdminClient();
|
||||
|
||||
try {
|
||||
const session = await createSessionClient();
|
||||
const user = await session.account.get();
|
||||
|
||||
const team = await session.teams.create(ID.unique(), companyName, ["owner"]);
|
||||
teamId = team.$id;
|
||||
|
||||
await admin.tablesDB.createRow(
|
||||
DATABASE_ID,
|
||||
TABLES.tenantSettings,
|
||||
ID.unique(),
|
||||
{
|
||||
tenantId: teamId,
|
||||
companyName,
|
||||
companyTaxId,
|
||||
companyPhone,
|
||||
plan: "free",
|
||||
planStartedAt: new Date().toISOString(),
|
||||
},
|
||||
[
|
||||
Permission.read(Role.team(teamId)),
|
||||
Permission.update(Role.team(teamId, "owner")),
|
||||
Permission.update(Role.team(teamId, "admin")),
|
||||
Permission.delete(Role.team(teamId, "owner")),
|
||||
],
|
||||
);
|
||||
|
||||
await session.account.updatePrefs({
|
||||
...(user.prefs ?? {}),
|
||||
activeTenant: teamId,
|
||||
});
|
||||
|
||||
await setActiveTenantCookie(teamId);
|
||||
} catch (e) {
|
||||
if (teamId) {
|
||||
try {
|
||||
await admin.teams.delete(teamId);
|
||||
} catch {
|
||||
// best-effort cleanup; original error is what we surface
|
||||
}
|
||||
}
|
||||
return { ok: false, error: appwriteError(e) };
|
||||
}
|
||||
|
||||
redirect("/dashboard");
|
||||
}
|
||||
|
||||
export async function setActiveTenantAction(tenantId: string) {
|
||||
try {
|
||||
const { account } = await createSessionClient();
|
||||
const user = await account.get();
|
||||
|
||||
const teams = await (await createSessionClient()).teams.list();
|
||||
const owns = teams.teams.some((t) => t.$id === tenantId);
|
||||
if (!owns) {
|
||||
return { ok: false, error: "Bu çalışma alanına erişiminiz yok." };
|
||||
}
|
||||
|
||||
await account.updatePrefs({ ...(user.prefs ?? {}), activeTenant: tenantId });
|
||||
await setActiveTenantCookie(tenantId);
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
return { ok: false, error: appwriteError(e) };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user