import { z } from 'zod'; import { createNamedBackendEntitySchema, idSchema, latitudeSchema, longitudeSchema, nameSchema, nonNegativeNumberSchema, positiveNumberSchema, } from '@/schemas/common'; /** * Backend-aligned Site schema * Matches the Go backend domain.Site struct * * Sites belong to Organizations (not just Businesses) * Organizations can be commercial, governmental, cultural, etc. * * Uses Zod v4's composition features for DRY code */ export const backendSiteSchema = createNamedBackendEntitySchema({ // Location Latitude: latitudeSchema, Longitude: longitudeSchema, // Site characteristics SiteType: z.string().optional().describe('Type of site'), FloorAreaM2: nonNegativeNumberSchema.optional().describe('Floor area in square meters'), Ownership: z.string().optional().describe('Ownership type'), // Ownership and operations OwnerOrganizationID: idSchema.describe('Owner organization ID'), // Site facilities and features AvailableUtilities: z.array(z.string()).optional().describe('Available utilities'), ParkingSpaces: nonNegativeNumberSchema.optional().describe('Number of parking spaces'), LoadingDocks: nonNegativeNumberSchema.optional().describe('Number of loading docks'), CraneCapacityTonnes: nonNegativeNumberSchema.optional().describe('Crane capacity in tonnes'), EnergyRating: z.string().optional().describe('Energy rating'), // Environmental WasteManagement: z.array(z.string()).optional().describe('Waste management features'), EnvironmentalImpact: z.string().optional().describe('Environmental impact'), // Historical/cultural building fields YearBuilt: z.string().optional().describe('Year built'), BuilderOwner: z.string().optional().describe('Builder/owner'), Architect: z.string().optional().describe('Architect'), OriginalPurpose: z.string().optional().describe('Original purpose'), CurrentUse: z.string().optional().describe('Current use'), Style: z.string().optional().describe('Architectural style'), Materials: z.string().optional().describe('Building materials'), Storeys: nonNegativeNumberSchema.optional().describe('Number of storeys'), HeritageStatus: z.string().optional().describe('Heritage status'), // Metadata Notes: z.string().optional().describe('Additional notes'), Sources: z.any().optional().describe('Data sources'), // Timestamps CreatedAt: z.string().optional().describe('Creation timestamp'), UpdatedAt: z.string().optional().describe('Last update timestamp'), // Relationships (populated via associations) Addresses: z.any().optional().describe('Associated addresses'), OwnerOrganization: z.any().optional().describe('Owner organization details'), OperatingOrganizations: z.any().optional().describe('Operating organizations'), ResourceFlows: z.any().optional().describe('Resource flows'), SharedAssets: z.any().optional().describe('Shared assets'), }); export type BackendSite = z.infer; /** * Request schema for creating a site * Uses Zod v4's composition for consistency */ export const createSiteRequestSchema = z.object({ name: nameSchema, address: z.string().optional().describe('Site address'), latitude: latitudeSchema, longitude: longitudeSchema, site_type: z.string().optional().describe('Type of site'), floor_area_m2: nonNegativeNumberSchema.optional().describe('Floor area in square meters'), owner_organization_id: idSchema.describe('Owner organization ID'), }); export type CreateSiteRequest = z.infer; /** * Query parameters for nearby sites * Uses Zod v4's coerce for automatic type conversion */ export const nearbySitesQuerySchema = z.object({ lat: z.coerce.number().pipe(latitudeSchema), lng: z.coerce.number().pipe(longitudeSchema), radius: z.coerce.number().pipe(positiveNumberSchema).optional(), }); export type NearbySitesQuery = z.infer;