RJBULK-APP/actions/suppliers.ts
SJCoetz 1efa979443 feat: initial setup of rj bulk supplies backoffice app
Adds complete initial codebase for the RJ Bulk Supplies fuel delivery backoffice:
- Authentication pages and protected route layouts
- Customer, supplier, fuel purchase, and delivery note management
- Custom reporting and customer statement sending tools
- Full UI component library and Tailwind styling
- Server actions, API routes, and PocketBase integration
- Development scripts and project configuration updates
- Updated README and package metadata
2026-07-19 20:38:16 +02:00

79 lines
2.8 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { pbCreate, pbDelete, pbUpdate } from "@/lib/pocketbase";
import { getAuth } from "@/lib/auth";
import { pbId } from "@/lib/pb";
const supplierSchema = z.object({
name: z.string().min(1, "Name is required"),
contact_number: z.string().optional().default(""),
email: z.string().email("Valid email required").or(z.literal("")).optional(),
address: z.string().optional().default(""),
vat_number: z.string().optional().default(""),
});
export type ActionResult = { ok: true } | { ok: false; error: string };
function clean(obj: any) {
const out: any = {};
for (const [k, v] of Object.entries(obj)) {
if (v === "" || v === null || v === undefined) continue;
out[k] = v;
}
return out;
}
export async function createSupplier(_: unknown, formData: FormData): Promise<ActionResult> {
const { token } = await getAuth();
if (!token) return { ok: false, error: "Not signed in" };
const parsed = supplierSchema.safeParse({
name: formData.get("name"),
contact_number: formData.get("contact_number") || "",
email: formData.get("email") || "",
address: formData.get("address") || "",
vat_number: formData.get("vat_number") || "",
});
if (!parsed.success) return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input" };
try {
await pbCreate("suppliers", { id: pbId(), ...clean(parsed.data) }, token);
} catch (err: any) {
return { ok: false, error: err?.message || "Failed to create supplier" };
}
revalidatePath("/suppliers");
return { ok: true };
}
export async function updateSupplier(id: string, _: unknown, formData: FormData): Promise<ActionResult> {
const { token } = await getAuth();
if (!token) return { ok: false, error: "Not signed in" };
const parsed = supplierSchema.safeParse({
name: formData.get("name"),
contact_number: formData.get("contact_number") || "",
email: formData.get("email") || "",
address: formData.get("address") || "",
vat_number: formData.get("vat_number") || "",
});
if (!parsed.success) return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input" };
try {
await pbUpdate("suppliers", id, clean(parsed.data), token);
} catch (err: any) {
return { ok: false, error: err?.message || "Failed to update supplier" };
}
revalidatePath("/suppliers");
revalidatePath(`/suppliers/${id}`);
return { ok: true };
}
export async function deleteSupplier(id: string): Promise<ActionResult> {
const { token } = await getAuth();
if (!token) return { ok: false, error: "Not signed in" };
try {
await pbDelete("suppliers", id, token);
} catch (err: any) {
return { ok: false, error: err?.message || "Failed to delete" };
}
revalidatePath("/suppliers");
return { ok: true };
}