103 lines
2.6 KiB
TypeScript
103 lines
2.6 KiB
TypeScript
"use server";
|
|
|
|
import { z } from "zod";
|
|
|
|
const submitPayloadSchema = z.object({
|
|
typeId: z.string().optional().nullable(),
|
|
customCardId: z.string().optional().nullable(),
|
|
optionId: z.string().optional().nullable(),
|
|
extraIds: z.array(z.string()).default([]),
|
|
|
|
customerName: z.string().min(1),
|
|
customerEmail: z.string().email(),
|
|
customerSocials: z.string().optional().nullable(),
|
|
message: z.string().min(1),
|
|
}).superRefine((data, ctx) => {
|
|
const hasType = Boolean(data.typeId);
|
|
const hasCustom = Boolean(data.customCardId);
|
|
if (!hasType && !hasCustom) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["typeId"],
|
|
message: "Missing commission type or custom card",
|
|
});
|
|
}
|
|
if (hasType && hasCustom) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["typeId"],
|
|
message: "Only one of typeId or customCardId is allowed",
|
|
});
|
|
}
|
|
});
|
|
|
|
export type SubmitCommissionPayload = z.infer<typeof submitPayloadSchema>;
|
|
|
|
export async function submitCommissionRequest(input: {
|
|
payload: SubmitCommissionPayload;
|
|
files: File[];
|
|
}) {
|
|
const adminUrl = process.env.ADMIN_URL;
|
|
if (!adminUrl) {
|
|
throw new Error("ADMIN_URL is not set on the server");
|
|
}
|
|
|
|
const payload = submitPayloadSchema.parse(input.payload);
|
|
const files = input.files ?? [];
|
|
|
|
const MAX_FILES = 10;
|
|
const MAX_BYTES_EACH = 10 * 1024 * 1024; // 10MB
|
|
|
|
if (files.length > MAX_FILES) {
|
|
throw new Error("Too many files");
|
|
}
|
|
|
|
for (const f of files) {
|
|
if (f.size > MAX_BYTES_EACH) {
|
|
throw new Error(`File too large: ${f.name}`);
|
|
}
|
|
}
|
|
|
|
const fd = new FormData();
|
|
fd.set("payload", JSON.stringify(payload));
|
|
|
|
for (const file of files) {
|
|
fd.append("files", file, file.name);
|
|
}
|
|
|
|
const res = await fetch(
|
|
`${adminUrl.replace(/\/$/, "")}/api/v1/commissions`,
|
|
{
|
|
method: "POST",
|
|
body: fd,
|
|
cache: "no-store",
|
|
}
|
|
);
|
|
|
|
if (!res.ok) {
|
|
const raw = await res.text().catch(() => "");
|
|
const statusLine = `${res.status} ${res.statusText || ""}`.trim();
|
|
|
|
let message = `Admin API error: ${statusLine}`;
|
|
|
|
if (raw) {
|
|
try {
|
|
const parsed = JSON.parse(raw);
|
|
message =
|
|
parsed?.error
|
|
? `Admin API error: ${statusLine} — ${parsed.error}`
|
|
: parsed?.message
|
|
? `Admin API error: ${statusLine} — ${parsed.message}`
|
|
: `Admin API error: ${statusLine} — ${raw}`;
|
|
} catch {
|
|
message = `Admin API error: ${statusLine} — ${raw}`;
|
|
}
|
|
}
|
|
|
|
console.error("[submitCommissionRequest] upstream error", { statusLine, raw });
|
|
|
|
throw new Error(message);
|
|
}
|
|
return (await res.json()) as { id: string; createdAt: string };
|
|
}
|