Saves winners to DB

This commit is contained in:
Kalle
2022-08-06 18:42:56 +03:00
parent f29ca201e8
commit 6a649efc06
3 changed files with 90 additions and 12 deletions

View File

@@ -7,6 +7,7 @@ import type {
Badge,
CalendarEventTag,
CalendarEventBadge,
CalendarEventWinner,
} from "../types";
const createStm = sql.prepare(`
@@ -130,6 +131,53 @@ export const update = sql.transaction(
}
);
const updateCalendarEventParticipantsCountStm = sql.prepare(`
update "CalendarEvent"
set "participantCount" = $participantCount
where "id" = $eventId
`);
const deleteCalendarEventWinnersByEventIdStm = sql.prepare(`
delete from "CalendarEventWinner"
where "eventId" = $eventId
`);
const insertCalendarEventWinnerStm = sql.prepare(`
insert into "CalendarEventWinner" (
"eventId",
"teamName",
"placement",
"userId",
"name"
) values (
$eventId,
$teamName,
$placement,
$userId,
$name
)
`);
export const upsertReportedScores = sql.transaction(
({
eventId,
participantCount,
winners,
}: {
eventId: CalendarEvent["id"];
participantCount: CalendarEvent["participantCount"];
winners: Array<
Pick<CalendarEventWinner, "teamName" | "placement" | "userId" | "name">
>;
}) => {
updateCalendarEventParticipantsCountStm.run({ eventId, participantCount });
deleteCalendarEventWinnersByEventIdStm.run({ eventId });
for (const winner of winners) {
insertCalendarEventWinnerStm.run({ ...winner, eventId });
}
}
);
const findAllBetweenTwoTimestampsStm = sql.prepare(`
select
"CalendarEvent"."name",

View File

@@ -82,18 +82,36 @@ const reportWinnersActionSchema = z.object({
),
});
export const action: ActionFunction = async ({ request }) => {
const data = await safeParseRequestFormData({
const reportWinnersParamsSchema = z.object({
id: z.preprocess(actualNumber, id),
});
export const action: ActionFunction = async ({ request, params }) => {
const parsedParams = reportWinnersParamsSchema.parse(params);
const parsedInput = await safeParseRequestFormData({
request,
schema: reportWinnersActionSchema,
});
if (!data.success) {
if (!parsedInput.success) {
return {
errors: data.error.errors.map((error) => error.message),
errors: parsedInput.errors,
};
}
db.calendarEvents.upsertReportedScores({
eventId: parsedParams.id,
participantCount: parsedInput.data.participantsCount,
winners: parsedInput.data.team.flatMap((t) =>
t.players.map((player) => ({
teamName: t.teamName,
placement: t.placement,
userId: typeof player !== "string" ? player.id : null,
name: typeof player === "string" ? player : null,
}))
),
});
return null;
};
@@ -102,9 +120,7 @@ export const handle = {
};
export const loader = async ({ request, params }: LoaderArgs) => {
const parsedParams = z
.object({ id: z.preprocess(actualNumber, id) })
.parse(params);
const parsedParams = reportWinnersParamsSchema.parse(params);
const user = await requireUser(request);
const event = notFoundIfFalsy(db.calendarEvents.findById(parsedParams.id));
@@ -267,8 +283,7 @@ function Team({
id={teamNameId}
value={results.teamName}
onChange={handleTeamNameChange}
// xxx: why doesn't work?
minLength={1}
required={!hidden}
maxLength={CALENDAR_EVENT_RESULT.MAX_TEAM_NAME_LENGTH}
/>
</div>
@@ -279,7 +294,7 @@ function Team({
value={results.placement}
type="number"
onChange={handlePlacementChange}
min={1}
required={!hidden}
max={CALENDAR_EVENT_RESULT.MAX_TEAM_PLACEMENT}
className="w-24"
/>

View File

@@ -44,8 +44,23 @@ export async function safeParseRequestFormData<T extends z.ZodTypeAny>({
}: {
request: Request;
schema: T;
}): Promise<z.SafeParseReturnType<z.infer<T>, T>> {
return schema.safeParse(formDataToObject(await request.formData()));
}): Promise<
{ success: true; data: z.infer<T> } | { success: false; errors: string[] }
> {
const parsed = schema.safeParse(formDataToObject(await request.formData()));
// this implementation is somewhat redundant but it's the only way I got types to work nice
if (!parsed.success) {
return {
success: false,
errors: parsed.error.errors.map((error) => error.message),
};
}
return {
success: true,
data: parsed.data,
};
}
function formDataToObject(formData: FormData) {