You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.6 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { getCurrentUser } from "@/data/auth";
import {
deletePelanggan,
insertPelanggan,
updatePelanggan,
type PelangganInput,
} from "@/data/pelanggan";
import {
logActionError,
type DeleteState,
type FormState,
} from "@/lib/server-action";
type PelangganField = keyof typeof pelangganSchema.shape;
export type SimpanPelangganState = FormState<PelangganField> & {
kdCustomer?: string;
};
export type HapusPelangganState = DeleteState;
const pelangganSchema = z.object({
nama: z.string().trim().min(1, "Nama wajib diisi").max(100),
alias: z.string().trim().max(11),
ktp: z.string().trim().max(16),
alamat: z.string().trim().min(1, "Alamat wajib diisi").max(100),
wilayah: z.string().trim().max(200),
telp: z.string().trim().max(15),
ponsel: z.string().trim().max(15),
email: z.string().trim().max(30),
jenisCustomer: z.string().trim().max(1),
upline: z.string().trim().max(11),
btsBon: z.coerce.number().int().min(0).max(2_000_000_000),
});
function emptyStringToNull(value: string): string | null {
return value === "" ? null : value;
}
export async function simpanPelanggan(
_prevState: SimpanPelangganState,
formData: FormData,
): Promise<SimpanPelangganState> {
const user = await getCurrentUser();
const fields = Object.keys(pelangganSchema.shape) as PelangganField[];
const values = Object.fromEntries(
fields.map((field) => [field, String(formData.get(field) ?? "")]),
) as Record<PelangganField, string>;
const parsed = pelangganSchema.safeParse(values);
if (!parsed.success) {
return {
ok: false,
fieldErrors: z.flattenError(parsed.error).fieldErrors,
values,
};
}
const input: PelangganInput = {
...parsed.data,
wilayah: emptyStringToNull(parsed.data.wilayah),
telp: emptyStringToNull(parsed.data.telp),
ponsel: emptyStringToNull(parsed.data.ponsel),
email: emptyStringToNull(parsed.data.email),
jenisCustomer: emptyStringToNull(parsed.data.jenisCustomer),
upline: emptyStringToNull(parsed.data.upline),
};
const kdCustomer = String(formData.get("kdCustomer") ?? "").trim();
try {
if (kdCustomer === "") {
const kdBaru = await insertPelanggan(input);
revalidatePath("/master/pelanggan");
return { ok: true, kdCustomer: kdBaru };
}
const updated = await updatePelanggan(kdCustomer, input);
if (!updated) {
return { ok: false, error: "Pelanggan tidak ditemukan", values };
}
revalidatePath("/master/pelanggan");
return { ok: true, kdCustomer };
} catch (error) {
logActionError(
"simpanPelanggan",
{ userId: user.id, kdCustomer: kdCustomer || "(baru)", nama: input.nama },
error,
);
return {
ok: false,
error: "Gagal menyimpan pelanggan, coba simpan ulang",
values,
};
}
}
export async function hapusPelanggan(
_prevState: HapusPelangganState,
formData: FormData,
): Promise<HapusPelangganState> {
const user = await getCurrentUser();
const kdCustomer = String(formData.get("kdCustomer") ?? "").trim();
if (kdCustomer === "") {
return { ok: false, error: "Kode pelanggan tidak ada" };
}
try {
const deleted = await deletePelanggan(kdCustomer);
if (!deleted) {
return { ok: false, error: "Pelanggan tidak ditemukan" };
}
revalidatePath("/master/pelanggan");
return { ok: true };
} catch (error) {
logActionError("hapusPelanggan", { userId: user.id, kdCustomer }, error);
return {
ok: false,
error: "Gagal menghapus pelanggan, coba hapus ulang",
};
}
}