Files
vercel_dashboard_example/app/lib/actions.ts
T
claude 93f7061c53 fix: resolve build failures
- Fix TypeScript type error in deleteInvoice server action (returned
  {message: string} instead of void, incompatible with form action type)
- Add export const dynamic = "force-dynamic" to dashboard pages that
  make DB calls at build time (/dashboard, /dashboard/invoices,
  /dashboard/invoices/create) to prevent failed static prerendering
- Fix import order in customers/page.tsx (export before import was invalid)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-12 14:52:47 +00:00

137 lines
3.5 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { AuthError } from "next-auth";
import postgres from "postgres";
import { z } from "zod";
import { signIn } from "@/auth";
const sql = postgres(process.env.POSTGRES_URL!, { ssl: "require" });
const FormSchema = z.object({
id: z.string(),
customerId: z.string({
invalid_type_error: "Please select a customer",
}),
amount: z.coerce
.number()
.gt(0, { message: "Please enter an amount greater than $0." }),
status: z.enum(["pending", "paid"], {
invalid_type_error: "Please select an invoice status. ",
}),
date: z.string(),
});
const CreateInvoice = FormSchema.omit({ id: true, date: true });
const UpdateInvoice = FormSchema.omit({ id: true, date: true });
export type State = {
errors?: {
customerId?: string[];
amount?: string[];
status?: string[];
};
message?: string | null;
};
export async function createInvoice(_prevState: State, formData: FormData) {
const validateFields = CreateInvoice.safeParse({
customerId: formData.get("customerId"),
amount: formData.get("amount"),
status: formData.get("status"),
});
if (!validateFields.success) {
return {
errors: validateFields.error.flatten().fieldErrors,
message: "Missing Fields. Failed to Create Invoice. ",
};
}
const { customerId, amount, status } = validateFields.data;
const amountInCents = amount * 100;
const date = new Date().toISOString().split("T")[0];
try {
await sql`
INSERT INTO invoices (customer_id, amount, status, date)
VALUES (${customerId}, ${amountInCents}, ${status}, ${date})
`;
} catch (_error) {
return {
message: "Database Error: Failed to Create Invoice.",
};
}
revalidatePath("/dashboard/invoices");
redirect("/dashboard/invoices");
}
export async function updateInvoice(
id: string,
_prevState: State,
formData: FormData,
) {
const validateFields = UpdateInvoice.safeParse({
customerId: formData.get("customerId"),
amount: formData.get("amount"),
status: formData.get("status"),
});
if (!validateFields.success) {
return {
errors: validateFields.error.flatten().fieldErrors,
message: "Missing Fields. Failed to update Invoice",
};
}
const { amount, customerId, status } = validateFields.data;
const amountInCents = amount * 100;
try {
await sql`
UPDATE invoices
SET customer_id = ${customerId}, amount = ${amountInCents}, status = ${status}
WHERE id = ${id}
`;
} catch (_error) {
return {
message: "Database Failed: Error while updating the Invoice",
};
}
revalidatePath("/dashboard/invoices");
redirect("/dashboard/invoices");
}
export async function deleteInvoice(id: string): Promise<void> {
// throw new Error('Failed to Delete Invoice. ')
try {
await sql`
DELETE FROM invoices
WHERE id = ${id}
`;
revalidatePath("/dashboard/invoices");
} catch (_error) {
console.error("Database Error: Failed while deleting record from Invoice.");
}
}
export async function authenticate(
_prevState: string | undefined,
formData: FormData,
) {
try {
await signIn("credentials", formData);
} catch (error) {
if (error instanceof AuthError) {
switch (error.type) {
case "CredentialsSignin":
return "Invalid credentials";
default:
return "Something went wrong.";
}
}
throw error;
}
}