122 lines
3.3 KiB
TypeScript
122 lines
3.3 KiB
TypeScript
import { FastifyPluginAsync } from 'fastify';
|
|
import { z } from 'zod';
|
|
import { db } from '../config/database.js';
|
|
import { galleryImages } from '../db/schema.js';
|
|
import { eq } from 'drizzle-orm';
|
|
|
|
const galleryImageSchema = z.object({
|
|
imageUrl: z.string().url(),
|
|
altText: z.string().min(1).max(200),
|
|
displayOrder: z.number().int().min(0),
|
|
isPublished: z.boolean().optional().default(true),
|
|
});
|
|
|
|
const galleryRoute: FastifyPluginAsync = async (fastify) => {
|
|
|
|
// List all gallery images
|
|
fastify.get('/gallery', {
|
|
preHandler: [fastify.authenticate],
|
|
}, async (request, reply) => {
|
|
const images = await db.select().from(galleryImages).orderBy(galleryImages.displayOrder);
|
|
return { images };
|
|
});
|
|
|
|
// Get single gallery image
|
|
fastify.get('/gallery/:id', {
|
|
preHandler: [fastify.authenticate],
|
|
}, async (request, reply) => {
|
|
const { id } = request.params as { id: string };
|
|
const image = await db.select().from(galleryImages).where(eq(galleryImages.id, id)).limit(1);
|
|
|
|
if (image.length === 0) {
|
|
return reply.code(404).send({ error: 'Image not found' });
|
|
}
|
|
|
|
return { image: image[0] };
|
|
});
|
|
|
|
// Create gallery image
|
|
fastify.post('/gallery', {
|
|
schema: {
|
|
body: galleryImageSchema,
|
|
},
|
|
preHandler: [fastify.authenticate],
|
|
}, async (request, reply) => {
|
|
const data = request.body as z.infer<typeof galleryImageSchema>;
|
|
|
|
const [newImage] = await db.insert(galleryImages).values(data).returning();
|
|
|
|
return reply.code(201).send({ image: newImage });
|
|
});
|
|
|
|
// Update gallery image
|
|
fastify.put('/gallery/:id', {
|
|
schema: {
|
|
body: galleryImageSchema,
|
|
},
|
|
preHandler: [fastify.authenticate],
|
|
}, async (request, reply) => {
|
|
const { id } = request.params as { id: string };
|
|
const data = request.body as z.infer<typeof galleryImageSchema>;
|
|
|
|
const [updated] = await db
|
|
.update(galleryImages)
|
|
.set(data)
|
|
.where(eq(galleryImages.id, id))
|
|
.returning();
|
|
|
|
if (!updated) {
|
|
return reply.code(404).send({ error: 'Image not found' });
|
|
}
|
|
|
|
return { image: updated };
|
|
});
|
|
|
|
// Delete gallery image
|
|
fastify.delete('/gallery/:id', {
|
|
preHandler: [fastify.authenticate],
|
|
}, async (request, reply) => {
|
|
const { id } = request.params as { id: string };
|
|
|
|
const [deleted] = await db
|
|
.delete(galleryImages)
|
|
.where(eq(galleryImages.id, id))
|
|
.returning();
|
|
|
|
if (!deleted) {
|
|
return reply.code(404).send({ error: 'Image not found' });
|
|
}
|
|
|
|
return { message: 'Image deleted successfully' };
|
|
});
|
|
|
|
// Reorder gallery images
|
|
fastify.put('/gallery/reorder', {
|
|
schema: {
|
|
body: z.object({
|
|
orders: z.array(z.object({
|
|
id: z.string().uuid(),
|
|
displayOrder: z.number().int().min(0),
|
|
})),
|
|
}),
|
|
},
|
|
preHandler: [fastify.authenticate],
|
|
}, async (request, reply) => {
|
|
const { orders } = request.body as { orders: Array<{ id: string; displayOrder: number }> };
|
|
|
|
// Update all in transaction
|
|
await db.transaction(async (tx) => {
|
|
for (const { id, displayOrder } of orders) {
|
|
await tx
|
|
.update(galleryImages)
|
|
.set({ displayOrder })
|
|
.where(eq(galleryImages.id, id));
|
|
}
|
|
});
|
|
|
|
return { message: 'Gallery images reordered successfully' };
|
|
});
|
|
};
|
|
|
|
export default galleryRoute;
|