feat: Wiederkehrende Aufgaben-Vorlagen (recurring task templates)
Neue TaskTemplate-Entität mit YEARLY/MONTHLY/INTERVAL_DAYS-Wiederholung. Fällige Aufgaben werden lazy bei GET /tasks erzeugt (Compare-and-Swap auf nextDueDate), damit mehrere API-Replicas im Kubernetes-Cluster dieselbe Vorlage nicht doppelt feuern - ohne zusätzliche Cron-Abhängigkeit. Frontend: Verwaltungsseite unter /settings/task-templates zum Anlegen, Auflisten und Deaktivieren von Vorlagen.
This commit is contained in:
1 parent
e458a7cf07
commit
4609a0f9ec
20 files changed
+1341
No files matched your search
@@ -0,0 +1,24 @@
|
||||
import { apiFetch } from "@/lib/auth/api-client";
|
||||
import { CreateTaskTemplateInput, TaskTemplate, UpdateTaskTemplateInput } from "./types";
|
||||
|
||||
export function fetchTaskTemplates(): Promise<TaskTemplate[]> {
|
||||
return apiFetch<TaskTemplate[]>("/task-templates");
|
||||
}
|
||||
|
||||
export function createTaskTemplate(input: CreateTaskTemplateInput): Promise<TaskTemplate> {
|
||||
return apiFetch<TaskTemplate>("/task-templates", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function updateTaskTemplate(id: string, input: UpdateTaskTemplateInput): Promise<TaskTemplate> {
|
||||
return apiFetch<TaskTemplate>(`/task-templates/${id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function deactivateTaskTemplate(id: string): Promise<TaskTemplate> {
|
||||
return apiFetch<TaskTemplate>(`/task-templates/${id}/deactivate`, { method: "POST" });
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { TaskPriority } from "@/lib/tasks/types";
|
||||
|
||||
export type TaskTemplateRecurrenceType = "YEARLY" | "MONTHLY" | "INTERVAL_DAYS";
|
||||
|
||||
export interface TaskTemplate {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
priority: TaskPriority;
|
||||
assignedUserId: string | null;
|
||||
createdByUserId: string | null;
|
||||
recurrenceType: TaskTemplateRecurrenceType;
|
||||
recurrenceMonth: number | null;
|
||||
recurrenceDayOfMonth: number | null;
|
||||
intervalDays: number | null;
|
||||
nextDueDate: string;
|
||||
active: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CreateTaskTemplateInput {
|
||||
title: string;
|
||||
description?: string;
|
||||
priority?: TaskPriority;
|
||||
assignedUserId?: string;
|
||||
recurrenceType: TaskTemplateRecurrenceType;
|
||||
recurrenceMonth?: number;
|
||||
recurrenceDayOfMonth?: number;
|
||||
intervalDays?: number;
|
||||
}
|
||||
|
||||
export interface UpdateTaskTemplateInput {
|
||||
title?: string;
|
||||
description?: string;
|
||||
priority?: TaskPriority;
|
||||
assignedUserId?: string;
|
||||
recurrenceType?: TaskTemplateRecurrenceType;
|
||||
recurrenceMonth?: number;
|
||||
recurrenceDayOfMonth?: number;
|
||||
intervalDays?: number;
|
||||
active?: boolean;
|
||||
}
|
||||
Reference in new issue
Block a user