feat: Implement persistence for plant placements in layout editor
This commit is contained in:
parent
ec9e98e696
commit
7ec8b1fc57
4 changed files with 34 additions and 16 deletions
|
|
@ -644,6 +644,8 @@ model FacilityPlant {
|
||||||
tagNumber String @unique // METRC tag
|
tagNumber String @unique // METRC tag
|
||||||
batchId String?
|
batchId String?
|
||||||
batch Batch? @relation(fields: [batchId], references: [id])
|
batch Batch? @relation(fields: [batchId], references: [id])
|
||||||
|
plantTypeId String?
|
||||||
|
plantType PlantType? @relation(fields: [plantTypeId], references: [id])
|
||||||
position FacilityPosition @relation(fields: [positionId], references: [id])
|
position FacilityPosition @relation(fields: [positionId], references: [id])
|
||||||
positionId String @unique
|
positionId String @unique
|
||||||
address String // Full hierarchical address
|
address String // Full hierarchical address
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,7 @@ export async function layoutRoutes(fastify: FastifyInstance, options: FastifyPlu
|
||||||
handler: async (request, reply) => {
|
handler: async (request, reply) => {
|
||||||
try {
|
try {
|
||||||
const { id } = request.params as any;
|
const { id } = request.params as any;
|
||||||
const { batchId } = request.body as any;
|
const { batchId, plantTypeId } = request.body as any;
|
||||||
|
|
||||||
const position = await prisma.facilityPosition.findUnique({
|
const position = await prisma.facilityPosition.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
|
|
@ -614,6 +614,7 @@ export async function layoutRoutes(fastify: FastifyInstance, options: FastifyPlu
|
||||||
data: {
|
data: {
|
||||||
tagNumber: `P-${Date.now()}-${Math.floor(Math.random() * 1000)}`,
|
tagNumber: `P-${Date.now()}-${Math.floor(Math.random() * 1000)}`,
|
||||||
batchId,
|
batchId,
|
||||||
|
plantTypeId,
|
||||||
positionId: id,
|
positionId: id,
|
||||||
address,
|
address,
|
||||||
status: 'ACTIVE'
|
status: 'ACTIVE'
|
||||||
|
|
|
||||||
|
|
@ -55,15 +55,23 @@ export function LayoutEditor({ floorId, className }: LayoutEditorProps) {
|
||||||
rows: section.rows,
|
rows: section.rows,
|
||||||
columns: section.columns,
|
columns: section.columns,
|
||||||
tiers: 1, // TODO: get from section
|
tiers: 1, // TODO: get from section
|
||||||
slots: section.positions.map(pos => ({
|
slots: section.positions.map(pos => {
|
||||||
id: pos.id,
|
// Find plant type by ID (new way) or strain name (legacy way)
|
||||||
row: pos.row,
|
const mappedPlantType = pos.plant
|
||||||
column: pos.column,
|
? plantTypes.find(pt => pt.id === pos.plant?.plantTypeId) ||
|
||||||
tier: pos.tier,
|
plantTypes.find(pt => pt.strain === pos.plant?.strain)
|
||||||
status: pos.status as PlantSlotData['status'],
|
: undefined;
|
||||||
plantType: pos.plant ? plantTypes.find(pt => pt.strain === pos.plant?.strain) : undefined,
|
|
||||||
tagNumber: pos.plant?.tagNumber,
|
return {
|
||||||
})),
|
id: pos.id,
|
||||||
|
row: pos.row,
|
||||||
|
column: pos.column,
|
||||||
|
tier: pos.tier,
|
||||||
|
status: pos.status as PlantSlotData['status'],
|
||||||
|
plantType: mappedPlantType,
|
||||||
|
tagNumber: pos.plant?.tagNumber,
|
||||||
|
};
|
||||||
|
}),
|
||||||
}))
|
}))
|
||||||
) || [];
|
) || [];
|
||||||
|
|
||||||
|
|
@ -72,10 +80,17 @@ export function LayoutEditor({ floorId, className }: LayoutEditorProps) {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSlotDrop = useCallback(async (slot: PlantSlotData, plantType: LayoutPlantType) => {
|
const handleSlotDrop = useCallback(async (slot: PlantSlotData, plantType: LayoutPlantType) => {
|
||||||
console.log('Dropped', plantType.name, 'onto slot', slot.id);
|
try {
|
||||||
// TODO: Implement actual placement via API
|
await layoutApi.occupyPosition(slot.id, { plantTypeId: plantType.id });
|
||||||
// For now, just log the action
|
|
||||||
}, []);
|
// Reload floor data to reflect changes
|
||||||
|
const floor = await layoutApi.getFloor3D(floorId);
|
||||||
|
setFloorData(floor);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to place plant:', e);
|
||||||
|
setError('Failed to place plant. Please try again.');
|
||||||
|
}
|
||||||
|
}, [floorId]);
|
||||||
|
|
||||||
const handleDragStart = useCallback((plantType: LayoutPlantType) => {
|
const handleDragStart = useCallback((plantType: LayoutPlantType) => {
|
||||||
setDraggingType(plantType);
|
setDraggingType(plantType);
|
||||||
|
|
|
||||||
|
|
@ -246,8 +246,8 @@ export const layoutApi = {
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
async placeBatchInPosition(positionId: string, batchId: string): Promise<void> {
|
async occupyPosition(positionId: string, data: { batchId?: string; plantTypeId?: string }): Promise<void> {
|
||||||
await api.post(`/layout/positions/${positionId}/occupy`, { batchId });
|
await api.post(`/layout/positions/${positionId}/occupy`, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
async fillSection(sectionId: string, batchId: string, maxCount?: number): Promise<{ plantsCreated: number; message: string }> {
|
async fillSection(sectionId: string, batchId: string, maxCount?: number): Promise<{ plantsCreated: number; message: string }> {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue