feat: implement full CRUD functionality for projects with image upload support and admin dashboard management

This commit is contained in:
Yolando
2026-03-28 21:11:36 +07:00
parent 0549f12a97
commit 01ecca4b28
17 changed files with 2399 additions and 6 deletions

38
src/core/storage/minio.ts Normal file
View File

@@ -0,0 +1,38 @@
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
export const s3Client = new S3Client({
region: "us-east-1",
endpoint: process.env.MINIO_ENDPOINT || "http://localhost:9000",
forcePathStyle: true, // Required for MinIO
credentials: {
accessKeyId: process.env.MINIO_ACCESS_KEY || "admin",
secretAccessKey: process.env.MINIO_SECRET_KEY || "password123",
},
});
export const BUCKET_NAME = process.env.MINIO_BUCKET_NAME || "portfolio";
/**
* Uploads a file to MinIO and returns the public URL
*/
export async function uploadFileToMinio(file: File): Promise<string> {
const bytes = await file.arrayBuffer();
const buffer = Buffer.from(bytes);
// Generate unique filename to prevent overwriting
const uniqueName = `${Date.now()}-${file.name.replace(/[^a-zA-Z0-9.-]/g, "_")}`;
await s3Client.send(
new PutObjectCommand({
Bucket: BUCKET_NAME,
Key: uniqueName,
Body: buffer,
ContentType: file.type,
// Setting ACL public-read ensures the frontend can display the image natively
// NOTE: Ensure the MinIO bucket policy itself allows public read if ACL doesn't stick
// ACL: "public-read",
})
);
return `${process.env.MINIO_ENDPOINT}/${BUCKET_NAME}/${uniqueName}`;
}