mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-02 08:07:40 -05:00
Saves winners to DB
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user