202 lines
5.1 KiB
TypeScript
202 lines
5.1 KiB
TypeScript
import type { RequestHandler } from './$types'
|
|
import { prisma } from '$lib/server/database'
|
|
import {
|
|
jsonResponse,
|
|
errorResponse,
|
|
checkAdminAuth,
|
|
parseRequestBody
|
|
} from '$lib/server/api-utils'
|
|
import { logger } from '$lib/server/logger'
|
|
|
|
// GET /api/albums/[id] - Get a single album
|
|
export const GET: RequestHandler = async (event) => {
|
|
const id = parseInt(event.params.id)
|
|
if (isNaN(id)) {
|
|
return errorResponse('Invalid album ID', 400)
|
|
}
|
|
|
|
try {
|
|
const album = await prisma.album.findUnique({
|
|
where: { id },
|
|
include: {
|
|
photos: {
|
|
orderBy: { displayOrder: 'asc' }
|
|
},
|
|
_count: {
|
|
select: { photos: true }
|
|
}
|
|
}
|
|
})
|
|
|
|
if (!album) {
|
|
return errorResponse('Album not found', 404)
|
|
}
|
|
|
|
// Get all media usage records for this album's photos in one query
|
|
const mediaUsages = await prisma.mediaUsage.findMany({
|
|
where: {
|
|
contentType: 'album',
|
|
contentId: album.id,
|
|
fieldName: 'photos'
|
|
},
|
|
include: {
|
|
media: true
|
|
}
|
|
})
|
|
|
|
// Create a map of media by mediaId for efficient lookup
|
|
const mediaMap = new Map()
|
|
mediaUsages.forEach((usage) => {
|
|
if (usage.media) {
|
|
mediaMap.set(usage.mediaId, usage.media)
|
|
}
|
|
})
|
|
|
|
// Enrich photos with media information using proper media usage tracking
|
|
const photosWithMedia = album.photos.map((photo) => {
|
|
// Find the corresponding media usage record for this photo
|
|
const usage = mediaUsages.find((u) => u.media && u.media.filename === photo.filename)
|
|
const media = usage?.media
|
|
|
|
return {
|
|
...photo,
|
|
mediaId: media?.id || null,
|
|
altText: media?.altText || '',
|
|
description: media?.description || photo.caption || '',
|
|
isPhotography: media?.isPhotography || false,
|
|
mimeType: media?.mimeType || 'image/jpeg',
|
|
size: media?.size || 0
|
|
}
|
|
})
|
|
|
|
const albumWithEnrichedPhotos = {
|
|
...album,
|
|
photos: photosWithMedia
|
|
}
|
|
|
|
return jsonResponse(albumWithEnrichedPhotos)
|
|
} catch (error) {
|
|
logger.error('Failed to retrieve album', error as Error)
|
|
return errorResponse('Failed to retrieve album', 500)
|
|
}
|
|
}
|
|
|
|
// PUT /api/albums/[id] - Update an album
|
|
export const PUT: RequestHandler = async (event) => {
|
|
// Check authentication
|
|
if (!checkAdminAuth(event)) {
|
|
return errorResponse('Unauthorized', 401)
|
|
}
|
|
|
|
const id = parseInt(event.params.id)
|
|
if (isNaN(id)) {
|
|
return errorResponse('Invalid album ID', 400)
|
|
}
|
|
|
|
try {
|
|
const body = await parseRequestBody<{
|
|
slug?: string
|
|
title?: string
|
|
description?: string
|
|
date?: string
|
|
location?: string
|
|
coverPhotoId?: number
|
|
isPhotography?: boolean
|
|
status?: string
|
|
showInUniverse?: boolean
|
|
}>(event.request)
|
|
|
|
if (!body) {
|
|
return errorResponse('Invalid request body', 400)
|
|
}
|
|
|
|
// Check if album exists
|
|
const existing = await prisma.album.findUnique({
|
|
where: { id }
|
|
})
|
|
|
|
if (!existing) {
|
|
return errorResponse('Album not found', 404)
|
|
}
|
|
|
|
// If slug is being updated, check for conflicts
|
|
if (body.slug && body.slug !== existing.slug) {
|
|
const slugExists = await prisma.album.findUnique({
|
|
where: { slug: body.slug }
|
|
})
|
|
|
|
if (slugExists) {
|
|
return errorResponse('Album with this slug already exists', 409)
|
|
}
|
|
}
|
|
|
|
// Update album
|
|
const album = await prisma.album.update({
|
|
where: { id },
|
|
data: {
|
|
slug: body.slug !== undefined ? body.slug : existing.slug,
|
|
title: body.title !== undefined ? body.title : existing.title,
|
|
description: body.description !== undefined ? body.description : existing.description,
|
|
date: body.date !== undefined ? (body.date ? new Date(body.date) : null) : existing.date,
|
|
location: body.location !== undefined ? body.location : existing.location,
|
|
coverPhotoId: body.coverPhotoId !== undefined ? body.coverPhotoId : existing.coverPhotoId,
|
|
isPhotography: body.isPhotography !== undefined ? body.isPhotography : existing.isPhotography,
|
|
status: body.status !== undefined ? body.status : existing.status,
|
|
showInUniverse: body.showInUniverse !== undefined ? body.showInUniverse : existing.showInUniverse
|
|
}
|
|
})
|
|
|
|
logger.info('Album updated', { id, slug: album.slug })
|
|
|
|
return jsonResponse(album)
|
|
} catch (error) {
|
|
logger.error('Failed to update album', error as Error)
|
|
return errorResponse('Failed to update album', 500)
|
|
}
|
|
}
|
|
|
|
// DELETE /api/albums/[id] - Delete an album
|
|
export const DELETE: RequestHandler = async (event) => {
|
|
// Check authentication
|
|
if (!checkAdminAuth(event)) {
|
|
return errorResponse('Unauthorized', 401)
|
|
}
|
|
|
|
const id = parseInt(event.params.id)
|
|
if (isNaN(id)) {
|
|
return errorResponse('Invalid album ID', 400)
|
|
}
|
|
|
|
try {
|
|
// Check if album exists
|
|
const album = await prisma.album.findUnique({
|
|
where: { id },
|
|
include: {
|
|
_count: {
|
|
select: { photos: true }
|
|
}
|
|
}
|
|
})
|
|
|
|
if (!album) {
|
|
return errorResponse('Album not found', 404)
|
|
}
|
|
|
|
// Check if album has photos
|
|
if (album._count.photos > 0) {
|
|
return errorResponse('Cannot delete album that contains photos', 409)
|
|
}
|
|
|
|
// Delete album
|
|
await prisma.album.delete({
|
|
where: { id }
|
|
})
|
|
|
|
logger.info('Album deleted', { id, slug: album.slug })
|
|
|
|
return new Response(null, { status: 204 })
|
|
} catch (error) {
|
|
logger.error('Failed to delete album', error as Error)
|
|
return errorResponse('Failed to delete album', 500)
|
|
}
|
|
}
|