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
79 lines
2.8 KiB
TypeScript
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 };
|
|
}
|