PrithviGuardian / client /src /lib /validationSchemas.ts
Varad Bakshi
Fresh upload
e7427b5
Raw
History Blame Contribute Delete
9.38 kB
// Comprehensive validation schemas for all modules
import { z } from "zod";
// Common validation rules
const positiveNumber = z.number().positive("Must be a positive number");
const nonNegativeNumber = z.number().min(0, "Must be zero or positive");
const requiredString = z.string().min(1, "This field is required");
const coordinates = z.string().regex(/^-?\d+\.?\d*,-?\d+\.?\d*$/, "Must be in format: latitude,longitude");
// Foundation Module (Bhoomi Bandhan)
export const foundationInputSchema = z.object({
soilType: z.enum(["clay", "sand", "silt", "loam", "rock"], { required_error: "Soil type is required" }),
loadRequirement: positiveNumber,
depth: positiveNumber,
width: positiveNumber,
safetyFactor: z.number().min(1.5).max(5, "Safety factor must be between 1.5 and 5"),
waterTable: nonNegativeNumber,
seismicZone: z.enum(["I", "II", "III", "IV", "V"], { required_error: "Seismic zone is required" })
});
// Road Design Module (Marg Yantra)
export const roadDesignInputSchema = z.object({
designSpeed: z.number().min(20).max(120, "Design speed must be between 20-120 km/h"),
radius: positiveNumber,
superelevation: z.number().min(0).max(0.07, "Superelevation must be between 0-7%"),
gradientPercent: z.number().min(0).max(12, "Gradient must be between 0-12%"),
pavementType: z.enum(["flexible", "rigid", "composite"], { required_error: "Pavement type is required" }),
trafficLoad: positiveNumber
});
// Survey Module (Naksha Drishti)
export const surveyInputSchema = z.object({
stations: z.array(z.object({
name: requiredString,
backsight: z.number().optional(),
foresight: z.number().optional(),
intermediate: z.number().optional()
})).min(2, "At least 2 stations are required"),
instrumentHeight: positiveNumber,
benchmarkLevel: z.number()
});
// Earthwork Module (Bhumi Ganit)
export const earthworkInputSchema = z.object({
gridPoints: z.array(z.object({
x: z.number(),
y: z.number(),
existingLevel: z.number(),
proposedLevel: z.number()
})).min(4, "At least 4 grid points are required"),
gridSpacing: positiveNumber,
bulkingFactor: z.number().min(1.1).max(1.4, "Bulking factor must be between 1.1-1.4"),
compactionFactor: z.number().min(0.8).max(0.95, "Compaction factor must be between 0.8-0.95")
});
// Water Treatment Module (Jal Punarjanma)
export const waterTreatmentInputSchema = z.object({
flowRate: positiveNumber,
influent: z.object({
bod: nonNegativeNumber,
cod: nonNegativeNumber,
tss: nonNegativeNumber,
ph: z.number().min(0).max(14, "pH must be between 0-14"),
turbidity: nonNegativeNumber
}),
treatmentType: z.enum(["primary", "secondary", "tertiary", "advanced"], { required_error: "Treatment type is required" }),
designCapacity: positiveNumber
});
// Environmental Impact Module (Paryavaran Sankalp)
export const eiaInputSchema = z.object({
projectType: z.enum(["industrial", "mining", "infrastructure", "residential", "commercial"], { required_error: "Project type is required" }),
area: positiveNumber,
location: requiredString,
environmentalZone: z.enum(["residential", "commercial", "industrial", "sensitive"], { required_error: "Environmental zone is required" }),
waterRequirement: nonNegativeNumber,
wasteGeneration: nonNegativeNumber,
energyConsumption: nonNegativeNumber
});
// Emission Calculator Module (Dhvansh Ganit)
export const emissionInputSchema = z.object({
sourceType: z.enum(["vehicle", "industry", "power_plant", "domestic"], { required_error: "Source type is required" }),
fuelType: z.enum(["petrol", "diesel", "coal", "natural_gas", "lpg"], { required_error: "Fuel type is required" }),
fuelConsumption: positiveNumber,
operatingHours: z.number().min(1).max(8760, "Operating hours must be between 1-8760"),
emissionStandard: z.enum(["BS4", "BS6", "Euro4", "Euro5", "Euro6"], { required_error: "Emission standard is required" })
});
// Green Building Module (Harit Manch)
export const greenBuildingInputSchema = z.object({
buildingType: z.enum(["residential", "commercial", "institutional", "industrial"], { required_error: "Building type is required" }),
area: positiveNumber,
floors: z.number().min(1).max(100, "Number of floors must be between 1-100"),
orientation: z.enum(["north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest"], { required_error: "Orientation is required" }),
energyFeatures: z.array(z.string()).min(1, "At least one energy feature is required"),
waterFeatures: z.array(z.string()).min(1, "At least one water feature is required")
});
// Project Management Schema
export const projectSchema = z.object({
name: requiredString,
description: z.string().optional(),
type: z.enum(["university", "residential", "commercial", "infrastructure"], { required_error: "Project type is required" }),
location: z.string().optional(),
status: z.enum(["active", "completed", "archived"]).default("active")
});
// Government Report Schema
export const governmentReportSchema = z.object({
title: requiredString,
reportType: z.enum(["eia", "cpcb", "municipal", "forest_clearance"], { required_error: "Report type is required" }),
projectId: z.number().optional()
});
// Crop Planning Schema
export const cropPlanSchema = z.object({
farmName: requiredString,
location: requiredString,
soilType: z.enum(["clay", "sandy", "loam", "black"], { required_error: "Soil type is required" }),
climate: z.enum(["tropical", "subtropical", "temperate"], { required_error: "Climate is required" }),
area: positiveNumber,
season: z.enum(["kharif", "rabi", "zaid"], { required_error: "Season is required" })
});
// Coastal Project Schema
export const coastalProjectSchema = z.object({
siteName: requiredString,
coordinates: coordinates,
coastlineLength: positiveNumber.optional(),
projectId: z.number().optional()
});
// Community Post Schema
export const communityPostSchema = z.object({
title: requiredString,
description: z.string().min(10, "Description must be at least 10 characters"),
category: z.enum(["case_study", "best_practice", "design_sharing"], { required_error: "Category is required" }),
tags: z.array(z.string()).optional()
});
// Traditional Module Schemas
export const varunaJalSanchaySchema = z.object({
catchmentArea: positiveNumber,
rainfall: positiveNumber,
runoffCoefficient: z.number().min(0.1).max(0.9, "Runoff coefficient must be between 0.1-0.9"),
storageRequirement: positiveNumber,
johad: z.object({
length: positiveNumber,
width: positiveNumber,
depth: positiveNumber
}),
baoli: z.object({
steps: z.number().min(5).max(100, "Number of steps must be between 5-100"),
depth: positiveNumber,
diameter: positiveNumber
})
});
export const vrikshaRakshakSchema = z.object({
groveArea: positiveNumber,
species: z.array(z.string()).min(1, "At least one species is required"),
biodiversityIndex: z.number().min(0).max(10, "Biodiversity index must be between 0-10"),
conservationPlan: z.object({
protectionMeasures: z.array(z.string()).min(1, "At least one protection measure is required"),
managementPractices: z.array(z.string()).min(1, "At least one management practice is required")
})
});
export const amritUrjaSchema = z.object({
solarCapacity: positiveNumber,
biogasCapacity: positiveNumber,
energyDemand: positiveNumber,
location: requiredString,
solar: z.object({
panelEfficiency: z.number().min(10).max(25, "Panel efficiency must be between 10-25%"),
sunlightHours: z.number().min(4).max(12, "Sunlight hours must be between 4-12")
}),
biogas: z.object({
organicWaste: positiveNumber,
gasProduction: positiveNumber,
slurryProduction: positiveNumber
})
});
// Validation helper functions
export function validateInputs<T>(schema: z.ZodSchema<T>, data: unknown): { success: true; data: T } | { success: false; errors: string[] } {
try {
const validatedData = schema.parse(data);
return { success: true, data: validatedData };
} catch (error) {
if (error instanceof z.ZodError) {
const errors = error.errors.map(err => `${err.path.join('.')}: ${err.message}`);
return { success: false, errors };
}
return { success: false, errors: ['Unknown validation error'] };
}
}
export function safeParseNumber(value: any, fieldName: string): number {
if (value === null || value === undefined || value === '') {
throw new Error(`${fieldName} is required`);
}
const num = typeof value === 'string' ? parseFloat(value) : Number(value);
if (isNaN(num) || !isFinite(num)) {
throw new Error(`${fieldName} must be a valid number`);
}
return num;
}
export function validateRange(value: number, min: number, max: number, fieldName: string): void {
if (value < min || value > max) {
throw new Error(`${fieldName} must be between ${min} and ${max}`);
}
}
export function validateCoordinates(coords: string): { lat: number; lng: number } {
const parts = coords.split(',');
if (parts.length !== 2) {
throw new Error('Coordinates must be in format: latitude,longitude');
}
const lat = safeParseNumber(parts[0].trim(), 'Latitude');
const lng = safeParseNumber(parts[1].trim(), 'Longitude');
validateRange(lat, -90, 90, 'Latitude');
validateRange(lng, -180, 180, 'Longitude');
return { lat, lng };
}