mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-12 22:11:06 -05:00
223 lines
6.3 KiB
TypeScript
223 lines
6.3 KiB
TypeScript
import { useQuery } from "@apollo/react-hooks"
|
|
import {
|
|
Badge,
|
|
Box,
|
|
Tab,
|
|
TabList,
|
|
TabPanel,
|
|
TabPanels,
|
|
Tabs,
|
|
} from "@chakra-ui/core"
|
|
import { Redirect, RouteComponentProps } from "@reach/router"
|
|
import React, { useContext } from "react"
|
|
import { Helmet } from "react-helmet-async"
|
|
import { FaTrophy, FaTshirt } from "react-icons/fa"
|
|
import { IconType } from "react-icons/lib/cjs"
|
|
import { PLAYER_INFO } from "../../graphql/queries/playerInfo"
|
|
import { SEARCH_FOR_BUILDS } from "../../graphql/queries/searchForBuilds"
|
|
import {
|
|
SearchForUserData,
|
|
SearchForUserVars,
|
|
SEARCH_FOR_USER,
|
|
} from "../../graphql/queries/searchForUser"
|
|
import { USER } from "../../graphql/queries/user"
|
|
import MyThemeContext from "../../themeContext"
|
|
import {
|
|
PlayerInfoData,
|
|
PlayerInfoVars,
|
|
SearchForBuildsData,
|
|
SearchForBuildsVars,
|
|
UserData,
|
|
} from "../../types"
|
|
import { weapons } from "../../utils/lists"
|
|
import Error from "../common/Error"
|
|
import Loading from "../common/Loading"
|
|
import Alert from "../elements/Alert"
|
|
import Markdown from "../elements/Markdown"
|
|
import AvatarWithInfo from "./AvatarWithInfo"
|
|
import BuildTab from "./BuildTab"
|
|
import XRankTab from "./XRankTab"
|
|
import { useTranslation, Trans } from "react-i18next"
|
|
|
|
interface Tab {
|
|
id: number
|
|
icon: IconType
|
|
title: JSX.Element
|
|
content: JSX.Element
|
|
}
|
|
|
|
interface UserPageProps {
|
|
id?: string
|
|
}
|
|
|
|
const UserPage: React.FC<RouteComponentProps & UserPageProps> = ({ id }) => {
|
|
const { t } = useTranslation()
|
|
const { data, error, loading } = useQuery<
|
|
SearchForUserData,
|
|
SearchForUserVars
|
|
>(SEARCH_FOR_USER, {
|
|
variables: isNaN(id as any) ? { custom_url: id } : { discord_id: id },
|
|
})
|
|
|
|
const { data: userData, error: userError, loading: userLoading } = useQuery<
|
|
UserData
|
|
>(USER)
|
|
|
|
const {
|
|
data: buildsData,
|
|
error: buildsError,
|
|
loading: buildsLoading,
|
|
} = useQuery<SearchForBuildsData, SearchForBuildsVars>(SEARCH_FOR_BUILDS, {
|
|
variables: { discord_id: data?.searchForUser?.discord_id as any },
|
|
skip: !data || !data.searchForUser,
|
|
})
|
|
|
|
const {
|
|
data: playerData,
|
|
error: playerError,
|
|
loading: playerLoading,
|
|
} = useQuery<PlayerInfoData, PlayerInfoVars>(PLAYER_INFO, {
|
|
variables: { twitter: data?.searchForUser?.twitter_name as any },
|
|
skip: !data || !data.searchForUser || !data.searchForUser.twitter_name,
|
|
})
|
|
|
|
const {
|
|
textColor,
|
|
themeColor,
|
|
themeColorWithShade,
|
|
grayWithShade,
|
|
} = useContext(MyThemeContext)
|
|
|
|
if (loading || userLoading || buildsLoading || playerLoading)
|
|
return <Loading />
|
|
if (error) return <Error errorMessage={error.message} />
|
|
if (userError) return <Error errorMessage={userError.message} />
|
|
if (buildsError) return <Error errorMessage={buildsError.message} />
|
|
if (playerError) return <Error errorMessage={playerError.message} />
|
|
if (!data || !data.searchForUser || !userData || !buildsData)
|
|
return <Redirect to="/404" />
|
|
|
|
const userLean = userData.user
|
|
const user = data.searchForUser
|
|
const builds = buildsData.searchForBuilds
|
|
|
|
const tabs: Tab[] = []
|
|
|
|
if (builds.length > 0 || userLean?.discord_id === user.discord_id) {
|
|
tabs.push({
|
|
id: 1,
|
|
icon: FaTshirt,
|
|
title: (
|
|
<>
|
|
{t("navigation;Builds")}{" "}
|
|
<Badge variantColor={themeColor} ml="0.5em">
|
|
{builds.length}
|
|
</Badge>
|
|
</>
|
|
),
|
|
content: (
|
|
<TabPanel key={1}>
|
|
<BuildTab
|
|
builds={builds.sort((a, b) => {
|
|
const weaponPool = user.weapons
|
|
if (weaponPool) {
|
|
if (
|
|
weaponPool.includes(a.weapon) &&
|
|
weaponPool.includes(b.weapon)
|
|
) {
|
|
return (
|
|
weaponPool.indexOf(a.weapon) - weaponPool.indexOf(b.weapon)
|
|
)
|
|
}
|
|
const poolComparision =
|
|
weaponPool.indexOf(b.weapon) - weaponPool.indexOf(a.weapon)
|
|
|
|
if (poolComparision !== 0) return poolComparision
|
|
}
|
|
return weapons.indexOf(a.weapon) - weapons.indexOf(b.weapon)
|
|
})}
|
|
canModifyBuilds={userLean?.discord_id === user.discord_id}
|
|
/>
|
|
</TabPanel>
|
|
),
|
|
})
|
|
}
|
|
|
|
if (playerData?.playerInfo?.placements) {
|
|
tabs.push({
|
|
id: 2,
|
|
icon: FaTrophy,
|
|
title: (
|
|
<>
|
|
{t("users;X Rank Top 500")}{" "}
|
|
<Badge variantColor={themeColor} ml="0.5em">
|
|
{playerData.playerInfo.placements.length}
|
|
</Badge>
|
|
</>
|
|
),
|
|
content: (
|
|
<TabPanel key={2}>
|
|
<XRankTab placements={playerData.playerInfo.placements} />
|
|
</TabPanel>
|
|
),
|
|
})
|
|
} else if (userLean?.discord_id === user.discord_id) {
|
|
tabs.push({
|
|
id: 2,
|
|
icon: FaTrophy,
|
|
title: <>{t("users;X Rank Top 500")}</>,
|
|
content: (
|
|
<TabPanel key={2}>
|
|
<Box color={grayWithShade}>
|
|
<Trans i18nKey="users;noPlacementsPrompt">
|
|
If you have reached Top 500 in a <b>finished</b> X Rank season you
|
|
can have it displayed here! Make sure your Twitter account is
|
|
verified on Discord to get it showing on your sendou.ink profile
|
|
and then contact Sendou#0043 on Discord with your in-game nick.
|
|
Once set up new results are added automatically and no further
|
|
action is needed unless you change your name on Twitter.
|
|
</Trans>
|
|
</Box>
|
|
</TabPanel>
|
|
),
|
|
})
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Helmet>
|
|
<title>
|
|
{user.username}#{user.discriminator} | sendou.ink
|
|
</title>
|
|
</Helmet>
|
|
<AvatarWithInfo
|
|
user={user}
|
|
canEdit={userLean?.discord_id === user.discord_id}
|
|
/>
|
|
{user.bio && (
|
|
<Box my="2em">
|
|
<Markdown value={user.bio} />
|
|
</Box>
|
|
)}
|
|
<Tabs isFitted variant="line" mt="2em" variantColor={themeColor}>
|
|
<TabList mb="1em">
|
|
{tabs.map((tabObj) => (
|
|
<Tab key={tabObj.id} color={textColor}>
|
|
<Box
|
|
as={tabObj.icon}
|
|
size="24px"
|
|
color={themeColorWithShade}
|
|
mr="7px"
|
|
/>{" "}
|
|
{tabObj.title}
|
|
</Tab>
|
|
))}
|
|
</TabList>
|
|
<TabPanels>{tabs.map((tabObj) => tabObj.content)}</TabPanels>
|
|
</Tabs>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default UserPage
|