- ✅
- ✅ - ✅ - ✅
This commit is contained in:
+70
-14
@@ -7,6 +7,7 @@ import {
|
||||
isTripDepartureDayPast,
|
||||
tripStoredInstantFromYmd,
|
||||
} from "@/lib/trip-dates";
|
||||
import { isValidTimeFormat, timeToMinutes } from "@/lib/itinerary";
|
||||
|
||||
export const tripImageUrlsSchema = z
|
||||
.array(
|
||||
@@ -18,6 +19,75 @@ export const tripImageUrlsSchema = z
|
||||
)
|
||||
.max(LIMITS.MAX_IMAGE_URLS, `Maksimal ${LIMITS.MAX_IMAGE_URLS} foto`);
|
||||
|
||||
export const itineraryItemSchema = z
|
||||
.object({
|
||||
day: z.coerce
|
||||
.number()
|
||||
.int("Nomor hari tidak valid")
|
||||
.min(1, "Nomor hari minimal 1")
|
||||
.max(
|
||||
LIMITS.MAX_ITINERARY_DAYS,
|
||||
`Maksimal ${LIMITS.MAX_ITINERARY_DAYS} hari`
|
||||
),
|
||||
startTime: z
|
||||
.string()
|
||||
.trim()
|
||||
.refine(isValidTimeFormat, "Format jam mulai harus HH:mm"),
|
||||
endTime: z.preprocess(
|
||||
(val) => {
|
||||
if (val == null) return undefined;
|
||||
const s = String(val).trim();
|
||||
return s === "" ? undefined : s;
|
||||
},
|
||||
z
|
||||
.string()
|
||||
.refine(isValidTimeFormat, "Format jam selesai harus HH:mm")
|
||||
.optional()
|
||||
),
|
||||
activity: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, "Deskripsi aktivitas harus diisi")
|
||||
.max(
|
||||
LIMITS.MAX_ITINERARY_ACTIVITY_LENGTH,
|
||||
`Aktivitas maksimal ${LIMITS.MAX_ITINERARY_ACTIVITY_LENGTH} karakter`
|
||||
),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (
|
||||
data.endTime &&
|
||||
timeToMinutes(data.endTime) < timeToMinutes(data.startTime)
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: "Jam selesai tidak boleh sebelum jam mulai",
|
||||
path: ["endTime"],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export const itineraryItemsSchema = z
|
||||
.array(itineraryItemSchema)
|
||||
.max(
|
||||
LIMITS.MAX_ITINERARY_ITEMS,
|
||||
`Maksimal ${LIMITS.MAX_ITINERARY_ITEMS} aktivitas total`
|
||||
)
|
||||
.superRefine((items, ctx) => {
|
||||
if (items.length === 0) return;
|
||||
const days = [...new Set(items.map((i) => i.day))].sort((a, b) => a - b);
|
||||
for (let i = 0; i < days.length; i++) {
|
||||
if (days[i] !== i + 1) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message:
|
||||
"Nomor hari harus berurutan mulai dari Hari 1 (tidak boleh lompat)",
|
||||
path: [0, "day"],
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const createTripSchema = z
|
||||
.object({
|
||||
category: z.enum(
|
||||
@@ -105,20 +175,6 @@ export const createTripSchema = z
|
||||
)
|
||||
.optional()
|
||||
),
|
||||
itinerary: z.preprocess(
|
||||
(val) => {
|
||||
if (val == null) return undefined;
|
||||
const s = String(val).trim();
|
||||
return s === "" ? undefined : s;
|
||||
},
|
||||
z
|
||||
.string()
|
||||
.max(
|
||||
LIMITS.MAX_TRIP_ITINERARY_LENGTH,
|
||||
`Itinerary maksimal ${LIMITS.MAX_TRIP_ITINERARY_LENGTH} karakter`
|
||||
)
|
||||
.optional()
|
||||
),
|
||||
whatsIncluded: z.preprocess(
|
||||
(val) => {
|
||||
if (val == null) return undefined;
|
||||
|
||||
Reference in New Issue
Block a user