summaryrefslogtreecommitdiff
path: root/lib/vendor-users/validations.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-users/validations.ts')
-rw-r--r--lib/vendor-users/validations.ts83
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/vendor-users/validations.ts b/lib/vendor-users/validations.ts
new file mode 100644
index 00000000..904bb41e
--- /dev/null
+++ b/lib/vendor-users/validations.ts
@@ -0,0 +1,83 @@
+import { 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";
+
+
+
+export const searchParamsVendorUserCache = createSearchParamsCache({
+ flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault(
+ []
+ ),
+ page: parseAsInteger.withDefault(1),
+ perPage: parseAsInteger.withDefault(10),
+ sort: getSortingStateParser<UserView>().withDefault([
+ { id: "created_at", desc: true },
+ ]),
+ email: parseAsString.withDefault(""),
+ // advanced filter
+ filters: getFiltersStateParser().withDefault([]),
+ joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
+ search: parseAsString.withDefault(""),
+
+})
+
+const phoneValidation = z
+ .string()
+ .optional()
+ .refine(
+ (phone) => {
+ if (!phone || phone.trim() === "") return true; // Optional field
+ // Remove spaces, hyphens, and parentheses for validation
+ const cleanPhone = phone.replace(/[\s\-\(\)]/g, '');
+ // Basic international phone number validation
+ return /^\+\d{10,15}$/.test(cleanPhone);
+ },
+ {
+ message: "올바른 국제 전화번호 형식이 아닙니다. +로 시작하는 10-15자리 번호를 입력해주세요. (예: +82 010-1234-5678)"
+ }
+ )
+
+export const createVendorUserSchema = 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
+ phone: phoneValidation,
+ 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(),
+
+});
+
+export const updateVendorUserSchema = z.object({
+ name: z.string().optional(),
+ email: z.string().email().optional(),
+ phone: phoneValidation,
+ domain: z.enum(users.domain.enumValues).optional(),
+ companyId: z.number().nullable().optional(),
+ roles: z.array(z.string()).optional(),
+ language: z.enum(["ko", "en"]).optional(),
+
+});
+export type GetVendorUsersSchema = Awaited<ReturnType<typeof searchParamsVendorUserCache.parse>>
+export type CreateVendorUserSchema = z.infer<typeof createVendorUserSchema>
+export type UpdateVendorUserSchema = z.infer<typeof updateVendorUserSchema>