task-managment / src / lib / schemas / projectSchema.ts
projectSchema.ts
Raw
import { formatDate, removeTimeFromDate } from "@/lib/utils";
import { z } from "zod";
import { v4 as uuidv4 } from "uuid";
import { projectStatusEnum } from "@/server/project/domain/models";

const baseProjectSchema = z.object({
  name: z
    .string()
    .min(3, { message: "El nombre debe tener al menos 3 caracteres." }),
  costPerMeter: z.coerce
    .number({ message: "Introduce un número válido" })
    .min(0, { message: "Valor no puede ser inferior a 0" })
    .refine((value) => !isNaN(value), {
      message: "El costo por metro debe ser un número.",
    }),
  startDate: z.coerce
    .date({ message: "Fecha de inicio es requerida" })
    .transform((str) => removeTimeFromDate(str)),
  estimatedEndDate: z.coerce
    .date({ message: "Fecha final estimada es requerida" })
    .transform((str) => (str ? removeTimeFromDate(str) : undefined))
    .optional(),
  laborCost: z.coerce
    .number({ message: "Introduce un número válido" })
    .min(0, { message: "Valor no puede ser inferior a 0" })
    .default(0),
  totalCostMaterials: z.coerce
    .number({ message: "Introduce un número válido" })
    .min(0, { message: "Valor no puede ser inferior a 0" })
    .default(0),
  totalCostPerMeter: z.coerce
    .number({ message: "Introduce un número válido" })
    .min(0, { message: "Valor no puede ser inferior a 0" })
    .default(0),
  typeCotization: z.string().min(2, { message: "Tipo de cotizacion invalido" }),
  residence: z.string().min(2, { message: "Tipo de residencia invalido" }),
});

const withCustomRefinements = (schema: z.ZodType<any>) =>
  schema
    .refine(
      (data) => {
        if (data.estimatedEndDate) {
          return (
            formatDate(data.estimatedEndDate) >= formatDate(data.startDate!)
          );
        }
        return true;
      },
      {
        message:
          "La fecha final estimada debe ser igual o posterior a la fecha de inicio",
        path: ["estimatedEndDate"],
      }
    )
    

export const createProjectSchema = withCustomRefinements(
  baseProjectSchema.extend({
    id: z
      .string()
      .uuid()
      .default(() => uuidv4()),
  })
);

export const updateProjectSchema = withCustomRefinements(
  baseProjectSchema
    .extend({
      id: z.string().uuid({ message: "Proyecto incorrecto" }),
      status: z.enum(projectStatusEnum),
    })
    .partial()
);