p 1 and 2 compeleted

This commit is contained in:
dimitar committed 2026-03-11 01:43:19 +01:00
1 parent 6adb541967
commit 3573709d99
28 files changed
+2533 -240

No files matched your search

@@ -0,0 +1,111 @@
import { z } from "zod";
/**
* Validation schemas for user creation flow
*/
// Step 1: Role Selection
export const roleSelectionSchema = z.object({
role: z.enum(["admin", "trainer", "client"], {
message: "Please select a role",
}),
});
export type RoleSelectionData = z.infer<typeof roleSelectionSchema>;
// Step 2: Basic Information
export const basicInfoSchema = z.object({
firstName: z
.string()
.min(2, "First name must be at least 2 characters")
.max(50, "First name must be less than 50 characters"),
lastName: z
.string()
.min(2, "Last name must be at least 2 characters")
.max(50, "Last name must be less than 50 characters"),
phone: z
.string()
.regex(/^\+?[1-9]\d{1,14}$/, "Please enter a valid phone number")
.optional()
.or(z.literal("")),
email: z.string().email("Please enter a valid email address"),
});
export type BasicInfoData = z.infer<typeof basicInfoSchema>;
// Step 3: Client-Specific Information (only for clients)
export const clientInfoSchema = z.object({
membershipType: z.enum(["basic", "premium", "vip"], {
message: "Please select a membership type",
}),
membershipStatus: z.enum(["active", "inactive", "suspended"]),
sendWelcomeEmail: z.boolean(),
});
export type ClientInfoData = z.infer<typeof clientInfoSchema>;
// Step 4: Invitation Options (for admin/trainer with email)
export const invitationOptionsSchema = z.object({
sendInvitation: z.boolean(),
gymId: z.string().optional(),
});
export type InvitationOptionsData = z.infer<typeof invitationOptionsSchema>;
// Complete user creation payload
export const createUserSchema = z.object({
role: z.enum(["admin", "trainer", "client"]),
firstName: z.string().min(2).max(50),
lastName: z.string().min(2).max(50),
phone: z.string().optional(),
email: z.string().email(),
// Client-specific fields
membershipType: z.enum(["basic", "premium", "vip"]).optional(),
membershipStatus: z.enum(["active", "inactive", "suspended"]).optional(),
// Invitation options
sendInvitation: z.boolean(),
sendWelcomeEmail: z.boolean(),
gymId: z.string().optional(),
});
export type CreateUserData = z.infer<typeof createUserSchema>;
/**
* Helper function to validate and merge form data from all steps
*/
export function mergeUserCreationData(
roleData: RoleSelectionData,
basicInfo: BasicInfoData,
clientInfo?: ClientInfoData,
invitationOptions?: InvitationOptionsData,
): CreateUserData {
const merged: CreateUserData = {
role: roleData.role,
firstName: basicInfo.firstName,
lastName: basicInfo.lastName,
phone: basicInfo.phone || undefined,
email: basicInfo.email,
sendInvitation: false,
sendWelcomeEmail: false,
};
// Add client-specific data
if (roleData.role === "client" && clientInfo) {
merged.membershipType = clientInfo.membershipType;
merged.membershipStatus = clientInfo.membershipStatus;
merged.sendWelcomeEmail = clientInfo.sendWelcomeEmail;
}
// Add invitation options for admin/trainer
if (
(roleData.role === "admin" || roleData.role === "trainer") &&
invitationOptions
) {
merged.sendInvitation = invitationOptions.sendInvitation;
merged.gymId = invitationOptions.gymId;
}
return createUserSchema.parse(merged);
}