From cfc57c838e1934d53ebd07f0463208ab1f016513 Mon Sep 17 00:00:00 2001 From: Regalijan Date: Sat, 11 Apr 2026 03:30:46 -0400 Subject: [PATCH] More events team nonsense --- app/routes/events-calendar.tsx | 58 ++++---- app/routes/events-team_.events-breakdown.tsx | 71 ++++------ app/routes/events-team_.historical.tsx | 9 +- app/routes/events-team_.outstanding.tsx | 77 +++++++--- functions/api/events-team/events/[id].ts | 132 +++++++++++------- .../events-team/events/[id]/_middleware.ts | 11 +- .../api/events-team/events/[id]/certify.ts | 2 +- .../api/events-team/events/[id]/complete.ts | 22 +-- .../api/events-team/events/[id]/decision.ts | 27 ++-- .../api/events-team/events/[id]/forgotten.ts | 23 +-- functions/api/events-team/events/new.ts | 65 +++++---- functions/api/events-team/points/[id].ts | 11 +- functions/api/events-team/strikes/[id].ts | 8 +- functions/api/events-team/strikes/new.ts | 8 +- .../api/events-team/team-members/user.ts | 52 ++++--- functions/api/short-links/[[id]].ts | 29 ++-- functions/permissions.ts | 9 +- 17 files changed, 355 insertions(+), 259 deletions(-) diff --git a/app/routes/events-calendar.tsx b/app/routes/events-calendar.tsx index fc1530c..7518cb5 100644 --- a/app/routes/events-calendar.tsx +++ b/app/routes/events-calendar.tsx @@ -31,6 +31,7 @@ import { import { useLoaderData } from "@remix-run/react"; import { useState } from "react"; import utc from "dayjs/plugin/utc.js"; +import { EtMember } from "../../generated/prisma/client.js"; export const links: LinksFunction = () => { return [ @@ -56,18 +57,31 @@ export async function loader({ context }: { context: RequestContext }) { }); const now = new Date(); - const eventsData = await context.env.D1.prepare( - "SELECT answer, approved, created_by, day, details, id, month, pending, performed_at, reached_minimum_player_count, type, year FROM events WHERE month = ? AND year = ? ORDER BY day;", - ) - .bind(now.getUTCMonth() + 1, now.getUTCFullYear()) - .all(); + const eventsData = await context.data.prisma.event.findMany({ + orderBy: { + day: "asc", + }, + select: { + answer: true, + approved: true, + created_by: true, + day: true, + details: true, + id: true, + month: true, + pending: true, + performed_at: true, + reached_minimum_player_count: true, + type: true, + year: true, + }, + where: { + month: now.getUTCMonth() + 1, + year: now.getUTCFullYear(), + }, + }); - if (eventsData.error) - throw new Response(null, { - status: 500, - }); - - const calendarData = eventsData.results.map((e) => { + const calendarData = eventsData.map((e) => { return { id: e.id, title: (e.type as string).toUpperCase(), @@ -78,19 +92,17 @@ export async function loader({ context }: { context: RequestContext }) { }; }); - const memberData = await context.env.D1.prepare( - "SELECT id, name FROM et_members WHERE id IN (SELECT created_by FROM events WHERE month = ? AND year = ?);", - ) - .bind(now.getUTCMonth() + 1, now.getUTCFullYear()) - .all(); + const memberData = await context.data.prisma.$queryRaw< + EtMember[] + >`SELECT id, name FROM et_members WHERE id IN (SELECT created_by FROM events WHERE month = ${now.getUTCMonth() + 1} AND year = ${now.getUTCFullYear()});`; return { calendarData, canManage: Boolean( [1 << 4, 1 << 12].find((p) => context.data.current_user.permissions & p), ), - eventList: eventsData.results, - memberData: memberData.results, + eventList: eventsData, + memberData, }; } @@ -111,15 +123,7 @@ export default function () { Host - { - ( - data.memberData.find( - (m) => m.id === eventData.created_by, - ) as { - [k: string]: any; - } - )?.name - } + {data.memberData.find((m) => m.id === eventData.created_by)?.name}
Event Type diff --git a/app/routes/events-team_.events-breakdown.tsx b/app/routes/events-team_.events-breakdown.tsx index d6c60df..3476b83 100644 --- a/app/routes/events-team_.events-breakdown.tsx +++ b/app/routes/events-team_.events-breakdown.tsx @@ -25,14 +25,13 @@ export async function loader({ context }: { context: RequestContext }) { status: 403, }); - const memberResults = await context.env.D1.prepare( - "SELECT id, name FROM et_members;", - ).all(); - - if (!memberResults.success) - throw new Response(null, { - status: 500, - }); + const { prisma } = context.data; + const memberResults = await prisma.etMember.findMany({ + select: { + id: true, + name: true, + }, + }); const data: { [k: string]: { @@ -45,7 +44,7 @@ export async function loader({ context }: { context: RequestContext }) { }; } = {}; - for (const row of memberResults.results as Record[]) { + for (const row of memberResults) { data[row.id].fotd = 0; data[row.id].gamenight = 0; data[row.id].name = row.name; @@ -53,22 +52,26 @@ export async function loader({ context }: { context: RequestContext }) { data[row.id].qotd = 0; } - const eventsResult = await context.env.D1.prepare( - "SELECT answered_at, created_by, day, month, performed_at, reached_minimum_player_count, type, year FROM events;", - ).all(); + const eventsResult = await prisma.event.findMany({ + select: { + answered_at: true, + created_by: true, + day: true, + month: true, + performed_at: true, + reached_minimum_player_count: true, + type: true, + year: true, + }, + }); - if (!eventsResult.success) - throw new Response(null, { - status: 500, - }); - - for (const row of eventsResult.results) { - const creator = row.created_by as string; - const type = row.type as string; + for (const row of eventsResult) { + const creator = row.created_by; + const type = row.type; if (!data[creator]) continue; - if (row.performed_at) data[creator][type as string] += 10; + if (row.performed_at) data[creator][type] += 10; else { const now = new Date(); const currentYear = now.getUTCFullYear(); @@ -76,33 +79,17 @@ export async function loader({ context }: { context: RequestContext }) { const currentDay = now.getUTCDate(); if ( - (row.year as number) < currentYear || - (currentYear === row.year && currentMonth > (row.month as number)) || + row.year < currentYear || + (currentYear === row.year && currentMonth > row.month) || (currentMonth === row.month && currentYear === row.year && - (row.day as number) < currentDay) + row.day < currentDay) ) data[creator][type] -= 5; } - switch (row.type) { - case "gamenight": - if (row.reached_minimum_player_count) data[creator].gamenight += 10; - - break; - - case "rotw": - if ( - (row.answered_at as number) - (row.performed_at as number) >= - 86400000 - ) - data[creator].rotw += 10; - - break; - - default: - break; - } + if (row.type === "gamenight" && row.reached_minimum_player_count) + data[creator].gamenight += 10; } return data; diff --git a/app/routes/events-team_.historical.tsx b/app/routes/events-team_.historical.tsx index a8aec15..75d5e88 100644 --- a/app/routes/events-team_.historical.tsx +++ b/app/routes/events-team_.historical.tsx @@ -44,9 +44,12 @@ export async function loader({ context }: { context: RequestContext }) { status: 403, }); - return ( - await context.env.D1.prepare("SELECT id, name FROM et_members;").all() - ).results; + return await context.data.prisma.etMember.findMany({ + select: { + id: true, + name: true, + }, + }); } export default function () { diff --git a/app/routes/events-team_.outstanding.tsx b/app/routes/events-team_.outstanding.tsx index caa315e..ed663e1 100644 --- a/app/routes/events-team_.outstanding.tsx +++ b/app/routes/events-team_.outstanding.tsx @@ -37,14 +37,40 @@ export async function loader({ context }: { context: RequestContext }) { year--; } - const data = await context.env.D1.prepare( - "SELECT day, details, id FROM events WHERE approved = 1 AND month = ? AND year = ? AND (performed_at IS NULL OR (reached_minimum_player_count = 0 AND type = 'gamenight')) ORDER BY day;", - ) - .bind(month, year) - .all(); + const data = await context.data.prisma.event.findMany({ + orderBy: { + day: "asc", + }, + select: { + answered_at: true, + day: true, + details: true, + id: true, + performed_at: true, + reached_minimum_player_count: true, + type: true, + }, + where: { + AND: { + approved: true, + month, + year, + OR: [ + { + AND: [ + { + reached_minimum_player_count: false, + type: "gamenight", + }, + ], + }, + ], + }, + }, + }); return { - events: data.results as Record[], + events: data, past_cutoff: now.getUTCDate() > 7, }; } @@ -52,7 +78,7 @@ export async function loader({ context }: { context: RequestContext }) { export default function () { const { events, past_cutoff } = useLoaderData(); const { isOpen, onClose, onOpen } = useDisclosure(); - const [eventData, setEventData] = useState({} as { [k: string]: any }); + const [eventData, setEventData] = useState({} as (typeof events)[number]); const [isBrowserSupported, setIsBrowserSupported] = useState(true); const toast = useToast(); @@ -74,10 +100,10 @@ export default function () { }); } - function getStatus(event: { [k: string]: string | number }) { + function getStatus(event: (typeof events)[number]) { if (!event.performed_at) return "Approved"; if (event.type === "rotw" && event.answered_at) return "Solved"; - if (event.type === "gamenight" && event.areached_minimum_player_count) + if (event.type === "gamenight" && event.reached_minimum_player_count) return "Certified"; return "Completed"; @@ -106,7 +132,7 @@ export default function () { }); const newData = structuredClone(eventData); - newData.reached_minimum_player_count = 1; + newData.reached_minimum_player_count = true; setEventData(newData); } @@ -134,9 +160,12 @@ export default function () { }); const newData = structuredClone(eventData); - newData.performed_at = Date.now(); - setEventData(newData); + setEventData( + Object.defineProperty(newData, "performed_at", { + value: new Date().toISOString(), + }), + ); } async function forgotten() { @@ -162,9 +191,12 @@ export default function () { }); const newData = structuredClone(eventData); - newData.performed_at = 0; - setEventData(newData); + setEventData( + Object.defineProperty(newData, "performed_at", { + value: new Date().toISOString(), + }), + ); } async function solve() { @@ -190,9 +222,12 @@ export default function () { }); const newData = structuredClone(eventData); - newData.answered_at = Date.now(); - setEventData(newData); + setEventData( + Object.defineProperty(newData, "performed_at", { + value: new Date().toISOString(), + }), + ); } return ( @@ -216,13 +251,13 @@ export default function () { Completion