99 lines
2.5 KiB
TypeScript
99 lines
2.5 KiB
TypeScript
"use server";
|
|
|
|
import { z } from "zod";
|
|
|
|
/**
|
|
* Server action
|
|
* Forwards a multipart/form-data request (payload + files[])
|
|
* from the public app to the admin app's public commissions endpoint.
|
|
*
|
|
* Server-only env required:
|
|
* ADMIN_URL=https://admin.domain.com
|
|
*/
|
|
|
|
const submitPayloadSchema = z.object({
|
|
typeId: 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),
|
|
});
|
|
|
|
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 ?? [];
|
|
|
|
// Optional safety limits
|
|
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();
|
|
|
|
// Show something useful even if raw is empty
|
|
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}`;
|
|
}
|
|
}
|
|
|
|
// Log full body server-side for debugging (safe; this is server-only)
|
|
console.error("[submitCommissionRequest] upstream error", { statusLine, raw });
|
|
|
|
throw new Error(message);
|
|
}
|
|
|
|
// Expected response: { id: string; createdAt: string }
|
|
return (await res.json()) as { id: string; createdAt: string };
|
|
}
|