Files
neta/app/(dashboard)/tasks/actions.ts
T

101 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use server";
import { revalidatePath } from "next/cache";
import { getSqliteConnection } from "@/server/db/client";
import {
ContentTranslationService,
parseContentTranslationsFromFormData,
} from "@/server/i18n/content";
import { cleanText, optionalDate, requiredText } from "@/server/web/form-data";
import { requireFreelancerBackend } from "@/server/web/freelancer";
const TASK_STATUSES = ["todo", "in_progress", "done"] as const;
const TASK_PRIORITIES = ["low", "medium", "high", "urgent"] as const;
function enumValue<T extends readonly string[]>(value: FormDataEntryValue | string | null, values: T, fallback: T[number]): T[number] {
return typeof value === "string" && values.includes(value) ? value as T[number] : fallback;
}
function minutes(value: FormDataEntryValue | null): number | null {
const parsed = Number(value);
return Number.isFinite(parsed) && parsed >= 0 ? Math.round(parsed) : null;
}
function payload(formData: FormData, translations?: Record<string, Record<string, string | null>>, defaultLocale = "tr") {
const dueAt = optionalDate(formData.get("due_at"));
const localized = translations?.[defaultLocale] ?? {};
return {
title: localized.title ?? requiredText(formData.get("title"), "Görev başlığı zorunludur."),
description: localized.description ?? cleanText(formData.get("description")),
status: enumValue(formData.get("status"), TASK_STATUSES, "todo"),
priority: enumValue(formData.get("priority"), TASK_PRIORITIES, "medium"),
clientId: cleanText(formData.get("client_id")),
projectId: cleanText(formData.get("project_id")),
scheduledDate: dueAt?.toISOString().slice(0, 10) ?? null,
dueAt,
estimatedMinutes: minutes(formData.get("estimated_minutes")),
actualMinutes: minutes(formData.get("actual_minutes")),
isPublicToClient: formData.get("is_public_to_client") === "on",
};
}
function completeRelations(
value: ReturnType<typeof payload>,
service: Awaited<ReturnType<typeof requireFreelancerBackend>>["service"],
actor: Awaited<ReturnType<typeof requireFreelancerBackend>>["actor"],
) {
const project = value.projectId ? service.getProject(actor, value.projectId) : null;
return { ...value, clientId: value.clientId ?? project?.clientId ?? null };
}
function revalidate(projectId?: string | null) {
revalidatePath("/tasks");
revalidatePath("/projects");
if (projectId) revalidatePath(`/projects/${projectId}`);
}
export async function createTaskRecord(formData: FormData) {
const { actor, service } = await requireFreelancerBackend();
const i18n = new ContentTranslationService(getSqliteConnection().db);
const context = i18n.getLocalizationContext(actor);
const translations = parseContentTranslationsFromFormData(formData, "task", context);
const value = completeRelations(payload(formData, translations, context.defaultLocale), service, actor);
service.createTask(actor, { ...value, translations });
revalidate(value.projectId);
}
export async function updateTaskRecord(formData: FormData) {
const { actor, service } = await requireFreelancerBackend();
const i18n = new ContentTranslationService(getSqliteConnection().db);
const context = i18n.getLocalizationContext(actor);
const translations = parseContentTranslationsFromFormData(formData, "task", context);
const id = requiredText(formData.get("id"), "Görev kaydı bulunamadı.");
const value = completeRelations(payload(formData, translations, context.defaultLocale), service, actor);
const current = service.listTasks(actor).find((task) => task.id === id);
service.updateTask(actor, id, { ...value, translations });
revalidate(value.projectId);
if (current?.projectId !== value.projectId) revalidate(current?.projectId);
}
export async function completeTaskRecord(formData: FormData) {
const id = requiredText(formData.get("id"), "Tamamlanacak görev bulunamadı.");
const projectId = cleanText(formData.get("project_id"));
const { actor, service } = await requireFreelancerBackend();
service.updateTask(actor, id, { status: "done" });
revalidate(projectId);
}
export async function updateTaskStatusRecord(taskId: string, status: string, projectId?: string) {
const { actor, service } = await requireFreelancerBackend();
service.updateTask(actor, taskId, { status: enumValue(status, TASK_STATUSES, "todo") });
revalidate(projectId);
}
export async function deleteTaskRecord(formData: FormData) {
const id = requiredText(formData.get("id"), "Silinecek görev bulunamadı.");
const projectId = cleanText(formData.get("project_id"));
const { actor, service } = await requireFreelancerBackend();
service.deleteTask(actor, id);
revalidate(projectId);
}