Phase 8: Visitor Management - Visitor/VisitorLog/AccessZone models - Check-in/out with badge generation - Zone occupancy tracking - Kiosk and management pages Phase 9: Messaging & Communication - Announcements with priority levels - Acknowledgement tracking - Shift notes for team handoffs - AnnouncementBanner component Phase 10: Compliance & Audit Trail - Immutable AuditLog model - Document versioning and approval workflow - Acknowledgement tracking for SOPs - CSV export for audit logs Phase 11: Accessibility & i18n - WCAG 2.1 AA compliance utilities - react-i18next with EN/ES translations - User preferences context (theme, font size, etc) - High contrast and reduced motion support Phase 12: Hardware Integration - QR code generation for batches/plants/visitors - Printable label system - Visitor badge printing Phase 13: Advanced Features - Environmental monitoring (sensors, readings, alerts) - Financial tracking (transactions, P&L reports) - AI/ML insights (yield predictions, anomaly detection)
167 lines
4.9 KiB
TypeScript
167 lines
4.9 KiB
TypeScript
import api from './api';
|
|
|
|
export interface LayoutProperty {
|
|
id: string;
|
|
name: string;
|
|
address?: string;
|
|
licenseNum?: string;
|
|
buildings: LayoutBuilding[];
|
|
createdAt?: string;
|
|
}
|
|
|
|
export interface LayoutBuilding {
|
|
id: string;
|
|
propertyId: string;
|
|
name: string;
|
|
code: string;
|
|
type: string;
|
|
floors: LayoutFloor[];
|
|
}
|
|
|
|
export interface LayoutFloor {
|
|
id: string;
|
|
buildingId: string;
|
|
name: string;
|
|
number: number;
|
|
width: number;
|
|
height: number;
|
|
rooms: LayoutRoom[];
|
|
}
|
|
|
|
export interface LayoutRoom {
|
|
id: string;
|
|
floorId: string;
|
|
name: string;
|
|
code: string;
|
|
type: 'VEG' | 'FLOWER' | 'DRY' | 'CURE' | 'MOTHER' | 'CLONE' | 'FACILITY';
|
|
posX: number;
|
|
posY: number;
|
|
width: number;
|
|
height: number;
|
|
rotation: number;
|
|
color?: string;
|
|
sections?: LayoutSection[];
|
|
}
|
|
|
|
export interface LayoutPosition {
|
|
id: string;
|
|
sectionId: string;
|
|
row: number;
|
|
column: number;
|
|
slot: number;
|
|
status: string;
|
|
plantId?: string;
|
|
plant?: any;
|
|
}
|
|
|
|
export interface LayoutSection {
|
|
id: string;
|
|
roomId: string;
|
|
name: string;
|
|
code: string;
|
|
type: string;
|
|
posX: number;
|
|
posY: number;
|
|
width: number;
|
|
height: number;
|
|
rows: number;
|
|
columns: number;
|
|
spacing?: number;
|
|
positions?: LayoutPosition[];
|
|
}
|
|
|
|
// ========================================
|
|
// API Functions
|
|
// ========================================
|
|
|
|
export const layoutApi = {
|
|
// Properties
|
|
async getProperties(): Promise<LayoutProperty[]> {
|
|
const response = await api.get('/api/layout/properties');
|
|
return response.data;
|
|
},
|
|
|
|
async createProperty(data: { name: string; address?: string; licenseNum?: string }): Promise<LayoutProperty> {
|
|
const response = await api.post('/api/layout/properties', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Buildings
|
|
async createBuilding(data: { propertyId: string; name: string; code: string; type: string }): Promise<LayoutBuilding> {
|
|
const response = await api.post('/api/layout/buildings', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Floors
|
|
async getFloor(id: string): Promise<LayoutFloor & { building: LayoutBuilding }> {
|
|
const response = await api.get(`/api/layout/floors/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
async createFloor(data: { buildingId: string; name: string; number: number; width?: number; height?: number }): Promise<LayoutFloor> {
|
|
const response = await api.post('/api/layout/floors', data);
|
|
return response.data;
|
|
},
|
|
|
|
async saveFloorLayout(floorId: string, rooms: LayoutRoom[]): Promise<LayoutFloor> {
|
|
const roomsForApi = rooms.map(r => ({
|
|
id: r.id,
|
|
name: r.name,
|
|
code: r.code,
|
|
type: r.type,
|
|
posX: r.posX,
|
|
posY: r.posY,
|
|
width: r.width,
|
|
height: r.height,
|
|
color: r.color,
|
|
rotation: r.rotation
|
|
}));
|
|
const response = await api.post(`/api/layout/floors/${floorId}/layout`, { rooms: roomsForApi });
|
|
return response.data;
|
|
},
|
|
|
|
// Rooms
|
|
async createRoom(data: Partial<LayoutRoom>): Promise<LayoutRoom> {
|
|
const response = await api.post('/api/layout/rooms', data);
|
|
return response.data;
|
|
},
|
|
|
|
async updateRoom(id: string, data: Partial<LayoutRoom>): Promise<LayoutRoom> {
|
|
const response = await api.put(`/api/layout/rooms/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
async deleteRoom(id: string): Promise<void> {
|
|
await api.delete(`/api/layout/rooms/${id}`);
|
|
},
|
|
|
|
// Sections
|
|
async createSection(data: Partial<LayoutSection> & { rows: number; columns: number }): Promise<LayoutSection> {
|
|
const response = await api.post('/api/layout/sections', data);
|
|
return response.data;
|
|
},
|
|
|
|
async getRoomSections(roomId: string): Promise<LayoutSection[]> {
|
|
const response = await api.get(`/api/layout/rooms/${roomId}/sections`);
|
|
return response.data;
|
|
},
|
|
|
|
async placeBatchInPosition(positionId: string, batchId: string): Promise<void> {
|
|
await api.post(`/api/layout/positions/${positionId}/occupy`, { batchId });
|
|
},
|
|
|
|
async fillSection(sectionId: string, batchId: string, maxCount?: number): Promise<{ plantsCreated: number; message: string }> {
|
|
const response = await api.post(`/api/layout/sections/${sectionId}/fill`, { batchId, maxCount });
|
|
return response.data;
|
|
},
|
|
|
|
async movePlant(plantId: string, targetPositionId: string, reason?: string): Promise<{ newAddress: string; message: string }> {
|
|
const response = await api.post(`/api/layout/plants/${plantId}/move`, { targetPositionId, reason });
|
|
return response.data;
|
|
},
|
|
|
|
async getSection(id: string): Promise<LayoutSection> {
|
|
const response = await api.get(`/api/layout/sections/${id}`);
|
|
return response.data;
|
|
}
|
|
};
|