fix: backend syntax and frontend toast API
Some checks are pending
Test / backend-test (push) Waiting to run
Test / frontend-test (push) Waiting to run

This commit is contained in:
fullsizemalt 2026-01-01 22:49:33 -08:00
parent a13d6f6907
commit 2bc596c527
2 changed files with 547 additions and 551 deletions

View file

@ -713,14 +713,10 @@ export async function layoutRoutes(fastify: FastifyInstance, options: FastifyPlu
return reply.status(500).send({ error: 'Failed to move plant' }); return reply.status(500).send({ error: 'Failed to move plant' });
} }
} }
}; });
} catch (error) {
fastify.log.error(error);
return reply.status(500).send({ error: 'Failed to move plant' });
});
// Update Plant (Tag, Notes) // Update Plant (Tag, Notes)
fastify.patch('/plants/:id', { fastify.patch('/plants/:id', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id } = request.params as any; const { id } = request.params as any;
@ -761,10 +757,10 @@ fastify.patch('/plants/:id', {
return reply.status(500).send({ error: 'Failed to update plant' }); return reply.status(500).send({ error: 'Failed to update plant' });
} }
} }
}); });
// Destroy Plant // Destroy Plant
fastify.post('/plants/:id/destroy', { fastify.post('/plants/:id/destroy', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id } = request.params as any; const { id } = request.params as any;
@ -804,10 +800,10 @@ fastify.post('/plants/:id/destroy', {
return reply.status(500).send({ error: 'Failed to destroy plant' }); return reply.status(500).send({ error: 'Failed to destroy plant' });
} }
} }
}); });
// Harvest Plant // Harvest Plant
fastify.post('/plants/:id/harvest', { fastify.post('/plants/:id/harvest', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id } = request.params as any; const { id } = request.params as any;
@ -847,10 +843,10 @@ fastify.post('/plants/:id/harvest', {
return reply.status(500).send({ error: 'Failed to harvest plant' }); return reply.status(500).send({ error: 'Failed to harvest plant' });
} }
} }
}); });
// Bulk Fill Section (Place plants in all empty positions) // Bulk Fill Section (Place plants in all empty positions)
fastify.post('/sections/:id/fill', { fastify.post('/sections/:id/fill', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id } = request.params as any; const { id } = request.params as any;
@ -915,14 +911,14 @@ fastify.post('/sections/:id/fill', {
return reply.status(500).send({ error: 'Failed to fill section' }); return reply.status(500).send({ error: 'Failed to fill section' });
} }
} }
}); });
// ======================================== // ========================================
// SECTION ROUTES // SECTION ROUTES
// ======================================== // ========================================
// Create section with positions // Create section with positions
fastify.post('/sections', { fastify.post('/sections', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { roomId, name, code, type, posX, posY, width, height, rows, columns, spacing, tiers } = request.body as any; const { roomId, name, code, type, posX, posY, width, height, rows, columns, spacing, tiers } = request.body as any;
@ -971,10 +967,10 @@ fastify.post('/sections', {
return reply.status(500).send({ error: 'Failed to create section' }); return reply.status(500).send({ error: 'Failed to create section' });
} }
} }
}); });
// Get section with positions // Get section with positions
fastify.get('/sections/:id', { fastify.get('/sections/:id', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id } = request.params as any; const { id } = request.params as any;
@ -999,14 +995,14 @@ fastify.get('/sections/:id', {
return reply.status(500).send({ error: 'Failed to fetch section' }); return reply.status(500).send({ error: 'Failed to fetch section' });
} }
} }
}); });
// ======================================== // ========================================
// BULK SAVE LAYOUT // BULK SAVE LAYOUT
// ======================================== // ========================================
// Save entire floor layout // Save entire floor layout
fastify.post('/floors/:id/layout', { fastify.post('/floors/:id/layout', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id: floorId } = request.params as any; const { id: floorId } = request.params as any;
@ -1143,14 +1139,14 @@ fastify.post('/floors/:id/layout', {
return reply.status(500).send({ error: 'Failed to save layout' }); return reply.status(500).send({ error: 'Failed to save layout' });
} }
} }
}); });
// ======================================== // ========================================
// POSITION ROUTES // POSITION ROUTES
// ======================================== // ========================================
// Get hierarchical address for a position // Get hierarchical address for a position
fastify.get('/positions/:id/address', { fastify.get('/positions/:id/address', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { id } = request.params as any; const { id } = request.params as any;
@ -1208,14 +1204,14 @@ fastify.get('/positions/:id/address', {
return reply.status(500).send({ error: 'Failed to generate address' }); return reply.status(500).send({ error: 'Failed to generate address' });
} }
} }
}); });
// ======================================== // ========================================
// PLANT TYPE LIBRARY ROUTES (Rackula-inspired) // PLANT TYPE LIBRARY ROUTES (Rackula-inspired)
// ======================================== // ========================================
// Get all plant types // Get all plant types
fastify.get('/plant-types', { fastify.get('/plant-types', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const plantTypes = await prisma.plantType.findMany({ const plantTypes = await prisma.plantType.findMany({
@ -1227,10 +1223,10 @@ fastify.get('/plant-types', {
return reply.status(500).send({ error: 'Failed to fetch plant types' }); return reply.status(500).send({ error: 'Failed to fetch plant types' });
} }
} }
}); });
// Get plant type by slug // Get plant type by slug
fastify.get('/plant-types/:slug', { fastify.get('/plant-types/:slug', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { slug } = request.params as { slug: string }; const { slug } = request.params as { slug: string };
@ -1248,10 +1244,10 @@ fastify.get('/plant-types/:slug', {
return reply.status(500).send({ error: 'Failed to fetch plant type' }); return reply.status(500).send({ error: 'Failed to fetch plant type' });
} }
} }
}); });
// Create plant type // Create plant type
fastify.post('/plant-types', { fastify.post('/plant-types', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { name, strain, category, colour, growthDays, yieldGrams, notes, tags, customFields } = request.body as any; const { name, strain, category, colour, growthDays, yieldGrams, notes, tags, customFields } = request.body as any;
@ -1292,10 +1288,10 @@ fastify.post('/plant-types', {
return reply.status(500).send({ error: 'Failed to create plant type' }); return reply.status(500).send({ error: 'Failed to create plant type' });
} }
} }
}); });
// Update plant type // Update plant type
fastify.put('/plant-types/:slug', { fastify.put('/plant-types/:slug', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { slug } = request.params as { slug: string }; const { slug } = request.params as { slug: string };
@ -1322,10 +1318,10 @@ fastify.put('/plant-types/:slug', {
return reply.status(500).send({ error: 'Failed to update plant type' }); return reply.status(500).send({ error: 'Failed to update plant type' });
} }
} }
}); });
// Delete plant type // Delete plant type
fastify.delete('/plant-types/:slug', { fastify.delete('/plant-types/:slug', {
handler: async (request, reply) => { handler: async (request, reply) => {
try { try {
const { slug } = request.params as { slug: string }; const { slug } = request.params as { slug: string };
@ -1336,5 +1332,5 @@ fastify.delete('/plant-types/:slug', {
return reply.status(500).send({ error: 'Failed to delete plant type' }); return reply.status(500).send({ error: 'Failed to delete plant type' });
} }
} }
}); });
} }

View file

@ -236,7 +236,7 @@ export function LayoutEditor({ floorId, className }: LayoutEditorProps) {
if (newTag && newTag !== selectedSlot.plant?.tagNumber) { if (newTag && newTag !== selectedSlot.plant?.tagNumber) {
layoutApi.updatePlant(selectedSlot.plant!.id, { tagNumber: newTag }) layoutApi.updatePlant(selectedSlot.plant!.id, { tagNumber: newTag })
.then(() => { .then(() => {
toast({ title: 'Tag Updated', description: newTag }); toast.info('Tag Updated', { description: newTag });
reloadFloorData(); reloadFloorData();
setSelectedSlot(prev => prev ? ({ ...prev, plant: { ...prev.plant!, tagNumber: newTag } }) : null); setSelectedSlot(prev => prev ? ({ ...prev, plant: { ...prev.plant!, tagNumber: newTag } }) : null);
}); });
@ -319,7 +319,7 @@ export function LayoutEditor({ floorId, className }: LayoutEditorProps) {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<button <button
className="py-2.5 bg-secondary hover:bg-secondary/80 text-foreground border border-border text-sm rounded-lg transition-colors font-medium flex items-center justify-center gap-2" className="py-2.5 bg-secondary hover:bg-secondary/80 text-foreground border border-border text-sm rounded-lg transition-colors font-medium flex items-center justify-center gap-2"
onClick={() => toast({ title: 'Move Plant', description: 'Drag and drop plants on the grid to move them.' })} onClick={() => toast.info('Move Plant', { description: 'Drag and drop plants on the grid to move them.' })}
> >
<Move className="w-4 h-4" /> Move <Move className="w-4 h-4" /> Move
</button> </button>
@ -362,7 +362,7 @@ export function LayoutEditor({ floorId, className }: LayoutEditorProps) {
)} )}
<button <button
className="col-span-2 py-2.5 bg-primary hover:bg-primary-hover text-primary-foreground font-medium text-sm rounded-lg shadow-sm transition-all flex items-center justify-center gap-2" className="col-span-2 py-2.5 bg-primary hover:bg-primary-hover text-primary-foreground font-medium text-sm rounded-lg shadow-sm transition-all flex items-center justify-center gap-2"
onClick={() => toast({ title: 'Compliance', description: 'Opening compliance manager...' })} onClick={() => toast.info('Compliance', { description: 'Opening compliance manager...' })}
> >
<ShieldCheck className="w-4 h-4" /> Manage Compliance <ShieldCheck className="w-4 h-4" /> Manage Compliance
</button> </button>