feat(backend): migrate freelancer and portal runtimes

This commit is contained in:
poyrazavsever
2026-07-17 00:16:38 +03:00
parent 561af11b70
commit 678c0236db
41 changed files with 5293 additions and 2324 deletions
+43 -82
View File
@@ -1,106 +1,67 @@
"use server";
import { createClient } from "@/lib/supabase/server";
import { revalidatePath } from "next/cache";
import { cleanText, optionalDate, requiredText } from "@/server/web/form-data";
import { requireFreelancerBackend } from "@/server/web/freelancer";
const EVENT_TYPES = ["meeting", "focus", "deadline", "personal", "finance"] as const;
function cleanText(value: FormDataEntryValue | null) {
const text = typeof value === "string" ? value.trim() : "";
return text.length > 0 && text !== "__none" ? text : null;
function eventType(value: FormDataEntryValue | null) {
return typeof value === "string" && EVENT_TYPES.includes(value as (typeof EVENT_TYPES)[number])
? value as (typeof EVENT_TYPES)[number]
: "focus";
}
function readType(value: FormDataEntryValue | null) {
const type = typeof value === "string" ? value : "focus";
return EVENT_TYPES.includes(type as (typeof EVENT_TYPES)[number]) ? type : "focus";
}
async function getCurrentUserId() {
const supabase = await createClient();
const {
data: { user },
error,
} = await supabase.auth.getUser();
if (error || !user) {
throw new Error("Takvim işlemi için giriş yapmış kullanıcı bulunamadı.");
}
return { supabase, userId: user.id };
}
function readPayload(formData: FormData) {
function payload(formData: FormData) {
return {
title: cleanText(formData.get("title")),
title: requiredText(formData.get("title"), "Etkinlik başlığı zorunludur."),
description: cleanText(formData.get("description")),
type: readType(formData.get("type")),
starts_at: cleanText(formData.get("starts_at")),
ends_at: cleanText(formData.get("ends_at")),
client_id: cleanText(formData.get("client_id")),
project_id: cleanText(formData.get("project_id")),
task_id: cleanText(formData.get("task_id")),
type: eventType(formData.get("type")),
startsAt: optionalDate(formData.get("starts_at")),
endsAt: optionalDate(formData.get("ends_at")),
clientId: cleanText(formData.get("client_id")),
projectId: cleanText(formData.get("project_id")),
taskId: cleanText(formData.get("task_id")),
};
}
function completeRelations(
value: ReturnType<typeof payload>,
service: Awaited<ReturnType<typeof requireFreelancerBackend>>["service"],
actor: Awaited<ReturnType<typeof requireFreelancerBackend>>["actor"],
) {
const task = value.taskId ? service.listTasks(actor).find((item) => item.id === value.taskId) : null;
const projectId = value.projectId ?? task?.projectId ?? null;
const project = projectId ? service.getProject(actor, projectId) : null;
return {
...value,
projectId,
clientId: value.clientId ?? task?.clientId ?? project?.clientId ?? null,
};
}
export async function createCalendarEventRecord(formData: FormData) {
const { supabase, userId } = await getCurrentUserId();
const payload = readPayload(formData);
if (!payload.title || !payload.starts_at) {
throw new Error("Etkinlik başlığı ve başlangıç zamanı zorunludur.");
}
const { error } = await supabase.from("calendar_events").insert({
user_id: userId,
...payload,
});
if (error) {
throw new Error(`Etkinlik eklenemedi: ${error.message}`);
}
const backend = await requireFreelancerBackend();
const value = completeRelations(payload(formData), backend.service, backend.actor);
if (!value.startsAt) throw new Error("Etkinlik başlangıç zamanı zorunludur.");
backend.service.createCalendarEvent(backend.actor, value);
revalidatePath("/calendar");
}
export async function updateCalendarEventRecord(formData: FormData) {
const { supabase, userId } = await getCurrentUserId();
const id = cleanText(formData.get("id"));
const payload = readPayload(formData);
if (!id || !payload.title || !payload.starts_at) {
throw new Error("Etkinlik güncellemek için başlık, başlangıç ve kayıt kimliği zorunludur.");
}
const { error } = await supabase
.from("calendar_events")
.update(payload)
.eq("id", id)
.eq("user_id", userId);
if (error) {
throw new Error(`Etkinlik güncellenemedi: ${error.message}`);
}
const backend = await requireFreelancerBackend();
const id = requiredText(formData.get("id"), "Etkinlik kaydı bulunamadı.");
const value = completeRelations(payload(formData), backend.service, backend.actor);
if (!value.startsAt) throw new Error("Etkinlik başlangıç zamanı zorunludur.");
backend.service.updateCalendarEvent(backend.actor, id, value);
revalidatePath("/calendar");
}
export async function deleteCalendarEventRecord(formData: FormData) {
const { supabase, userId } = await getCurrentUserId();
const id = cleanText(formData.get("id"));
if (!id) {
throw new Error("Silinecek etkinlik bulunamadı.");
}
const { error } = await supabase
.from("calendar_events")
.delete()
.eq("id", id)
.eq("user_id", userId);
if (error) {
throw new Error(`Etkinlik silinemedi: ${error.message}`);
}
const { actor, service } = await requireFreelancerBackend();
service.deleteCalendarEvent(
actor,
requiredText(formData.get("id"), "Silinecek etkinlik bulunamadı."),
);
revalidatePath("/calendar");
}