mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-25 20:50:14 -05:00
Team: Fetch from DB
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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)];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user