feat(layout): Add Ceiling Height and Tiers to Floor creation
- Added ceilingHeight and defaultTiers to FacilityFloor model - Updated API routes and frontend client - Updated AddFloorModal with new fields and clearer labels
This commit is contained in:
parent
0c970cadb7
commit
da93320ccf
5 changed files with 94 additions and 8 deletions
40
.agent/artifacts/deployment_summary_2025_12_11.md
Normal file
40
.agent/artifacts/deployment_summary_2025_12_11.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Deployment & Verification Summary
|
||||
|
||||
**Date:** 2025-12-11
|
||||
**Environment:** `nexus-vector` (Demo)
|
||||
**URL:** [https://777wolfpack.runfoo.run](https://777wolfpack.runfoo.run)
|
||||
|
||||
## Key Achievements
|
||||
|
||||
1. **Layout Designer Enhancements**
|
||||
* **Property Creation:** Implemented "Add Property" workflow directly within the Layout Designer.
|
||||
* **Building Creation:** Added `AddBuildingModal` and "Add New Building" button in the floor selector.
|
||||
* **Floor Creation:** Integrated `AddFloorModal` for creating new floors on the fly.
|
||||
* **API Updates:** Fixed `layout.routes.ts` to support complex nested queries and proper address generation.
|
||||
|
||||
2. **Backend & Database Fixes**
|
||||
* **Schema Update:** Added bi-directional relation between `Batch` and `FacilityPlant` in `schema.prisma`.
|
||||
* **Seed Script Fixed:** Corrected `seed.js` to use valid `RoleEnum` values (`GROWER`, `STAFF`) and `SupplyCategory` (`OTHER`), and removed invalid `createdById` field in Task creation.
|
||||
* **Type Safety:** Resolved TypeScript errors in `audit.routes.ts` (null vs undefined), `insights.routes.ts` (Batch relations), and `messaging.routes.ts` (duplicate keys).
|
||||
|
||||
3. **Deployment Success**
|
||||
* Successfully deployed the latest code to `nexus-vector`.
|
||||
* Database migrations applied and seed data populated successfully.
|
||||
* Verified frontend application loads and Layout Designer components are active.
|
||||
|
||||
## Verification Steps Performed
|
||||
|
||||
* **Build:** Backend and Frontend Docker builds completed successfully.
|
||||
* **Database:** `prisma db push` and `node prisma/seed.js` executed without errors.
|
||||
* **Frontend:** Verified access to Layout Designer and presence of "Setup Property" / creation controls.
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
To test the new features:
|
||||
|
||||
1. Login as `admin@runfoo.run` / `password123`.
|
||||
2. Navigate to **Layout Designer**.
|
||||
3. Open the top-left dropdown (Floor Selector).
|
||||
4. Use **"Add New Property"** to set up a facility.
|
||||
5. Use **"Add New Building"** to add structures.
|
||||
6. Use **"Add Floor"** to define levels.
|
||||
|
|
@ -545,6 +545,8 @@ model FacilityFloor {
|
|||
number Int // 1, 2, 3...
|
||||
width Int // feet
|
||||
height Int // feet
|
||||
ceilingHeight Float? // feet
|
||||
defaultTiers Int @default(1)
|
||||
rooms FacilityRoom[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
|
|
|||
|
|
@ -155,9 +155,17 @@ export async function layoutRoutes(fastify: FastifyInstance, options: FastifyPlu
|
|||
fastify.post('/floors', {
|
||||
handler: async (request, reply) => {
|
||||
try {
|
||||
const { buildingId, name, number, width, height } = request.body as any;
|
||||
const { buildingId, name, number, width, height, ceilingHeight, defaultTiers } = request.body as any;
|
||||
const floor = await prisma.facilityFloor.create({
|
||||
data: { buildingId, name, number, width: width || 200, height: height || 150 },
|
||||
data: {
|
||||
buildingId,
|
||||
name,
|
||||
number,
|
||||
width: width || 200,
|
||||
height: height || 150,
|
||||
ceilingHeight: ceilingHeight || null,
|
||||
defaultTiers: defaultTiers || 1
|
||||
},
|
||||
include: { rooms: true }
|
||||
});
|
||||
return reply.status(201).send(floor);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ export function AddFloorModal({ isOpen, onClose, buildingId, onCreated }: AddFlo
|
|||
name: '',
|
||||
number: 1,
|
||||
width: 100,
|
||||
height: 100
|
||||
height: 100,
|
||||
ceilingHeight: undefined,
|
||||
defaultTiers: 1
|
||||
});
|
||||
|
||||
if (!isOpen || !buildingId) return null;
|
||||
|
|
@ -30,12 +32,14 @@ export function AddFloorModal({ isOpen, onClose, buildingId, onCreated }: AddFlo
|
|||
name: formData.name.trim(),
|
||||
number: formData.number,
|
||||
width: formData.width,
|
||||
height: formData.height
|
||||
height: formData.height,
|
||||
ceilingHeight: formData.ceilingHeight,
|
||||
defaultTiers: formData.defaultTiers
|
||||
});
|
||||
onCreated(floor.id);
|
||||
onClose();
|
||||
// Reset form
|
||||
setFormData({ name: '', number: formData.number + 1, width: 100, height: 100 });
|
||||
setFormData({ name: '', number: formData.number + 1, width: 100, height: 100, ceilingHeight: undefined, defaultTiers: 1 });
|
||||
} catch (error) {
|
||||
console.error('Failed to create floor:', error);
|
||||
} finally {
|
||||
|
|
@ -75,7 +79,7 @@ export function AddFloorModal({ isOpen, onClose, buildingId, onCreated }: AddFlo
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm text-slate-400 mb-2">Number</label>
|
||||
<input
|
||||
|
|
@ -85,6 +89,18 @@ export function AddFloorModal({ isOpen, onClose, buildingId, onCreated }: AddFlo
|
|||
className="w-full bg-slate-800 border border-slate-700 rounded-lg px-4 py-3 text-white focus:border-emerald-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm text-slate-400 mb-2">Default Tiers</label>
|
||||
<input
|
||||
type="number"
|
||||
value={formData.defaultTiers}
|
||||
onChange={(e) => setFormData({ ...formData, defaultTiers: parseInt(e.target.value) || 1 })}
|
||||
className="w-full bg-slate-800 border border-slate-700 rounded-lg px-4 py-3 text-white focus:border-emerald-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm text-slate-400 mb-2">Width (ft)</label>
|
||||
<input
|
||||
|
|
@ -95,7 +111,7 @@ export function AddFloorModal({ isOpen, onClose, buildingId, onCreated }: AddFlo
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm text-slate-400 mb-2">Height (ft)</label>
|
||||
<label className="block text-sm text-slate-400 mb-2">Length (ft)</label>
|
||||
<input
|
||||
type="number"
|
||||
value={formData.height}
|
||||
|
|
@ -103,6 +119,16 @@ export function AddFloorModal({ isOpen, onClose, buildingId, onCreated }: AddFlo
|
|||
className="w-full bg-slate-800 border border-slate-700 rounded-lg px-4 py-3 text-white focus:border-emerald-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm text-slate-400 mb-2">Ceiling (ft)</label>
|
||||
<input
|
||||
type="number"
|
||||
value={formData.ceilingHeight ?? ''}
|
||||
onChange={(e) => setFormData({ ...formData, ceilingHeight: e.target.value ? parseInt(e.target.value) : undefined })}
|
||||
placeholder="Optional"
|
||||
className="w-full bg-slate-800 border border-slate-700 rounded-lg px-4 py-3 text-white focus:border-emerald-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ export interface LayoutFloor {
|
|||
number: number;
|
||||
width: number;
|
||||
height: number;
|
||||
ceilingHeight?: number;
|
||||
defaultTiers?: number;
|
||||
rooms: LayoutRoom[];
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +100,15 @@ export const layoutApi = {
|
|||
return response.data;
|
||||
},
|
||||
|
||||
async createFloor(data: { buildingId: string; name: string; number: number; width?: number; height?: number }): Promise<LayoutFloor> {
|
||||
async createFloor(data: {
|
||||
buildingId: string;
|
||||
name: string;
|
||||
number: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
ceilingHeight?: number;
|
||||
defaultTiers?: number;
|
||||
}): Promise<LayoutFloor> {
|
||||
const response = await api.post('/api/layout/floors', data);
|
||||
return response.data;
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue