forked from jappel/leistungsbilanz-ts
160 lines
5.5 KiB
TypeScript
160 lines
5.5 KiB
TypeScript
import { z } from "zod";
|
|
import {
|
|
distributionBoardInfoFieldMaxLengths,
|
|
distributionBoardSupplyTypes,
|
|
type DistributionBoardInfoField,
|
|
} from "../constants/distribution-board.js";
|
|
import {
|
|
projectCoverFieldMaxLengths,
|
|
type ProjectCoverField,
|
|
} from "../constants/project-cover.js";
|
|
import { expectedProjectRevisionSchema } from "./project-command.schemas.js";
|
|
|
|
// Empty text is stored as null so "not entered" has one representation.
|
|
const optionalCoverValueSchema = (field: ProjectCoverField) =>
|
|
z
|
|
.string()
|
|
.trim()
|
|
.max(projectCoverFieldMaxLengths[field])
|
|
.nullable()
|
|
.transform((value) => (value ? value : null))
|
|
.optional();
|
|
|
|
export const createProjectSchema = z.object({
|
|
name: z.string().trim().min(1).max(200),
|
|
internalProjectNumber: z.string().trim().max(100).optional(),
|
|
externalProjectNumber: z.string().trim().max(100).optional(),
|
|
buildingOwner: z.string().trim().max(200).optional(),
|
|
description: z.string().trim().max(2000).optional(),
|
|
isPublicBuilding: z.boolean().optional(),
|
|
singlePhaseVoltageV: z.number().positive().optional(),
|
|
threePhaseVoltageV: z.number().positive().optional(),
|
|
});
|
|
|
|
export const updateProjectSettingsSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
name: z.string().trim().min(1).max(200),
|
|
internalProjectNumber: z.string().trim().max(100).nullable(),
|
|
externalProjectNumber: z.string().trim().max(100).nullable(),
|
|
buildingOwner: z.string().trim().max(200).nullable(),
|
|
description: z.string().trim().max(2000).nullable(),
|
|
isPublicBuilding: z.boolean(),
|
|
singlePhaseVoltageV: z.number().positive(),
|
|
threePhaseVoltageV: z.number().positive(),
|
|
enabledDistributionBoardSupplyTypes: z
|
|
.array(z.enum(distributionBoardSupplyTypes))
|
|
.min(1)
|
|
.refine((values) => new Set(values).size === values.length, {
|
|
message: "Netzarten dürfen nicht mehrfach ausgewählt werden.",
|
|
}),
|
|
// Print cover fields; omitted fields keep their current value.
|
|
siteAddress: optionalCoverValueSchema("siteAddress"),
|
|
workStage: optionalCoverValueSchema("workStage"),
|
|
projectLead: optionalCoverValueSchema("projectLead"),
|
|
projectEditor: optionalCoverValueSchema("projectEditor"),
|
|
})
|
|
.strict();
|
|
|
|
export const createDistributionBoardSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
name: z.string().trim().min(1).max(200),
|
|
floorId: z.string().trim().min(1).nullable(),
|
|
supplyType: z.enum(distributionBoardSupplyTypes),
|
|
})
|
|
.strict();
|
|
|
|
// Empty info text is stored as null so that "not entered" has one
|
|
// representation in the database, snapshots and print view.
|
|
const distributionBoardInfoValueSchema = (field: DistributionBoardInfoField) =>
|
|
z
|
|
.string()
|
|
.trim()
|
|
.max(distributionBoardInfoFieldMaxLengths[field])
|
|
.nullable()
|
|
.transform((value) => (value ? value : null))
|
|
.optional();
|
|
|
|
export const updateDistributionBoardSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
floorId: z.string().trim().min(1).nullable(),
|
|
supplyType: z.enum(distributionBoardSupplyTypes),
|
|
simultaneityFactor: z.number().finite().min(0).max(1),
|
|
boardNumber: distributionBoardInfoValueSchema("boardNumber"),
|
|
location: distributionBoardInfoValueSchema("location"),
|
|
fedFrom: distributionBoardInfoValueSchema("fedFrom"),
|
|
remark: distributionBoardInfoValueSchema("remark"),
|
|
feedingDistributionBoardId: z.string().trim().min(1).nullable().optional(),
|
|
feedingCircuitId: z.string().trim().min(1).nullable().optional(),
|
|
})
|
|
.strict();
|
|
|
|
export const copyDistributionBoardSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
name: z.string().trim().min(1).max(200),
|
|
})
|
|
.strict();
|
|
|
|
export const deleteDistributionBoardSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
})
|
|
.strict();
|
|
|
|
export const createBuildingSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
name: z.string().trim().min(1).max(200),
|
|
})
|
|
.strict();
|
|
|
|
export const updateBuildingSchema = createBuildingSchema;
|
|
|
|
// A missing buildingId keeps the current value (older clients send only the
|
|
// name); null removes the floor from its building.
|
|
export const createFloorSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
name: z.string().trim().min(1).max(200),
|
|
buildingId: z.string().trim().min(1).nullable().optional(),
|
|
})
|
|
.strict();
|
|
|
|
export const updateFloorSchema = createFloorSchema;
|
|
|
|
export const deleteProjectLocationSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
})
|
|
.strict();
|
|
|
|
export const createRoomSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
floorId: z.string().trim().min(1).optional(),
|
|
roomNumber: z.string().trim().min(1).max(50),
|
|
roomName: z.string().trim().min(1).max(200),
|
|
areaM2: z.number().finite().nonnegative().nullable().optional(),
|
|
})
|
|
.strict();
|
|
|
|
export const updateRoomSchema = z
|
|
.object({
|
|
expectedRevision: expectedProjectRevisionSchema,
|
|
floorId: z.string().trim().min(1).nullable(),
|
|
roomNumber: z.string().trim().min(1).max(50),
|
|
roomName: z.string().trim().min(1).max(200),
|
|
areaM2: z.number().finite().nonnegative().nullable().optional(),
|
|
})
|
|
.strict();
|
|
|
|
export type CreateProjectInput = z.infer<typeof createProjectSchema>;
|
|
export type UpdateProjectSettingsInput = z.infer<
|
|
typeof updateProjectSettingsSchema
|
|
>;
|
|
export type CreateDistributionBoardInput = z.infer<
|
|
typeof createDistributionBoardSchema
|
|
>;
|