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.

122 lines
3.2 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { getCurrentUser } from "@/data/auth";
import {
countPemakaianSatuanBarang,
deleteSatuanBarang,
insertSatuanBarang,
updateSatuanBarang,
type SatuanBarangInput,
} from "@/data/satuan-barang";
export type SimpanSatuanBarangState = {
ok: boolean;
error?: string;
fieldErrors?: { namaSatuanBarang?: string[] };
values?: { namaSatuanBarang?: string };
idSatuanBarang?: number;
};
export type HapusSatuanBarangState = { ok: boolean; error?: string };
const satuanBarangSchema = z.object({
namaSatuanBarang: z
.string()
.trim()
.min(1, "Nama satuan wajib diisi")
.max(30, "Maksimal 30 karakter"),
});
export async function simpanSatuanBarang(
_prevState: SimpanSatuanBarangState,
formData: FormData,
): Promise<SimpanSatuanBarangState> {
const user = await getCurrentUser();
const values = {
namaSatuanBarang: String(formData.get("namaSatuanBarang") ?? ""),
};
const parsed = satuanBarangSchema.safeParse(values);
if (!parsed.success) {
return {
ok: false,
fieldErrors: z.flattenError(parsed.error).fieldErrors,
values,
};
}
const input: SatuanBarangInput = parsed.data;
const idRaw = String(formData.get("idSatuanBarang") ?? "");
const id = idRaw ? Number.parseInt(idRaw, 10) : null;
if (id !== null && (!Number.isSafeInteger(id) || id <= 0)) {
return { ok: false, error: "ID satuan tidak valid", values };
}
try {
if (id !== null) {
const updated = await updateSatuanBarang(id, input);
if (!updated) {
return { ok: false, error: "Satuan tidak ditemukan", values };
}
revalidatePath("/master/satuan-barang");
return { ok: true, idSatuanBarang: id };
}
const idBaru = await insertSatuanBarang(input);
revalidatePath("/master/satuan-barang");
return { ok: true, idSatuanBarang: idBaru };
} catch (error) {
console.error(
"[simpanSatuanBarang] gagal",
{
userId: user.id,
idSatuanBarang: id ?? "(baru)",
nama: input.namaSatuanBarang,
},
error,
);
return {
ok: false,
error: "Gagal menyimpan satuan, coba simpan ulang",
values,
};
}
}
export async function hapusSatuanBarang(
_prevState: HapusSatuanBarangState,
formData: FormData,
): Promise<HapusSatuanBarangState> {
const user = await getCurrentUser();
const id = Number.parseInt(String(formData.get("idSatuanBarang") ?? ""), 10);
if (!Number.isSafeInteger(id) || id <= 0) {
return { ok: false, error: "ID satuan tidak ada" };
}
try {
const dipakai = await countPemakaianSatuanBarang(id);
if (dipakai > 0) {
return {
ok: false,
error: `Satuan masih dipakai ${dipakai} barang, tidak bisa dihapus`,
};
}
const deleted = await deleteSatuanBarang(id);
if (!deleted) {
return { ok: false, error: "Satuan tidak ditemukan" };
}
revalidatePath("/master/satuan-barang");
return { ok: true };
} catch (error) {
console.error("[hapusSatuanBarang] gagal", { userId: user.id, id }, error);
return {
ok: false,
error: "Gagal menghapus satuan, coba hapus ulang",
};
}
}