Add commission type example image

This commit is contained in:
2026-01-31 16:37:24 +01:00
parent 51cfde4d78
commit e869f19142
7 changed files with 229 additions and 12 deletions

View File

@ -0,0 +1,92 @@
"use server";
import { s3 } from "@/lib/s3";
import {
DeleteObjectCommand,
ListObjectsV2Command,
PutObjectCommand,
} from "@aws-sdk/client-s3";
const PREFIX = "commissions/examples/";
export type CommissionExampleItem = {
key: string;
url: string;
size: number | null;
lastModified: string | null;
};
function buildImageUrl(key: string) {
return `/api/image/${encodeURI(key)}`;
}
function sanitizeFilename(name: string) {
return name.replace(/[^a-zA-Z0-9._-]/g, "_");
}
export async function listCommissionExamples(): Promise<CommissionExampleItem[]> {
const command = new ListObjectsV2Command({
Bucket: `${process.env.BUCKET_NAME}`,
Prefix: PREFIX,
});
const res = await s3.send(command);
return (
res.Contents?.filter((obj) => obj.Key && obj.Key !== PREFIX).map((obj) => {
const key = obj.Key as string;
return {
key,
url: buildImageUrl(key),
size: obj.Size ?? null,
lastModified: obj.LastModified?.toISOString() ?? null,
};
}) ?? []
);
}
export async function uploadCommissionExample(
formData: FormData
): Promise<CommissionExampleItem> {
const file = formData.get("file");
if (!(file instanceof File)) {
throw new Error("Missing file");
}
if (!file.type.startsWith("image/")) {
throw new Error("Only image uploads are allowed");
}
const safeName = sanitizeFilename(file.name || "example");
const key = `${PREFIX}${Date.now()}-${safeName}`;
const buffer = Buffer.from(await file.arrayBuffer());
await s3.send(
new PutObjectCommand({
Bucket: `${process.env.BUCKET_NAME}`,
Key: key,
Body: buffer,
ContentType: file.type,
})
);
return {
key,
url: buildImageUrl(key),
size: file.size,
lastModified: new Date().toISOString(),
};
}
export async function deleteCommissionExample(key: string) {
if (!key.startsWith(PREFIX)) {
throw new Error("Invalid key");
}
await s3.send(
new DeleteObjectCommand({
Bucket: `${process.env.BUCKET_NAME}`,
Key: key,
})
);
}

View File

@ -2,10 +2,21 @@
import { prisma } from "@/lib/prisma";
export async function getActiveGuidelines(): Promise<string | null> {
export async function getActiveGuidelines(): Promise<{
markdown: string | null;
exampleImageUrl: string | null;
}> {
const guidelines = await prisma.commissionGuidelines.findFirst({
where: { isActive: true },
orderBy: { createdAt: 'desc' },
orderBy: { createdAt: "desc" },
select: {
markdown: true,
exampleImageUrl: true,
},
});
return guidelines?.markdown ?? null;
return {
markdown: guidelines?.markdown ?? null,
exampleImageUrl: guidelines?.exampleImageUrl ?? null,
};
}

View File

@ -2,7 +2,7 @@
import { prisma } from "@/lib/prisma";
export async function saveGuidelines(markdown: string) {
export async function saveGuidelines(markdown: string, exampleImageUrl: string | null) {
await prisma.commissionGuidelines.updateMany({
where: { isActive: true },
data: { isActive: false },
@ -11,6 +11,7 @@ export async function saveGuidelines(markdown: string) {
await prisma.commissionGuidelines.create({
data: {
markdown,
exampleImageUrl: exampleImageUrl || null,
},
});
}
}