import { User, userRoles, users, type UserView } from "@/db/schema/users"; import { createSearchParamsCache, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, } from "nuqs/server" import * as z from "zod" import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" import { checkEmailExists } from "./service"; import { fallbackModeToStaticPathsResult } from "next/dist/lib/fallback"; export const searchParamsCache = createSearchParamsCache({ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault( [] ), page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), sort: getSortingStateParser().withDefault([ { id: "created_at", desc: true }, ]), email: parseAsString.withDefault(""), // advanced filter filters: getFiltersStateParser().withDefault([]), joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), search: parseAsString.withDefault(""), }) export const searchParamsUsersCache = createSearchParamsCache({ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault( [] ), page: parseAsInteger.withDefault(1), perPage: parseAsInteger.withDefault(10), sort: getSortingStateParser().withDefault([ { id: "createdAt", desc: true }, ]), email: parseAsString.withDefault(""), // advanced filter filters: getFiltersStateParser().withDefault([]), joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), search: parseAsString.withDefault(""), }) export const createUserSchema = z.object({ email: z .string() .email() .refine( async (email) => { // 1) DB 조회해서 이미 같은 email이 있으면 false 반환 const isUsed = await checkEmailExists(email); return !isUsed; }, { message: "This email is already in use", } ), name: z.string().min(1), // 최소 길이 1 domain: z.enum(users.domain.enumValues), // "evcp" | "partners" companyId: z.number().nullable().optional(), // number | null | undefined roles:z.array(z.string()).min(1, "At least one role must be selected"), language: z.enum(["ko", "en"]).optional(), phone: z .string() .refine( (phone) => { if (!phone) return false; // Optional field // Remove spaces, hyphens, and parentheses for validation const cleanPhone = phone.replace(/[\s\-\(\)]/g, ''); // Basic international phone number validation return /^\+\d{3,20}$/.test(cleanPhone); }, { message: "올바른 국제 전화번호 형식이 아닙니다. +로 시작하는 3-20자리 번호를 입력해주세요. (예: +82-10-1234-5678)" } ), // 전화번호 필드 추가 isActive: z.boolean().default(true), // 활성화 상태 필드 추가 country: z.string().optional(), // 국가 필드 (기존 코드 호환성) }); export const updateUserSchema = z.object({ name: z.string().optional(), email: z.string().email().optional(), domain: z.enum(users.domain.enumValues).optional(), companyId: z.number().nullable().optional(), roles: z.array(z.string()).optional(), language: z.enum(["ko", "en"]).optional(), phone: z .string() .refine( (phone) => { if (!phone) return false; // Optional field // Remove spaces, hyphens, and parentheses for validation const cleanPhone = phone.replace(/[\s\-\(\)]/g, ''); // Basic international phone number validation return /^\+\d{3,20}$/.test(cleanPhone); }, { message: "올바른 국제 전화번호 형식이 아닙니다. +로 시작하는 3-20자리 번호를 입력해주세요. (예: +82-10-1234-5678)" } ), // 전화번호 필드 추가 isActive: z.boolean().optional(), // 활성화 상태 필드 추가 }); export type GetUsersSchema = Awaited> export type GetSimpleUsersSchema = Awaited> export type CreateUserSchema = z.infer export type UpdateUserSchema = z.infer