sendou.ink/app/features/top-search/routes/xsearch.player.$id.tsx
2024-02-03 10:20:21 +02:00

112 lines
2.9 KiB
TypeScript

import type {
LinksFunction,
LoaderFunctionArgs,
MetaFunction,
SerializeFrom,
} from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
import { Main } from "~/components/Main";
import { type SendouRouteHandle, notFoundIfFalsy } from "~/utils/remix";
import { PlacementsTable } from "../components/Placements";
import { findPlacementsByPlayerId } from "../queries/findPlacements.server";
import styles from "../top-search.css";
import { removeDuplicates } from "~/utils/arrays";
import {
navIconUrl,
topSearchPage,
topSearchPlayerPage,
userPage,
} from "~/utils/urls";
import { i18next } from "~/modules/i18n";
import { makeTitle } from "~/utils/strings";
import { useTranslation } from "react-i18next";
export const handle: SendouRouteHandle = {
breadcrumb: ({ match }) => {
const data = match.data as SerializeFrom<typeof loader> | undefined;
if (!data) return [];
const firstName = data.placements[0].name;
return [
{
imgPath: navIconUrl("xsearch"),
href: topSearchPage(),
type: "IMAGE",
},
{
text: firstName,
type: "TEXT",
href: topSearchPlayerPage(data.placements[0].playerId),
},
];
},
};
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
export const meta: MetaFunction = (args) => {
const data = args.data as SerializeFrom<typeof loader> | null;
if (!data) return [];
return [
{ title: data.title },
{
name: "description",
content: `Splatoon 3 X Battle for the player ${data.placements[0].name}`,
},
];
};
export const loader = async ({ params, request }: LoaderFunctionArgs) => {
const placements = notFoundIfFalsy(
findPlacementsByPlayerId(Number(params["id"])),
);
const t = await i18next.getFixedT(request);
return {
placements,
title: makeTitle([placements[0].name, t("pages.xsearch")]),
};
};
export default function XSearchPlayerPage() {
const { t } = useTranslation(["common"]);
const data = useLoaderData<typeof loader>();
const firstName = data.placements[0].name;
const aliases = removeDuplicates(
data.placements
.map((placement) => placement.name)
.filter((name) => name !== firstName),
);
const hasUserLinked = Boolean(data.placements[0].discordId);
return (
<Main halfWidth className="stack lg">
<div>
<h2 className="text-lg">
{hasUserLinked ? (
<Link to={userPage(data.placements[0])}>{firstName}</Link>
) : (
<>{firstName}</>
)}{" "}
{t("common:xsearch.placements")}
</h2>
{aliases.length > 0 ? (
<div className="text-lighter text-sm">
{t("common:xsearch.aliases")} {aliases.join(", ")}
</div>
) : null}
</div>
<PlacementsTable placements={data.placements} type="MODE_INFO" />
</Main>
);
}