"use server"; import { revalidatePath } from "next/cache"; import { z } from "zod"; import { tr } from "@/i18n/tr"; import { fail, ok, type ActionResult } from "@/lib/action-result"; import { getHouseholdActionContext } from "@/lib/dal"; import { confirmOccurrenceSchema, recurringRuleFormSchema } from "@/shared/schemas/recurring"; import { confirmOccurrence, createRule, deleteRule, getRuleForm, postponeOccurrence, skipOccurrence, updateRule, type RuleFormValues, } from "./service"; const idSchema = z.string().regex(/^[a-f0-9]{24}$/i); const optionalId = idSchema.optional(); const scopeSchema = z.enum(["all", "following"]); const ymd = z.string().regex(/^\d{4}-\d{2}-\d{2}$/); function fieldErrors(error: z.ZodError) { const out: Record = {}; for (const issue of error.issues) { const key = issue.path.join("."); if (key && !out[key]) out[key] = issue.message; } return out; } function revalidate() { revalidatePath("/", "layout"); } export async function createRuleAction(input: unknown): Promise> { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const parsed = recurringRuleFormSchema.safeParse(input); if (!parsed.success) return fail(tr.adminUsers.errors.checkFields, fieldErrors(parsed.error)); const result = await createRule(ctx.user.id, ctx.household.id, parsed.data); if (result.ok) revalidate(); return result.ok ? ok({ id: result.data.id }) : result; } export async function updateRuleAction( ruleId: unknown, input: unknown, scope: unknown, fromTransactionId?: unknown, ): Promise> { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const id = idSchema.safeParse(ruleId); const s = scopeSchema.safeParse(scope); const from = optionalId.safeParse(fromTransactionId ?? undefined); if (!id.success || !s.success || !from.success) return fail(tr.common.notFound); const parsed = recurringRuleFormSchema.safeParse(input); if (!parsed.success) return fail(tr.adminUsers.errors.checkFields, fieldErrors(parsed.error)); const result = await updateRule( ctx.user.id, ctx.household.id, id.data, parsed.data, s.data, from.data, ); if (result.ok) revalidate(); return result; } export async function deleteRuleAction( ruleId: unknown, scope: unknown, fromTransactionId?: unknown, ): Promise> { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const id = idSchema.safeParse(ruleId); const s = scopeSchema.safeParse(scope); const from = optionalId.safeParse(fromTransactionId ?? undefined); if (!id.success || !s.success || !from.success) return fail(tr.common.notFound); const result = await deleteRule(ctx.user.id, ctx.household.id, id.data, s.data, from.data); if (result.ok) revalidate(); return result; } export async function getRuleFormAction(ruleId: unknown): Promise> { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const id = idSchema.safeParse(ruleId); if (!id.success) return fail(tr.common.notFound); const values = await getRuleForm(ctx.user.id, ctx.household.id, id.data); return values ? ok(values) : fail(tr.common.notFound); } export async function confirmOccurrenceAction( transactionId: unknown, input: unknown, ): Promise { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const id = idSchema.safeParse(transactionId); if (!id.success) return fail(tr.common.notFound); const parsed = confirmOccurrenceSchema.safeParse(input); if (!parsed.success) return fail(tr.adminUsers.errors.checkFields, fieldErrors(parsed.error)); const result = await confirmOccurrence(ctx.user.id, ctx.household.id, id.data, parsed.data); if (result.ok) revalidate(); return result; } export async function skipOccurrenceAction(transactionId: unknown): Promise { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const id = idSchema.safeParse(transactionId); if (!id.success) return fail(tr.common.notFound); const result = await skipOccurrence(ctx.user.id, ctx.household.id, id.data); if (result.ok) revalidate(); return result; } export async function postponeOccurrenceAction( transactionId: unknown, date: unknown, ): Promise { const ctx = await getHouseholdActionContext("member"); if (!ctx) return fail(tr.common.unauthorized); const id = idSchema.safeParse(transactionId); const d = ymd.safeParse(date); if (!id.success) return fail(tr.common.notFound); if (!d.success) return fail(tr.validation.date, { date: tr.validation.date }); const result = await postponeOccurrence(ctx.user.id, ctx.household.id, id.data, d.data); if (result.ok) revalidate(); return result; }