39aa19d168
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
"use server";
|
|
|
|
import { revalidatePath } from "next/cache";
|
|
import { z } from "zod";
|
|
import { tr } from "@/i18n/tr";
|
|
import { fail, type ActionResult } from "@/lib/action-result";
|
|
import { getHouseholdActionContext } from "@/lib/dal";
|
|
import { budgetLimitsSchema, budgetMonthSchema, incomeItemsSchema } from "@/shared/schemas/budget";
|
|
import { saveIncomeItems } from "./plan";
|
|
import { budgetFromActuals, copyPreviousBudget, saveBudget } from "./service";
|
|
|
|
function fieldErrors(error: z.ZodError) {
|
|
const out: Record<string, string> = {};
|
|
for (const issue of error.issues) {
|
|
const key = issue.path.join(".");
|
|
if (key && !out[key]) out[key] = issue.message;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
async function run<T>(
|
|
schema: z.ZodType<T>,
|
|
input: unknown,
|
|
fn: (userId: string, householdId: string, data: T) => Promise<ActionResult<unknown>>,
|
|
): Promise<ActionResult<unknown>> {
|
|
const ctx = await getHouseholdActionContext("member");
|
|
if (!ctx) return fail(tr.common.unauthorized);
|
|
const parsed = schema.safeParse(input);
|
|
if (!parsed.success) return fail(tr.adminUsers.errors.checkFields, fieldErrors(parsed.error));
|
|
const result = await fn(ctx.user.id, ctx.household.id, parsed.data);
|
|
if (result.ok) revalidatePath("/", "layout");
|
|
return result;
|
|
}
|
|
|
|
export async function saveBudgetAction(input: unknown) {
|
|
return run(budgetLimitsSchema, input, saveBudget);
|
|
}
|
|
|
|
export async function copyPreviousBudgetAction(month: unknown) {
|
|
return run(budgetMonthSchema, month, copyPreviousBudget);
|
|
}
|
|
|
|
export async function budgetFromActualsAction(month: unknown) {
|
|
return run(budgetMonthSchema, month, budgetFromActuals);
|
|
}
|
|
|
|
export async function saveIncomeItemsAction(input: unknown) {
|
|
return run(incomeItemsSchema, input, saveIncomeItems);
|
|
}
|