146 lines
4.3 KiB
TypeScript
146 lines
4.3 KiB
TypeScript
"use server";
|
||
|
||
import { revalidatePath } from "next/cache";
|
||
import { ID, Permission, Role } from "node-appwrite";
|
||
|
||
import { DATABASE_ID, TABLES, type Lead, type LeadActivityType } from "./schema";
|
||
import { createAdminClient } from "./server";
|
||
import { requireTenant } from "./tenant-guard";
|
||
|
||
export type ActivityActionState = { ok: boolean; error?: string };
|
||
|
||
export async function addLeadActivityAction(
|
||
_prev: ActivityActionState,
|
||
formData: FormData,
|
||
): Promise<ActivityActionState> {
|
||
const leadId = String(formData.get("leadId") ?? "");
|
||
const type = String(formData.get("type") ?? "note") as LeadActivityType;
|
||
const content = String(formData.get("content") ?? "").trim();
|
||
const occurredAt = String(formData.get("occurredAt") ?? "") || new Date().toISOString();
|
||
|
||
if (!leadId || !content) return { ok: false, error: "Zorunlu alanlar eksik." };
|
||
|
||
let ctx;
|
||
try {
|
||
ctx = await requireTenant();
|
||
} catch {
|
||
return { ok: false, error: "Yetkiniz yok." };
|
||
}
|
||
|
||
try {
|
||
const { tablesDB } = createAdminClient();
|
||
const lead = (await tablesDB.getRow(DATABASE_ID, TABLES.leads, leadId)) as unknown as Lead;
|
||
if (lead.tenantId !== ctx.tenantId) return { ok: false, error: "Erişim engellendi." };
|
||
|
||
await tablesDB.createRow(
|
||
DATABASE_ID,
|
||
TABLES.leadActivities,
|
||
ID.unique(),
|
||
{
|
||
tenantId: ctx.tenantId,
|
||
createdBy: ctx.user.id,
|
||
leadId,
|
||
type,
|
||
content,
|
||
occurredAt,
|
||
},
|
||
[
|
||
Permission.read(Role.team(ctx.tenantId)),
|
||
Permission.update(Role.team(ctx.tenantId)),
|
||
Permission.delete(Role.team(ctx.tenantId, "owner")),
|
||
],
|
||
);
|
||
|
||
// Update lastContactAt on the lead
|
||
await tablesDB.updateRow(DATABASE_ID, TABLES.leads, leadId, {
|
||
lastContactAt: new Date().toISOString(),
|
||
});
|
||
|
||
revalidatePath("/leads");
|
||
return { ok: true };
|
||
} catch (e) {
|
||
return { ok: false, error: e instanceof Error ? e.message : "Hata oluştu." };
|
||
}
|
||
}
|
||
|
||
export async function scheduleFollowUpAction(
|
||
_prev: ActivityActionState,
|
||
formData: FormData,
|
||
): Promise<ActivityActionState> {
|
||
const leadId = String(formData.get("leadId") ?? "");
|
||
const followUpAt = String(formData.get("followUpAt") ?? "");
|
||
const note = String(formData.get("note") ?? "").trim();
|
||
|
||
if (!leadId || !followUpAt) return { ok: false, error: "Tarih seçin." };
|
||
|
||
let ctx;
|
||
try {
|
||
ctx = await requireTenant();
|
||
} catch {
|
||
return { ok: false, error: "Yetkiniz yok." };
|
||
}
|
||
|
||
try {
|
||
const { tablesDB } = createAdminClient();
|
||
const lead = (await tablesDB.getRow(DATABASE_ID, TABLES.leads, leadId)) as unknown as Lead;
|
||
if (lead.tenantId !== ctx.tenantId) return { ok: false, error: "Erişim engellendi." };
|
||
|
||
const followUpDate = new Date(followUpAt);
|
||
const endDate = new Date(followUpDate.getTime() + 60 * 60 * 1000); // +1h
|
||
|
||
const permissions = [
|
||
Permission.read(Role.team(ctx.tenantId)),
|
||
Permission.update(Role.team(ctx.tenantId)),
|
||
Permission.delete(Role.team(ctx.tenantId, "owner")),
|
||
];
|
||
|
||
// Create calendar event
|
||
const event = await tablesDB.createRow(
|
||
DATABASE_ID,
|
||
TABLES.calendarEvents,
|
||
ID.unique(),
|
||
{
|
||
tenantId: ctx.tenantId,
|
||
createdBy: ctx.user.id,
|
||
title: `Takip: ${lead.contactName || lead.name}`,
|
||
description: note || `Lead takip görüşmesi — ${lead.name}`,
|
||
start: followUpDate.toISOString(),
|
||
end: endDate.toISOString(),
|
||
allDay: false,
|
||
leadId,
|
||
color: "#f97316", // orange — lead events
|
||
},
|
||
permissions,
|
||
);
|
||
|
||
// Update lead nextFollowUpAt + calendarEventId
|
||
await tablesDB.updateRow(DATABASE_ID, TABLES.leads, leadId, {
|
||
nextFollowUpAt: followUpDate.toISOString(),
|
||
calendarEventId: event.$id,
|
||
});
|
||
|
||
// Log activity
|
||
await tablesDB.createRow(
|
||
DATABASE_ID,
|
||
TABLES.leadActivities,
|
||
ID.unique(),
|
||
{
|
||
tenantId: ctx.tenantId,
|
||
createdBy: ctx.user.id,
|
||
leadId,
|
||
type: "meeting",
|
||
content: `Takip planlandı: ${followUpDate.toLocaleString("tr-TR")}${note ? ` — ${note}` : ""}`,
|
||
calendarEventId: event.$id,
|
||
occurredAt: new Date().toISOString(),
|
||
},
|
||
permissions,
|
||
);
|
||
|
||
revalidatePath("/leads");
|
||
revalidatePath("/calendar");
|
||
return { ok: true };
|
||
} catch (e) {
|
||
return { ok: false, error: e instanceof Error ? e.message : "Hata oluştu." };
|
||
}
|
||
}
|