Validate only one date per tournament

This commit is contained in:
Kalle 2024-01-13 11:37:04 +02:00
parent 235448527d
commit c637ade5ec
3 changed files with 70 additions and 48 deletions

View File

@ -93,58 +93,75 @@ export const meta: MetaFunction = (args) => {
return [{ title: data.title }];
};
const newCalendarEventActionSchema = z.object({
eventToEditId: z.preprocess(actualNumber, id.nullish()),
name: z
.string()
.min(CALENDAR_EVENT.NAME_MIN_LENGTH)
.max(CALENDAR_EVENT.NAME_MAX_LENGTH),
description: z.preprocess(
falsyToNull,
z.string().max(CALENDAR_EVENT.DESCRIPTION_MAX_LENGTH).nullable(),
),
date: z.preprocess(
toArray,
z
.array(z.preprocess(date, z.date().min(MIN_DATE).max(MAX_DATE)))
.min(1)
.max(CALENDAR_EVENT.MAX_AMOUNT_OF_DATES),
),
bracketUrl: z
.string()
.url()
.max(CALENDAR_EVENT.BRACKET_URL_MAX_LENGTH)
.default("https://sendou.ink"),
discordInviteCode: z.preprocess(
falsyToNull,
z.string().max(CALENDAR_EVENT.DISCORD_INVITE_CODE_MAX_LENGTH).nullable(),
),
tags: z.preprocess(
processMany(safeJSONParse, removeDuplicates),
z
.array(
z
.string()
.refine((val) =>
CALENDAR_EVENT.TAGS.includes(val as CalendarEventTag),
),
)
.nullable(),
),
badges: z.preprocess(
processMany(safeJSONParse, removeDuplicates),
z.array(id).nullable(),
),
pool: z.string().optional(),
toToolsEnabled: z.preprocess(checkboxValueToBoolean, z.boolean()),
toToolsMode: z.enum(["ALL", "SZ", "TC", "RM", "CB"]).optional(),
});
const newCalendarEventActionSchema = z
.object({
eventToEditId: z.preprocess(actualNumber, id.nullish()),
name: z
.string()
.min(CALENDAR_EVENT.NAME_MIN_LENGTH)
.max(CALENDAR_EVENT.NAME_MAX_LENGTH),
description: z.preprocess(
falsyToNull,
z.string().max(CALENDAR_EVENT.DESCRIPTION_MAX_LENGTH).nullable(),
),
date: z.preprocess(
toArray,
z
.array(z.preprocess(date, z.date().min(MIN_DATE).max(MAX_DATE)))
.min(1)
.max(CALENDAR_EVENT.MAX_AMOUNT_OF_DATES),
),
bracketUrl: z
.string()
.url()
.max(CALENDAR_EVENT.BRACKET_URL_MAX_LENGTH)
.default("https://sendou.ink"),
discordInviteCode: z.preprocess(
falsyToNull,
z.string().max(CALENDAR_EVENT.DISCORD_INVITE_CODE_MAX_LENGTH).nullable(),
),
tags: z.preprocess(
processMany(safeJSONParse, removeDuplicates),
z
.array(
z
.string()
.refine((val) =>
CALENDAR_EVENT.TAGS.includes(val as CalendarEventTag),
),
)
.nullable(),
),
badges: z.preprocess(
processMany(safeJSONParse, removeDuplicates),
z.array(id).nullable(),
),
pool: z.string().optional(),
toToolsEnabled: z.preprocess(checkboxValueToBoolean, z.boolean()),
toToolsMode: z.enum(["ALL", "SZ", "TC", "RM", "CB"]).optional(),
})
.refine(
async (schema) => {
if (schema.eventToEditId) {
const eventToEdit = await CalendarRepository.findById({
id: schema.eventToEditId,
});
return schema.date.length === 1 || !eventToEdit?.tournamentId;
} else {
return schema.date.length === 1 || !schema.toToolsEnabled;
}
},
{
message: "Tournament must have exactly one date",
},
);
export const action: ActionFunction = async ({ request }) => {
const user = await requireUser(request);
const data = await parseRequestFormData({
request,
schema: newCalendarEventActionSchema,
parseAsync: true,
});
validate(canAddNewEvent(user), "Not authorized", 401);

View File

@ -10,7 +10,6 @@ export async function findById(id: number) {
const row = await db
.selectFrom("Tournament")
.innerJoin("CalendarEvent", "Tournament.id", "CalendarEvent.tournamentId")
// TODO: it does not support multiple dates
.innerJoin(
"CalendarEventDate",
"CalendarEvent.id",

View File

@ -47,12 +47,18 @@ export function parseSearchParams<T extends z.ZodTypeAny>({
export async function parseRequestFormData<T extends z.ZodTypeAny>({
request,
schema,
parseAsync,
}: {
request: Request;
schema: T;
parseAsync?: boolean;
}): Promise<z.infer<T>> {
try {
return schema.parse(formDataToObject(await request.formData()));
const parsed = parseAsync
? await schema.parseAsync(formDataToObject(await request.formData()))
: schema.parse(formDataToObject(await request.formData()));
return parsed;
} catch (e) {
if (e instanceof z.ZodError) {
console.error(e);