From 077e2356aec8ab9821dc537c11fcec97bd92aa3e Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Mon, 2 Jan 2023 21:59:58 +0200 Subject: [PATCH] Team: Fetch from DB --- app/db/seed.ts | 61 +++++++- app/db/types.ts | 3 +- .../team/queries/findByIdentifier.server.ts | 137 +++++++++++------- app/features/team/routes/t.$customUrl.tsx | 12 +- app/utils/arrays.ts | 4 + 5 files changed, 155 insertions(+), 62 deletions(-) diff --git a/app/db/seed.ts b/app/db/seed.ts index 86bf4b4d5..d2fba6881 100644 --- a/app/db/seed.ts +++ b/app/db/seed.ts @@ -55,6 +55,7 @@ const basicSeeds = [ calendarEventWithToToolsTeams, adminBuilds, manySplattershotBuilds, + detailedTeam, ]; export function seed() { @@ -67,6 +68,9 @@ export function seed() { function wipeDB() { const tablesToDelete = [ + "UserSubmittedImage", + "TeamMember", + "Team", "Build", "TournamentTeamMember", "MapPoolMap", @@ -386,15 +390,15 @@ function patrons() { } } -function userIdsInRandomOrder(adminLast = false) { +function userIdsInRandomOrder(specialLast = false) { const rows = sql .prepare(`select "id" from "User" order by random()`) .all() .map((u) => u.id) as number[]; - if (!adminLast) return rows; + if (!specialLast) return rows; - return [...rows.filter((id) => id !== 1), 1]; + return [...rows.filter((id) => id !== 1 && id !== 2), 1, 2]; } function calendarEvents() { @@ -868,3 +872,54 @@ function manySplattershotBuilds() { }); } } + +function detailedTeam() { + sql + .prepare( + /* sql */ ` + insert into "UserSubmittedImage" ("validatedAt", "url") + values + (1672587342, 'https://abload.de/img/ryri0cnc_400x4005qcyx.jpeg'), + (1672587342, 'https://abload.de/img/fjkfa-uxkamgdbxr3iqn.jpeg') + ` + ) + .run(); + + sql + .prepare( + /* sql */ ` + insert into "Team" ("name", "customUrl", "inviteCode", "twitter", "bio", "lutiDiv", "avatarImgId", "bannerImgId") + values ( + 'Alliance Rogue', + 'alliance-rogue', + '${nanoid(INVITE_CODE_LENGTH)}', + 'AllianceRogueFR', + '${faker.lorem.paragraph()}', + 'X', + 1, + 2 + ) + ` + ) + .run(); + + const userIds = userIdsInRandomOrder(true); + for (let i = 0; i < 5; i++) { + const userId = i <= 1 ? i + 1 : userIds.shift()!; + + sql + .prepare( + /*sql*/ ` + insert into "TeamMember" ("teamId", "userId", "role", "isOwner", "leftAt") + values ( + 1, + ${userId}, + ${i === 0 ? "'CAPTAIN'" : "'FRONTLINE'"}, + ${i === 0 ? 1 : 0}, + ${i < 4 ? "null" : "1672587342"} + ) + ` + ) + .run(); + } +} diff --git a/app/db/types.ts b/app/db/types.ts index cc1d39b3a..43bc2c2d7 100644 --- a/app/db/types.ts +++ b/app/db/types.ts @@ -247,6 +247,7 @@ export interface Team { name: string; customUrl: string; inviteCode: string; + twitter: string | null; bio: string | null; lutiDiv: string | null; avatarImgId: number | null; @@ -266,7 +267,7 @@ export interface TeamMember { teamId: number; userId: number; role: MemberRole | null; - isCaptain: number; + isOwner: number; createdAt: number; leftAt: number | null; } diff --git a/app/features/team/queries/findByIdentifier.server.ts b/app/features/team/queries/findByIdentifier.server.ts index 14db11fc8..71b2c86df 100644 --- a/app/features/team/queries/findByIdentifier.server.ts +++ b/app/features/team/queries/findByIdentifier.server.ts @@ -1,57 +1,90 @@ +import { sql } from "~/db/sql"; +import type { Team, TeamMember, User } from "~/db/types"; +import { removeDuplicates } from "~/utils/arrays"; import type { DetailedTeam } from "../team-types"; -export function findByIdentifier(/*customUrl: string*/): DetailedTeam | null { +const teamStm = sql.prepare(/*sql*/ ` + select + "t"."id", + "t"."name", + "t"."twitter", + "t"."bio", + "t"."lutiDiv", + "ia"."url" as "avatarSrc", + "ib"."url" as "bannerSrc", + json_group_array("User"."country") as "countries" + from "Team" as "t" + left join "UserSubmittedImage" as "ia" on "avatarImgId" = "ia"."id" and "ia"."validatedAt" is not null + left join "UserSubmittedImage" as "ib" on "bannerImgId" = "ib"."id" and "ib"."validatedAt" is not null + left join "TeamMember" on "TeamMember"."teamId" = "t"."id" + left join "User" on "User"."id" = "TeamMember"."userId" + where "t"."customUrl" = @customUrl + group by "t"."id" +`); + +const membersStm = sql.prepare(/*sql*/ ` + select + "User"."discordName", + "User"."discordAvatar", + "User"."discordId", + "TeamMember"."role", + json_group_array("UserWeapon"."weaponSplId") as "weapons" + from "TeamMember" + join "User" on "User"."id" = "TeamMember"."userId" + left join "UserWeapon" on "UserWeapon"."userId" = "User"."id" + where "TeamMember"."teamId" = @teamId + group by "User"."id" +`); + +type TeamRow = + | (Pick & { + avatarSrc: string; + bannerSrc: string; + countries: string; + }) + | null; + +type MemberRows = Array< + Pick & + Pick & { weapons: string } +>; + +export function findByIdentifier(customUrl: string): DetailedTeam | null { + const team = teamStm.get({ customUrl }) as TeamRow; + + if (!team) return null; + + const members = membersStm.all({ teamId: team.id }) as MemberRows; + return { - countries: ["FR", "US"], - name: "Alliance Rogue", - lutiDiv: "X", - teamXp: "2981.2", - twitter: "AllianceRogueFR", - avatarSrc: - "https://pbs.twimg.com/profile_images/1567529215523786754/RYRI0cNc_400x400.jpg", - bannerSrc: "https://abload.de/img/fjkfa-uxkamgdbxr3iqn.jpeg", - members: [ - { - discordName: "Kiver", - discordAvatar: "2ce2f7e4fe6cd2aeceec940ecebcb22c", - discordId: "92909500100513792", - role: "FRONTLINE", - weapons: [40, 20, 210, 1000, 1010], - }, - { - discordName: "Scar", - discordAvatar: "fcf2508d5bc21046108a19d26cafce31", - discordId: "129931199383601153", - role: "FRONTLINE", - weapons: [20, 3020], - }, - { - discordName: "Grey", - discordAvatar: "a_ce66d041d5bde589099ebc68ecf74da0", - discordId: "99931397451419648", - role: "SUPPORT", - weapons: [20, 10, 1030], - }, - { - discordName: "Jay", - discordAvatar: "fbafa57c8b571378806c743dcad6a067", - discordId: "273503438124613632", - role: "BACKLINE", - weapons: [2040], - }, - ], - results: { - count: 23, - placements: [ - { - count: 10, - placement: 1, - }, - { - count: 5, - placement: 2, - }, - ], - }, + name: team.name, + twitter: team.twitter ?? undefined, + bio: team.bio ?? undefined, + lutiDiv: team.lutiDiv ?? undefined, + teamXp: undefined, + avatarSrc: team.avatarSrc, + bannerSrc: team.bannerSrc, + countries: removeDuplicates(JSON.parse(team.countries).filter(Boolean)), + members: members.map((member) => ({ + discordAvatar: member.discordAvatar, + discordId: member.discordId, + discordName: member.discordName, + role: member.role ?? undefined, + weapons: JSON.parse(member.weapons).filter(Boolean), + })), + results: undefined, + // results: { + // count: 23, + // placements: [ + // { + // count: 10, + // placement: 1, + // }, + // { + // count: 5, + // placement: 2, + // }, + // ], + // }, }; } diff --git a/app/features/team/routes/t.$customUrl.tsx b/app/features/team/routes/t.$customUrl.tsx index 575e27270..65e2cf0b8 100644 --- a/app/features/team/routes/t.$customUrl.tsx +++ b/app/features/team/routes/t.$customUrl.tsx @@ -1,6 +1,6 @@ import type { LinksFunction, - // LoaderArgs, + LoaderArgs, MetaFunction, SerializeFrom, } from "@remix-run/node"; @@ -12,7 +12,7 @@ import { notFoundIfFalsy } from "~/utils/remix"; import { makeTitle } from "~/utils/strings"; import { navIconUrl, userPage } from "~/utils/urls"; import { findByIdentifier } from "../queries/findByIdentifier.server"; -// import { teamParamsSchema } from "../team-schemas.server"; +import { teamParamsSchema } from "../team-schemas.server"; import { Placement } from "~/components/Placement"; import styles from "../team.css"; import type { DetailedTeamMember, TeamResultPeek } from "../team-types"; @@ -48,10 +48,10 @@ export const handle: SendouRouteHandle = { // }), }; -export const loader = (/*{ params }: LoaderArgs*/) => { - // const { customUrl } = teamParamsSchema.parse(params); +export const loader = ({ params }: LoaderArgs) => { + const { customUrl } = teamParamsSchema.parse(params); - const team = notFoundIfFalsy(findByIdentifier(/*customUrl*/)); + const team = notFoundIfFalsy(findByIdentifier(customUrl.toLowerCase())); return { team }; }; @@ -66,7 +66,7 @@ export default function TeamPage() { - {team.results ? : null} + {team.results ? :
}
{team.members.map((member) => ( diff --git a/app/utils/arrays.ts b/app/utils/arrays.ts index 2ab5b0efd..bfceac172 100644 --- a/app/utils/arrays.ts +++ b/app/utils/arrays.ts @@ -45,3 +45,7 @@ export function normalizeFormFieldArray( export function isDefined(value: T | undefined | null): value is T { return value !== null && value !== undefined; } + +export function removeDuplicates(arr: T[]): T[] { + return [...new Set(arr)]; +}