feat: add product image upload to admin panel
- Add storage.ts utility (saveImage, deleteImageFile) for local disk operations - Add POST /api/admin/products/[id]/images: validates MIME type and 5MB limit, saves file, creates MediaAsset record - Add DELETE /api/admin/products/[id]/images?imageId=: removes file and DB record - Add Images section to product edit form (hidden for new products until saved) - Display images in square aspect-ratio grid matching storefront display - Support multi-file upload; hover to reveal delete button
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { mkdir, writeFile, unlink } from 'fs/promises'
|
||||
import path from 'path'
|
||||
|
||||
const UPLOAD_DIR = path.join(process.cwd(), 'public', 'uploads')
|
||||
|
||||
export async function saveImage(
|
||||
productId: string,
|
||||
buffer: Buffer,
|
||||
originalFilename: string
|
||||
): Promise<string> {
|
||||
const dir = path.join(UPLOAD_DIR, productId)
|
||||
await mkdir(dir, { recursive: true })
|
||||
const safeName = originalFilename.replace(/[^a-z0-9._-]/gi, '_').toLowerCase()
|
||||
const filename = `${Date.now()}-${safeName}`
|
||||
await writeFile(path.join(dir, filename), buffer)
|
||||
return `/uploads/${productId}/${filename}`
|
||||
}
|
||||
|
||||
export async function deleteImageFile(url: string): Promise<void> {
|
||||
const filePath = path.join(process.cwd(), 'public', url)
|
||||
await unlink(filePath)
|
||||
}
|
||||
Reference in New Issue
Block a user