Team: Fetch from DB

This commit is contained in:
Kalle
2023-01-02 21:59:58 +02:00
parent 0caa90756a
commit 077e2356ae
5 changed files with 155 additions and 62 deletions

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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<Team, "id" | "name" | "twitter" | "bio" | "lutiDiv"> & {
avatarSrc: string;
bannerSrc: string;
countries: string;
})
| null;
type MemberRows = Array<
Pick<User, "discordName" | "discordAvatar" | "discordId"> &
Pick<TeamMember, "role"> & { 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,
// },
// ],
// },
};
}

View File

@@ -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() {
<InfoBadges />
</div>
<MobileTeamNameCountry />
{team.results ? <ResultsBanner results={team.results} /> : null}
{team.results ? <ResultsBanner results={team.results} /> : <div />}
<div className="stack lg">
{team.members.map((member) => (
<React.Fragment key={member.discordId}>

View File

@@ -45,3 +45,7 @@ export function normalizeFormFieldArray(
export function isDefined<T>(value: T | undefined | null): value is T {
return value !== null && value !== undefined;
}
export function removeDuplicates<T>(arr: T[]): T[] {
return [...new Set(arr)];
}