From d51beef9d5d30f90f47590c5a7414c9b837bdf8a Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Tue, 27 Dec 2022 22:01:15 +0200 Subject: [PATCH] Team: UI initial --- app/db/types.ts | 37 ++++ .../team/queries/findByIdentifier.server.ts | 57 ++++++ app/features/team/routes/t.$customUrl.tsx | 184 ++++++++++++++++++ app/features/team/team-schemas.server.ts | 3 + app/features/team/team-types.ts | 33 ++++ app/features/team/team.css | 136 +++++++++++++ app/root.tsx | 1 + app/styles/vars.css | 3 + public/locales/en/team.json | 7 + public/static-assets/img/layout/xsearch.avif | Bin 0 -> 3746 bytes public/static-assets/img/layout/xsearch.png | Bin 0 -> 20408 bytes remix.config.js | 1 + types/react-i18next.d.ts | 2 + 13 files changed, 464 insertions(+) create mode 100644 app/features/team/queries/findByIdentifier.server.ts create mode 100644 app/features/team/routes/t.$customUrl.tsx create mode 100644 app/features/team/team-schemas.server.ts create mode 100644 app/features/team/team-types.ts create mode 100644 app/features/team/team.css create mode 100644 public/locales/en/team.json create mode 100644 public/static-assets/img/layout/xsearch.avif create mode 100644 public/static-assets/img/layout/xsearch.png diff --git a/app/db/types.ts b/app/db/types.ts index 94374f310..cc1d39b3a 100644 --- a/app/db/types.ts +++ b/app/db/types.ts @@ -233,3 +233,40 @@ export interface TournamentMatchGameResult { reporterId: number; createdAt: number; } + +/** TODO: incomplete team tables */ + +export interface UserSubmittedImage { + id: number; + validatedAt: number | null; + url: string; +} + +export interface Team { + id: number; + name: string; + customUrl: string; + inviteCode: string; + bio: string | null; + lutiDiv: string | null; + avatarImgId: number | null; + bannerImgId: number | null; + createdAt: number; + deletedAt: number | null; +} + +export type MemberRole = + | "CAPTAIN" + | "FRONTLINE" + | "SUPPORT" + | "BACKLINE" + | "COACH"; + +export interface TeamMember { + teamId: number; + userId: number; + role: MemberRole | null; + isCaptain: number; + createdAt: number; + leftAt: number | null; +} diff --git a/app/features/team/queries/findByIdentifier.server.ts b/app/features/team/queries/findByIdentifier.server.ts new file mode 100644 index 000000000..ceb526523 --- /dev/null +++ b/app/features/team/queries/findByIdentifier.server.ts @@ -0,0 +1,57 @@ +import type { DetailedTeam } from "../team-types"; + +export function findByIdentifier(customUrl: string): DetailedTeam | null { + return { + countries: ["FR"], + 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], + }, + { + 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, + }, + ], + }, + }; +} diff --git a/app/features/team/routes/t.$customUrl.tsx b/app/features/team/routes/t.$customUrl.tsx new file mode 100644 index 000000000..b29b0dd23 --- /dev/null +++ b/app/features/team/routes/t.$customUrl.tsx @@ -0,0 +1,184 @@ +import type { + LinksFunction, + LoaderArgs, + MetaFunction, + SerializeFrom, +} from "@remix-run/node"; +import { Link, useLoaderData } from "@remix-run/react"; +import { Image, WeaponImage } from "~/components/Image"; +import { Main } from "~/components/Main"; +import type { SendouRouteHandle } from "~/utils/remix"; +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 { Placement } from "~/components/Placement"; +import styles from "../team.css"; +import type { DetailedTeamMember } from "../team-types"; +import { Avatar } from "~/components/Avatar"; +import { useTranslation } from "~/hooks/useTranslation"; + +export const meta: MetaFunction = ({ + data, +}: { + data: SerializeFrom; +}) => { + if (!data) return {}; + + return { + title: makeTitle(data.team.name), + description: data.team.bio, + }; +}; + +export const links: LinksFunction = () => { + return [{ rel: "stylesheet", href: styles }]; +}; + +export const handle: SendouRouteHandle = { + i18n: ["team"], + // breadcrumb: () => ({ + // imgPath: navIconUrl("object-damage-calculator"), + // href: OBJECT_DAMAGE_CALCULATOR_URL, + // type: "IMAGE", + // }), +}; + +export const loader = ({ params }: LoaderArgs) => { + const { customUrl } = teamParamsSchema.parse(params); + + const team = notFoundIfFalsy(findByIdentifier(customUrl)); + + return { team }; +}; + +export default function TeamPage() { + const { team } = useLoaderData(); + + return ( +
+
+ + +
+ +
+ {team.members.map((member) => ( + + ))} +
+
+ ); +} + +function TeamBanner() { + const { team } = useLoaderData(); + + return ( +
+ {team.avatarSrc ? ( +
+
+ +
+
+ ) : null} +
+ {/* xxx: map to real flags */} + Flag of Finland +
+
{team.name}
+
+ ); +} + +function InfoBadges() { + const { team } = useLoaderData(); + + return ( +
+ {team.teamXp ? ( +
+ Team XP + {team.teamXp} +
+ ) : null} + {team.lutiDiv ?
LUTI Div {team.lutiDiv}
: null} +
+ ); +} + +function ResultsBanner() { + const { team } = useLoaderData(); + + if (!team.results) return null; + + return ( + +
View {team.results.count} results
+
    + {team.results.placements.map(({ placement, count }) => { + return ( +
  • + ×{count} +
  • + ); + })} +
+ + ); +} + +function MemberRow({ member }: { member: DetailedTeamMember }) { + const { t } = useTranslation(["team"]); + + return ( +
+ {member.role ? ( + + {t(`team:roles.${member.role}`)} + + ) : null} +
+ +
+ +
+ {member.discordName} + +
+ {member.weapons.map((weapon) => ( + + ))} +
+
+
+ ); +} diff --git a/app/features/team/team-schemas.server.ts b/app/features/team/team-schemas.server.ts new file mode 100644 index 000000000..12a628c79 --- /dev/null +++ b/app/features/team/team-schemas.server.ts @@ -0,0 +1,3 @@ +import { z } from "zod"; + +export const teamParamsSchema = z.object({ customUrl: z.string() }); diff --git a/app/features/team/team-types.ts b/app/features/team/team-types.ts new file mode 100644 index 000000000..31fcd41f1 --- /dev/null +++ b/app/features/team/team-types.ts @@ -0,0 +1,33 @@ +import type { MemberRole } from "~/db/types"; +import type { MainWeaponId } from "~/modules/in-game-lists"; + +export interface DetailedTeam { + name: string; + bio?: string; + twitter?: string; + lutiDiv?: string; + avatarSrc?: string; + bannerSrc?: string; + teamXp?: string; + countries: string[]; + members: DetailedTeamMember[]; + results?: TeamResultPeek; +} + +export interface DetailedTeamMember { + discordName: string; + discordId: string; + discordAvatar: string | null; + weapons: MainWeaponId[]; + role?: MemberRole; +} + +export interface TeamResultPeek { + count: number; + placements: Array; +} + +export interface TeamResultPeekPlacement { + placement: number; + count: number; +} diff --git a/app/features/team/team.css b/app/features/team/team.css new file mode 100644 index 000000000..b15d9f20f --- /dev/null +++ b/app/features/team/team.css @@ -0,0 +1,136 @@ +.team__banner { + background-image: linear-gradient( + to bottom, + rgba(255, 255, 255, 0), + rgba(255, 255, 255, 0), + rgba(0, 0, 0, 0.6) + ), + var(--team-banner-img); + background-size: cover; + width: 100%; + aspect-ratio: 2 / 1; + border-radius: var(--rounded); + display: grid; + grid-template-areas: "flags ." "avatar name"; + padding: var(--s-5); +} + +.team__banner__flags { + grid-area: flags; + margin-top: -5px; +} + +.team__banner__name { + grid-area: name; + align-self: flex-end; + justify-self: flex-end; + font-size: 36px; + line-height: 1; + font-weight: var(--bold); + color: #fff; +} + +.team__banner__avatar { + grid-area: avatar; + align-self: flex-end; + margin-bottom: -90px; + margin-left: var(--s-2); +} + +.team__banner__avatar > div { + padding: var(--s-2); + background-color: var(--bg); + border-radius: 100%; + aspect-ratio: 1 / 1; + display: grid; + place-items: center; + width: 10rem; +} + +.team__banner__avatar img { + border-radius: 100%; +} + +.team__badges { + display: flex; + justify-content: flex-end; + display: flex; + gap: var(--s-3); +} + +.team__badges > div { + background-color: var(--theme-semi-transparent); + border-radius: var(--rounded); + font-size: var(--fonts-xs); + padding-inline: var(--s-2); + font-weight: var(--bold); + display: flex; + align-items: center; + gap: var(--s-1-5); +} + +.team__results { + background-color: var(--bg-lightest); + max-width: 32rem; + margin: 0 auto; + border-radius: var(--rounded); + padding: var(--s-1) var(--s-4); + font-weight: var(--bold); + font-size: var(--fonts-sm); + display: flex; + justify-content: space-between; + width: min(100%, 48rem); + color: var(--text); + margin-block-start: var(--s-10); +} + +.team__results__placements { + list-style: none; + display: flex; + gap: var(--s-4); +} + +.team__results__placements > li { + display: flex; + align-items: center; + gap: var(--s-1); +} + +.team__member { + display: flex; + flex-direction: column; +} + +.team__member__section { + background-color: var(--bg-lighter); + border-radius: var(--rounded); + padding: var(--s-2) var(--s-4); + font-size: var(--fonts-xl); + font-weight: var(--bold); + display: flex; + justify-content: space-between; + align-items: center; + height: 4.5rem; +} + +.team__member__avatar-name-container { + display: flex; + align-items: center; + gap: var(--s-4); + color: var(--text); + font-weight: var(--bold); +} + +.team__member__avatar { + background-color: var(--bg); + padding: var(--s-2); + border-radius: 100%; +} + +.team__member__role { + margin-left: auto; + font-size: var(--fonts-sm); + color: var(--text-lighter); + margin-inline-end: var(--s-2-5); + font-weight: var(--bold); +} diff --git a/app/root.tsx b/app/root.tsx index bad989959..a9445440c 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -182,6 +182,7 @@ export const namespaceJsonsToPreloadObj: Record< user: true, weapons: true, tournament: true, + team: true, }; const namespaceJsonsToPreload = Object.keys(namespaceJsonsToPreloadObj); diff --git a/app/styles/vars.css b/app/styles/vars.css index 00c6f51b4..4901328da 100644 --- a/app/styles/vars.css +++ b/app/styles/vars.css @@ -34,6 +34,7 @@ html { --theme-transparent: #f3a0c386; --theme-very-transparent: #f3a0c341; --theme-vibrant: #f73e8b; + --theme-semi-transparent: #ff99c477; --theme-secondary: rgb(63 58 255); --backdrop-filter: blur(10px) brightness(95%); --rounded: 16px; @@ -51,6 +52,7 @@ html { --bold: 600; --semi-bold: 500; --body: 400; + --s-0-5: 0.125rem; --s-1: 0.25rem; --s-1-5: 0.375rem; --s-2: 0.5rem; @@ -118,6 +120,7 @@ html.dark { --theme: #ffc6de; --theme-very-transparent: #ffc6de36; --theme-vibrant: #f391ba; + --theme-semi-transparent: #ff99c477; --theme-transparent: #ffc6de52; --theme-secondary: rgb(239 229 83); --backdrop-filter: blur(10px) brightness(75%); diff --git a/public/locales/en/team.json b/public/locales/en/team.json new file mode 100644 index 000000000..028f04686 --- /dev/null +++ b/public/locales/en/team.json @@ -0,0 +1,7 @@ +{ + "roles.CAPTAIN": "Captain", + "roles.FRONTLINE": "Frontline", + "roles.SUPPORT": "Support", + "roles.BACKLINE": "Backline", + "roles.COACH": "Coach" +} diff --git a/public/static-assets/img/layout/xsearch.avif b/public/static-assets/img/layout/xsearch.avif new file mode 100644 index 0000000000000000000000000000000000000000..725e7bdc6be92ddd6cc6bf877101adbe415ad68e GIT binary patch literal 3746 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 YJpEMZj0nX*DBy#!%m@r-y?IjhKOtPZ{{R30 literal 0 HcmV?d00001 diff --git a/public/static-assets/img/layout/xsearch.png b/public/static-assets/img/layout/xsearch.png new file mode 100644 index 0000000000000000000000000000000000000000..6d6b0f403cd9aa5067921771912757cb2681da1f GIT binary patch literal 20408 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 literal 0 HcmV?d00001 diff --git a/remix.config.js b/remix.config.js index 9fba4ed31..ef1d2faad 100644 --- a/remix.config.js +++ b/remix.config.js @@ -21,6 +21,7 @@ module.exports = { route("/to/:id/teams", "features/tournament/routes/to.$id.teams.tsx"); route("/to/:id/join", "features/tournament/routes/to.$id.join.tsx"); }); + route("/t/:customUrl", "features/team/routes/t.$customUrl.tsx"); }); }, }; diff --git a/types/react-i18next.d.ts b/types/react-i18next.d.ts index b676938b4..43f86fb21 100644 --- a/types/react-i18next.d.ts +++ b/types/react-i18next.d.ts @@ -12,6 +12,7 @@ import type builds from "../public/locales/en/builds.json"; import type analyzer from "../public/locales/en/analyzer.json"; import type gameMisc from "../public/locales/en/game-misc.json"; import type tournament from "../public/locales/en/tournament.json"; +import type team from "../public/locales/en/team.json"; declare module "react-i18next" { interface CustomTypeOptions { @@ -29,6 +30,7 @@ declare module "react-i18next" { analyzer: typeof analyzer; "game-misc": typeof gameMisc; tournament: typeof tournament; + team: typeof team; }; } }