jedmund-svelte/src/routes/api/albums/[id]/+server.ts

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)
}
}