Files
setrip/features/profile/schemas.ts
T

67 lines
1.8 KiB
TypeScript

import { z } from "zod/v4";
import { LIMITS } from "@/lib/limits";
import { VIBES } from "@/lib/vibe";
const optionalTrimmed = (max: number, label: string) =>
z.preprocess(
(val) => {
if (val == null) return undefined;
const s = String(val).trim();
return s === "" ? undefined : s;
},
z.string().max(max, `${label} maksimal ${max} karakter`).optional()
);
const interestSchema = z
.string()
.trim()
.min(2, "Minat minimal 2 karakter")
.max(
LIMITS.MAX_PROFILE_INTEREST_LENGTH,
`Setiap minat maksimal ${LIMITS.MAX_PROFILE_INTEREST_LENGTH} karakter`
)
.regex(
/^[a-zA-Z0-9 \-]+$/,
"Minat hanya boleh huruf, angka, spasi, atau strip"
);
export const updateProfileSchema = z.object({
bio: optionalTrimmed(LIMITS.MAX_PROFILE_BIO_LENGTH, "Bio"),
city: optionalTrimmed(LIMITS.MAX_PROFILE_CITY_LENGTH, "Kota"),
instagram: z.preprocess(
(val) => {
if (val == null) return undefined;
const s = String(val).trim().replace(/^@/, "");
return s === "" ? undefined : s;
},
z
.string()
.max(
LIMITS.MAX_PROFILE_INSTAGRAM_LENGTH,
`Instagram maksimal ${LIMITS.MAX_PROFILE_INSTAGRAM_LENGTH} karakter`
)
.regex(
/^[a-zA-Z0-9._]+$/,
"Username Instagram hanya boleh huruf, angka, titik, atau underscore"
)
.optional()
),
interests: z
.array(interestSchema)
.max(
LIMITS.MAX_PROFILE_INTERESTS_COUNT,
`Maksimal ${LIMITS.MAX_PROFILE_INTERESTS_COUNT} minat`
)
.default([]),
vibe: z.preprocess(
(val) => {
if (val == null) return undefined;
const s = String(val).trim();
return s === "" ? undefined : s;
},
z.enum([...VIBES]).optional()
),
});
export type UpdateProfileInput = z.infer<typeof updateProfileSchema>;