Update shift creation to use a new form schema and improve validation
Refactor shift creation endpoint to use `insertShiftFormSchema` for validation and data transformation, and update client-side components to handle datetime strings. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 99f0fce6-9386-489a-9632-1d81223cab44 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/99f0fce6-9386-489a-9632-1d81223cab44/cpTvSfP
This commit is contained in:
parent
133be08785
commit
177ad892f0
4
.replit
4
.replit
@ -22,6 +22,10 @@ externalPort = 3001
|
||||
localPort = 41343
|
||||
externalPort = 3000
|
||||
|
||||
[[ports]]
|
||||
localPort = 45115
|
||||
externalPort = 3002
|
||||
|
||||
[env]
|
||||
PORT = "5000"
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { insertShiftSchema } from "@shared/schema";
|
||||
import { insertShiftFormSchema } from "@shared/schema";
|
||||
import { Plus, Calendar, MapPin, Users, Clock } from "lucide-react";
|
||||
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
@ -29,16 +29,13 @@ export default function Shifts() {
|
||||
queryKey: ["/api/sites"],
|
||||
});
|
||||
|
||||
const form = useForm<InsertShift>({
|
||||
resolver: zodResolver(insertShiftSchema.extend({
|
||||
startTime: insertShiftSchema.shape.startTime,
|
||||
endTime: insertShiftSchema.shape.endTime,
|
||||
})),
|
||||
const form = useForm({
|
||||
resolver: zodResolver(insertShiftFormSchema),
|
||||
defaultValues: {
|
||||
siteId: "",
|
||||
startTime: new Date(),
|
||||
endTime: new Date(),
|
||||
status: "planned",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
status: "planned" as const,
|
||||
},
|
||||
});
|
||||
|
||||
@ -65,13 +62,7 @@ export default function Shifts() {
|
||||
});
|
||||
|
||||
const onSubmit = (data: InsertShift) => {
|
||||
// Ensure dates are Date objects, not strings
|
||||
const shiftData = {
|
||||
...data,
|
||||
startTime: data.startTime instanceof Date ? data.startTime : new Date(data.startTime),
|
||||
endTime: data.endTime instanceof Date ? data.endTime : new Date(data.endTime),
|
||||
};
|
||||
createMutation.mutate(shiftData);
|
||||
createMutation.mutate(data);
|
||||
};
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
@ -155,8 +146,8 @@ export default function Shifts() {
|
||||
<input
|
||||
type="datetime-local"
|
||||
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
|
||||
value={field.value ? format(new Date(field.value), "yyyy-MM-dd'T'HH:mm") : ""}
|
||||
onChange={(e) => field.onChange(new Date(e.target.value))}
|
||||
value={field.value}
|
||||
onChange={(e) => field.onChange(e.target.value)}
|
||||
data-testid="input-start-time"
|
||||
/>
|
||||
</FormControl>
|
||||
@ -175,8 +166,8 @@ export default function Shifts() {
|
||||
<input
|
||||
type="datetime-local"
|
||||
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
|
||||
value={field.value ? format(new Date(field.value), "yyyy-MM-dd'T'HH:mm") : ""}
|
||||
onChange={(e) => field.onChange(new Date(e.target.value))}
|
||||
value={field.value}
|
||||
onChange={(e) => field.onChange(e.target.value)}
|
||||
data-testid="input-end-time"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@ -3,7 +3,7 @@ import { createServer, type Server } from "http";
|
||||
import { storage } from "./storage";
|
||||
import { setupAuth, isAuthenticated } from "./replitAuth";
|
||||
import { db } from "./db";
|
||||
import { guards, certifications, sites, shifts, shiftAssignments, users } from "@shared/schema";
|
||||
import { guards, certifications, sites, shifts, shiftAssignments, users, insertShiftSchema } from "@shared/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { differenceInDays } from "date-fns";
|
||||
|
||||
@ -197,7 +197,28 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
|
||||
app.post("/api/shifts", isAuthenticated, async (req, res) => {
|
||||
try {
|
||||
const shift = await storage.createShift(req.body);
|
||||
// Validate that required fields are present and dates are valid strings
|
||||
if (!req.body.siteId || !req.body.startTime || !req.body.endTime) {
|
||||
return res.status(400).json({ message: "Missing required fields" });
|
||||
}
|
||||
|
||||
// Convert and validate dates
|
||||
const startTime = new Date(req.body.startTime);
|
||||
const endTime = new Date(req.body.endTime);
|
||||
|
||||
if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
|
||||
return res.status(400).json({ message: "Invalid date format" });
|
||||
}
|
||||
|
||||
// Validate and transform the request body
|
||||
const validatedData = insertShiftSchema.parse({
|
||||
siteId: req.body.siteId,
|
||||
startTime,
|
||||
endTime,
|
||||
status: req.body.status || "planned",
|
||||
});
|
||||
|
||||
const shift = await storage.createShift(validatedData);
|
||||
res.json(shift);
|
||||
} catch (error) {
|
||||
console.error("Error creating shift:", error);
|
||||
|
||||
@ -262,6 +262,18 @@ export const insertShiftSchema = createInsertSchema(shifts).omit({
|
||||
updatedAt: true,
|
||||
});
|
||||
|
||||
// Form schema that accepts datetime strings and transforms to Date
|
||||
export const insertShiftFormSchema = z.object({
|
||||
siteId: z.string().min(1, "Sito obbligatorio"),
|
||||
startTime: z.string().min(1, "Data inizio obbligatoria").refine((val) => !isNaN(new Date(val).getTime()), {
|
||||
message: "Data inizio non valida",
|
||||
}).transform((val) => new Date(val)),
|
||||
endTime: z.string().min(1, "Data fine obbligatoria").refine((val) => !isNaN(new Date(val).getTime()), {
|
||||
message: "Data fine non valida",
|
||||
}).transform((val) => new Date(val)),
|
||||
status: z.enum(["planned", "active", "completed", "cancelled"]).default("planned"),
|
||||
});
|
||||
|
||||
export const insertShiftAssignmentSchema = createInsertSchema(shiftAssignments).omit({
|
||||
id: true,
|
||||
assignedAt: true,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user