- 
- 
- 
This commit is contained in:
2026-05-18 18:31:16 +07:00
parent b599d01eea
commit c4efe4453b
36 changed files with 3057 additions and 1493 deletions
+70 -14
View File
@@ -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;