mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import { Form, useLoaderData } from "react-router";
|
|
import { Alert } from "~/components/Alert";
|
|
import { LinkButton } from "~/components/elements/Button";
|
|
import { FriendCodeInput } from "~/components/FriendCodeInput";
|
|
import { SubmitButton } from "~/components/SubmitButton";
|
|
import { useUser } from "~/features/auth/core/user";
|
|
import invariant from "~/utils/invariant";
|
|
import { assertUnreachable } from "~/utils/types";
|
|
import { userEditProfilePage } from "~/utils/urls";
|
|
import { action } from "../actions/to.$id.join.server";
|
|
import { loader } from "../loaders/to.$id.join.server";
|
|
import styles from "../tournament.module.css";
|
|
import { validateCanJoinTeam } from "../tournament-utils";
|
|
import { useTournament } from "./to.$id";
|
|
|
|
export { action, loader };
|
|
|
|
export default function JoinTeamPage() {
|
|
const { t } = useTranslation(["tournament", "common"]);
|
|
const user = useUser();
|
|
const tournament = useTournament();
|
|
const data = useLoaderData<typeof loader>();
|
|
|
|
const teamToJoin = data.teamId ? tournament.teamById(data.teamId) : undefined;
|
|
const validationStatus = validateCanJoinTeam({
|
|
inviteCode: data.inviteCode,
|
|
teamToJoin,
|
|
userId: user?.id,
|
|
maxTeamSize: tournament.maxMembersPerTeam,
|
|
});
|
|
|
|
const textPrompt = () => {
|
|
switch (validationStatus) {
|
|
case "MISSING_CODE":
|
|
case "SHORT_CODE":
|
|
case "NO_TEAM_MATCHING_CODE":
|
|
case "TEAM_FULL":
|
|
case "ALREADY_JOINED":
|
|
case "NOT_LOGGED_IN":
|
|
return t(`tournament:join.error.${validationStatus}`);
|
|
case "VALID": {
|
|
invariant(teamToJoin);
|
|
|
|
return t("tournament:join.VALID", {
|
|
teamName: teamToJoin.name,
|
|
eventName: tournament.ctx.name,
|
|
});
|
|
}
|
|
default: {
|
|
assertUnreachable(validationStatus);
|
|
}
|
|
}
|
|
};
|
|
|
|
if (tournament.ctx.settings.requireInGameNames && user && !user.inGameName) {
|
|
return (
|
|
<Alert variation="WARNING" alertClassName="w-max">
|
|
<div className="stack horizontal sm items-center flex-wrap justify-center text-center">
|
|
This tournament requires you to have an in-game name set{" "}
|
|
<LinkButton to={userEditProfilePage(user)} size="small">
|
|
Edit profile
|
|
</LinkButton>
|
|
</div>
|
|
</Alert>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="stack lg items-center">
|
|
<div className="text-center text-lg font-semi-bold">{textPrompt()}</div>
|
|
<div className="stack sm items-center">
|
|
{validationStatus === "VALID" ? (
|
|
<FriendCodeInput friendCode={user?.friendCode} />
|
|
) : null}
|
|
{user?.inGameName ? (
|
|
<div className="font-bold">
|
|
<span className="text-lighter">IGN</span> {user.inGameName}
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
<Form method="post" className={styles.inviteContainer}>
|
|
{validationStatus === "VALID" ? (
|
|
<div className="stack md items-center">
|
|
<SubmitButton size="big" isDisabled={!user?.friendCode}>
|
|
{t("common:actions.join")}
|
|
</SubmitButton>
|
|
{!user?.friendCode ? (
|
|
<div className="text-warning">
|
|
Save friend code before joining the team
|
|
</div>
|
|
) : (
|
|
<div className="text-lighter text-sm">
|
|
{t("tournament:join.friendSuggestion")}
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
</Form>
|
|
</div>
|
|
);
|
|
}
|