build cards including ap view

This commit is contained in:
Sendou
2020-01-21 23:26:21 +02:00
parent e10d8850d9
commit ec0c4a4012
52 changed files with 563 additions and 79 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,3 +1,32 @@
import BDU from "./abilityIcons/BDU.png"
import BRU from "./abilityIcons/BRU.png"
import CB from "./abilityIcons/CB.png"
import DR from "./abilityIcons/DR.png"
import H from "./abilityIcons/H.png"
import ISM from "./abilityIcons/ISM.png"
import ISS from "./abilityIcons/ISS.png"
import LDE from "./abilityIcons/LDE.png"
import MPU from "./abilityIcons/MPU.png"
import NS from "./abilityIcons/NS.png"
import OG from "./abilityIcons/OG.png"
import QR from "./abilityIcons/QR.png"
import QSJ from "./abilityIcons/QSJ.png"
import REC from "./abilityIcons/REC.png"
import RES from "./abilityIcons/RES.png"
import RP from "./abilityIcons/RP.png"
import RSU from "./abilityIcons/RSU.png"
import SCU from "./abilityIcons/SCU.png"
import SJ from "./abilityIcons/SJ.png"
import SPU from "./abilityIcons/SPU.png"
import SS from "./abilityIcons/SS.png"
import SSU from "./abilityIcons/SSU.png"
import T from "./abilityIcons/T.png"
import TI from "./abilityIcons/TI.png"
import OS from "./abilityIcons/OS.png"
import AD from "./abilityIcons/AD.png"
import UNKNOWN from "./abilityIcons/UNKNOWN.png"
import * as top500logo from "./top500.png"
//https://stackoverflow.com/questions/42118296/dynamically-import-images-from-a-directory-using-webpack
export const wpnSmall: object = importAll(require.context("./wpnSmall", false))
export const wpnMedium: object = importAll(
@@ -11,3 +40,36 @@ function importAll(r: __WebpackModuleApi.RequireContext) {
})
return images
}
export const abilityIcons = {
BDU: BDU,
BRU: BRU,
CB: CB,
DR: DR,
H: H,
ISM: ISM,
ISS: ISS,
LDE: LDE,
MPU: MPU,
NS: NS,
OG: OG,
QR: QR,
QSJ: QSJ,
REC: REC,
RES: RES,
RP: RP,
RSU: RSU,
SCU: SCU,
SJ: SJ,
SPU: SPU,
SS: SS,
SSU: SSU,
T: T,
TI: TI,
OS: OS,
AD: AD,
UNKNOWN: UNKNOWN,
"": UNKNOWN,
} as const
export const top500 = top500logo

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -0,0 +1,58 @@
import React from "react"
import {
StackableAbility,
HeadOnlyAbility,
ClothingOnlyAbility,
ShoesOnlyAbility,
} from "../../types"
import { abilityIcons } from "../../assets/imageImports"
const mainAbilityStyle = {
//https://github.com/loadout-ink/splat2-calc
zIndex: 2,
borderRadius: "50%",
width: "50px",
height: "50px",
background: "#000",
border: "2px solid #888",
borderRight: "0px",
borderBottom: "0px",
backgroundSize: "100%",
boxShadow: "0 0 0 1px #000",
userSelect: "none",
} as const
const subAbilityStyle = {
//https://github.com/loadout-ink/splat2-calc
zIndex: 2,
borderRadius: "50%",
width: "40px",
height: "40px",
background: "#000",
border: "2px solid #888",
borderRight: "0px",
borderBottom: "0px",
backgroundSize: "100%",
boxShadow: "0 0 0 1px #000",
userSelect: "none",
} as const
interface AbilityIconProps {
ability:
| StackableAbility
| HeadOnlyAbility
| ClothingOnlyAbility
| ShoesOnlyAbility
size: "MAIN" | "SUB"
}
const AbilityIcon: React.FC<AbilityIconProps> = ({ ability, size }) => {
return (
<img
src={abilityIcons[ability]}
style={size === "MAIN" ? mainAbilityStyle : subAbilityStyle}
alt={ability}
/>
)
}
export default AbilityIcon

View File

@@ -1,13 +1,108 @@
import React from "react"
import React, { useState } from "react"
import { Build } from "../../types"
import { Box } from "@chakra-ui/core"
import {
Box,
Flex,
Image,
IconButton,
Popover,
PopoverTrigger,
PopoverContent,
PopoverBody,
} from "@chakra-ui/core"
import useTheme from "../../hooks/useTheme"
import WeaponImage from "../common/WeaponImage"
import { top500 } from "../../assets/imageImports"
import { FaInfo, FaPlus, FaMinus } from "react-icons/fa"
import ViewGear from "./ViewGear"
import ViewAP from "./ViewAP"
interface BuildCardProps {
build: Build
defaultToAPView: Boolean
}
const BuildCard: React.FC<BuildCardProps> = ({ build }) => {
return <Box>asd</Box>
const BuildCard: React.FC<BuildCardProps> = ({ build, defaultToAPView }) => {
const [apView, setApView] = useState(defaultToAPView)
const { borderStyle, themeColor, darkerBgColor, grayWithShade } = useTheme()
return (
<Box
width="325px"
borderWidth="1px"
border={borderStyle}
rounded="lg"
overflow="hidden"
pt="2"
pb="6"
px="6"
>
<Flex justifyContent="space-between">
<Box width="24" height="auto">
<WeaponImage englishName={build.weapon} size="MEDIUM" />
</Box>
{build.top && (
<Image
src={top500}
alt="x rank top 500 logo"
height="50px"
width="auto"
title="Maker of the build has reached top 500 with this weapon"
/>
)}
</Flex>
<Box
color={grayWithShade}
fontWeight="semibold"
letterSpacing="wide"
fontSize="xs"
>
{new Date(parseInt(build.updatedAt)).toLocaleString()}
</Box>
{build.title && (
<Box mt="1" fontWeight="semibold" as="h4" lineHeight="tight">
{build.title}
</Box>
)}
{apView ? <ViewAP build={build} /> : <ViewGear build={build} />}
<Flex justifyContent="space-between" mt="1em">
{build.description ? (
<Popover placement="top">
<PopoverTrigger>
<IconButton
variant="ghost"
isRound
variantColor={themeColor}
aria-label="Show description"
fontSize="20px"
icon={FaInfo}
/>
</PopoverTrigger>
<PopoverContent
zIndex={4}
width="220px"
backgroundColor={darkerBgColor}
>
<PopoverBody textAlign="center" whiteSpace="pre-wrap">
{build.description}
</PopoverBody>
</PopoverContent>
</Popover>
) : (
<Box />
)}
<IconButton
variant="ghost"
isRound
variantColor={themeColor}
aria-label={apView ? "Show gear" : "Show ability point count"}
fontSize="20px"
icon={apView ? FaMinus : FaPlus}
onClick={() => setApView(!apView)}
/>
</Flex>
</Box>
)
}
export default BuildCard

View File

@@ -0,0 +1,26 @@
import React from "react"
import { HeadGear, ClothingGear, ShoesGear } from "../../types"
import english_internal from "../../utils/english_internal.json"
import { Box } from "@chakra-ui/core"
interface GearImageProps {
englishName?: HeadGear | ClothingGear | ShoesGear
renderNullIfNoName: boolean
}
const GearImage: React.FC<GearImageProps> = ({
englishName,
renderNullIfNoName,
}) => {
if (!englishName && renderNullIfNoName) return null
if (!englishName) return <Box />
return (
<img
alt={englishName}
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/gear/${english_internal[englishName]}.png`}
title={englishName}
/>
)
}
export default GearImage

View File

@@ -0,0 +1,122 @@
// This while is bit of a mess from TS PoV - might be worth while to do it better later
import React from "react"
import { Build, Ability } from "../../types"
import { Box, Flex } from "@chakra-ui/core"
import DividingBox from "../ui/DividingBox"
import AbilityIcon from "./AbilityIcon"
import useTheme from "../../hooks/useTheme"
const mainOnlyAbilities = [
"CB",
"LDE",
"OG",
"T",
"H",
"NS",
"TI",
"RP",
"AD",
"DR",
"SJ",
"OS",
] as const
interface ViewAPProps {
build: Build
}
const ViewAP: React.FC<ViewAPProps> = ({ build }) => {
const { grayWithShade } = useTheme()
const abilityArrays: Ability[][] = [
build.headgear,
build.clothing,
build.shoes,
]
const abilityToPoints: Partial<Record<Ability, number>> = {}
abilityArrays.forEach(arr =>
arr.forEach((ability, index) => {
let abilityPoints = index === 0 ? 10 : 3
if (mainOnlyAbilities.indexOf(ability as any) !== -1) abilityPoints = 999
abilityToPoints[ability] = abilityToPoints.hasOwnProperty(ability)
? (abilityToPoints[ability] as any) + abilityPoints
: abilityPoints
})
)
const pointsToAbilities: Record<string, Ability[]> = {}
;(Object.keys(abilityToPoints) as Array<
keyof typeof abilityToPoints
>).forEach((ability: Ability) => {
const points = abilityToPoints[ability]
pointsToAbilities.hasOwnProperty(points as any)
? pointsToAbilities[points as any].push(ability)
: (pointsToAbilities[points as any] = [ability])
})
const APArrays = (Object.keys(pointsToAbilities) as Array<
keyof typeof pointsToAbilities
>)
.map(points => [points, pointsToAbilities[points as any]])
.sort((a1, a2) => parseInt(a2[0] as string) - parseInt(a1[0] as string))
let indexToPrintAPAt = APArrays[0][0] === "999" ? 1 : 0
return (
<Box mt="2">
{APArrays.map((arr, index) => {
return (
<Flex
key={arr[0] as any}
justifyContent="flex-start"
alignItems="center"
gridRowGap="2em"
mt={index === 0 ? "0" : "1em"}
>
{arr[0] !== "999" ? (
<DividingBox location="right">
<Box
color={grayWithShade}
width="32px"
minH="45px"
letterSpacing="wide"
fontSize="s"
fontWeight="semibold"
textAlign="center"
pt={indexToPrintAPAt !== index ? "10px" : undefined}
>
{arr[0] as string}
{indexToPrintAPAt === index ? (
<>
<br />
AP
</>
) : null}
</Box>
</DividingBox>
) : (
<Box width="37px" />
)}
{(arr[1] as Array<Ability>).map((ability, abilityIndex) => (
<Box
width="45px"
key={ability}
ml={
abilityIndex !== 0 && arr[1].length > 5
? `-${(arr[1].length - 5) * 5}px`
: undefined
}
>
<AbilityIcon ability={ability} size="SUB" />
</Box>
))}
</Flex>
)
})}
</Box>
)
}
export default ViewAP

View File

@@ -0,0 +1,56 @@
import React from "react"
import { Grid } from "@chakra-ui/core"
import GearImage from "./GearImage"
import { Build } from "../../types"
import AbilityIcon from "./AbilityIcon"
interface ViewGearProps {
build: Build
}
const ViewGear: React.FC<ViewGearProps> = ({ build }) => {
const noItems =
!build.headgearItem && !build.clothingItem && !build.clothingItem
return (
<Grid
gridTemplateColumns={`${noItems ? "" : "75px "} 60px 45px 45px 45px`}
gridRowGap="10px"
justifyItems="center"
alignItems="center"
mt={noItems ? "2" : "0"}
>
<GearImage
englishName={build.headgearItem}
renderNullIfNoName={noItems}
/>
{build.headgear.map((ability, index) => (
<AbilityIcon
key={index}
ability={ability}
size={index === 0 ? "MAIN" : "SUB"}
/>
))}
<GearImage
englishName={build.clothingItem}
renderNullIfNoName={noItems}
/>
{build.clothing.map((ability, index) => (
<AbilityIcon
key={index}
ability={ability}
size={index === 0 ? "MAIN" : "SUB"}
/>
))}
<GearImage englishName={build.shoesItem} renderNullIfNoName={noItems} />
{build.shoes.map((ability, index) => (
<AbilityIcon
key={index}
ability={ability}
size={index === 0 ? "MAIN" : "SUB"}
/>
))}
</Grid>
)
}
export default ViewGear

View File

@@ -1,15 +1,15 @@
import React from "react"
import { Spinner, useColorMode, Box } from "@chakra-ui/core"
import { Spinner, Box } from "@chakra-ui/core"
import useTheme from "../../hooks/useTheme"
interface LoadingProps {}
const Loading: React.FC<LoadingProps> = () => {
const { colorMode } = useColorMode()
const color = { light: "orange.500", dark: "pink.200" }
const { themeColorWithShade } = useTheme()
return (
<Box textAlign="center">
<Spinner
color={color[colorMode]}
color={themeColorWithShade}
size="xl"
thickness="4px"
speed="0.65s"

View File

@@ -12,7 +12,11 @@ interface WeaponImageProps {
const WeaponImage: React.FC<WeaponImageProps> = ({ englishName, size }) => {
const dictToUse: any = size === "MEDIUM" ? wpnMedium : wpnSmall
return (
<img src={dictToUse[english_internal[englishName]]} alt={englishName} />
<img
src={dictToUse[english_internal[englishName]]}
alt={englishName}
title={englishName}
/>
)
}

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from "react"
import React from "react"
import { Box } from "@chakra-ui/core"
import { MenuBar } from "./MenuBar"
@@ -9,15 +9,13 @@ import useTheme from "../../hooks/useTheme"
const App: React.FC = () => {
const { bgColor, textColor } = useTheme()
useEffect(() => {
document.body.style.backgroundColor = bgColor
}, [bgColor])
return (
<Box
marginLeft={[null, null, "250px"]}
mt={["4em", null, "0"]}
color={textColor}
bg={bgColor}
minH="100vh"
>
<SideNav />
<MenuBar />

View File

@@ -5,7 +5,6 @@ import {
Popover,
PopoverBody,
PopoverContent,
useColorMode,
useTheme as useChakraTheme,
} from "@chakra-ui/core"
import { CirclePicker, ColorResult } from "react-color"
@@ -13,12 +12,10 @@ import { writeStorage } from "@rehooks/local-storage"
import { themeColors as choices } from "../../utils/lists"
import useTheme from "../../hooks/useTheme"
const bgColor = { light: "#eff0f3", dark: "#232946" } as const
const size = "20px" as const
const ColorPicker: React.FC = () => {
const { colorMode } = useColorMode()
const { themeColorHex } = useTheme()
const { themeColorHex, bgColor } = useTheme()
const theme = useChakraTheme()
const hexCodes = choices.map(color =>
@@ -46,11 +43,7 @@ const ColorPicker: React.FC = () => {
ml="10px"
/>
</PopoverTrigger>
<PopoverContent
zIndex={4}
width="220px"
backgroundColor={bgColor[colorMode]}
>
<PopoverContent zIndex={4} width="220px" backgroundColor={bgColor}>
<PopoverBody textAlign="center">
<CirclePicker
width="220px"

View File

@@ -1,11 +1,12 @@
import React, { Suspense, lazy } from "react"
import { Router } from "@reach/router"
import Loading from "../common/Loading"
const UserPage = lazy(() => import("../user/UserPage"))
const Routes: React.FC = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<Suspense fallback={<Loading />}>
<Router>
<UserPage path="/u/:id" />
</Router>

View File

@@ -1,17 +1,18 @@
import { Box, useColorMode } from "@chakra-ui/core"
import { Box } from "@chakra-ui/core"
import React from "react"
import { SideNavContent } from "./SideNavContent"
import useTheme from "../../hooks/useTheme"
const shadow = {
light: "0px 1px 10px 8px rgba(0,0,0,0.15)",
dark: "0px 1px 10px 8px rgba(255,255,255,0.04)",
} as const
const SideNav = () => {
const { colorMode } = useColorMode()
const bgColor = { light: "#D6D7DA", dark: "#0A102D" }
const shadow = {
light: "0px 1px 10px 8px rgba(0,0,0,0.15)",
dark: "0px 1px 10px 8px rgba(255,255,255,0.04)",
}
const { darkerBgColor, colorMode } = useTheme()
return (
<Box
bg={bgColor[colorMode]}
bg={darkerBgColor}
boxShadow={shadow[colorMode]}
height="100%"
width="250px"

View File

@@ -3,14 +3,16 @@ import { Box } from "@chakra-ui/core"
import useTheme from "../../hooks/useTheme"
interface DividingBoxProps {
children: JSX.Element | JSX.Element[]
location: "top" | "left" | "bottom"
children: JSX.Element | JSX.Element[] | string
location: "top" | "left" | "bottom" | "right"
margin?: string
width?: string
}
const DividingBox: React.FC<DividingBoxProps> = ({
children,
location,
width = undefined,
margin = "0.4em",
}) => {
const { borderStyle } = useTheme()
@@ -22,6 +24,9 @@ const DividingBox: React.FC<DividingBoxProps> = ({
mt={location === "top" ? margin : undefined}
borderBottom={location === "bottom" ? borderStyle : undefined}
mb={location === "bottom" ? margin : undefined}
borderRight={location === "right" ? borderStyle : undefined}
mr={location === "right" ? margin : undefined}
width={width}
>
{children}
</Box>

View File

@@ -4,7 +4,6 @@ import { FaUserAlt, FaTwitter, FaTwitch, FaGamepad } from "react-icons/fa"
import UserAvatar from "../common/UserAvatar"
import { User } from "../../types"
import DividingBox from "../ui/DividingBox"
import Flag from "../common/Flag"
import { countries } from "../../utils/lists"
@@ -22,48 +21,57 @@ interface AvatarWithInfoProps {
const AvatarWithInfo: React.FC<AvatarWithInfoProps> = ({ user }) => {
return (
<Flex justifyContent="center" flexWrap="wrap" alignItems="center">
<Flex
justifyContent="center"
flexWrap="wrap"
alignItems="center"
flexDirection="column"
>
<UserAvatar
name={user.username}
twitterName={user.twitter_name}
size="2xl"
/>
<DividingBox location="left">
<List spacing={2} mx="0.5em" fontWeight="light">
<List
spacing={2}
mt="1em"
mx="0.5em"
fontWeight="light"
textAlign="center"
>
<ListItem>
<ListIcon icon={FaUserAlt} />
{user.username}#{user.discriminator}
</ListItem>
{user.country && (
<ListItem>
<ListIcon icon={FaUserAlt} />
{user.username}#{user.discriminator}
<Flag code={user.country} />
{countries.find(obj => obj.code === user.country)?.name}
</ListItem>
{user.country && (
<ListItem>
<Flag code={user.country} />
{countries.find(obj => obj.code === user.country)?.name}
</ListItem>
)}
{user.twitter_name && (
<ListItem>
<ListIcon icon={FaTwitter} />
<a href={`https://twitter.com/${user.twitter_name}`}>
{user.twitter_name}
</a>
</ListItem>
)}
{user.twitch_name && (
<ListItem>
<ListIcon icon={FaTwitch} />
<a href={`https://www.twitch.tv/${user.twitch_name}`}>
{user.twitch_name}
</a>
</ListItem>
)}
{user.sens?.stick && (
<ListItem>
<ListIcon icon={FaGamepad} />
{getSensString(user.sens.motion, user.sens.stick)}
</ListItem>
)}
</List>
</DividingBox>
)}
{user.twitter_name && (
<ListItem>
<ListIcon icon={FaTwitter} />
<a href={`https://twitter.com/${user.twitter_name}`}>
{user.twitter_name}
</a>
</ListItem>
)}
{user.twitch_name && (
<ListItem>
<ListIcon icon={FaTwitch} />
<a href={`https://www.twitch.tv/${user.twitch_name}`}>
{user.twitch_name}
</a>
</ListItem>
)}
{user.sens?.stick && (
<ListItem>
<ListIcon icon={FaGamepad} />
{getSensString(user.sens.motion, user.sens.stick)}
</ListItem>
)}
</List>
</Flex>
)
}

View File

@@ -0,0 +1,30 @@
import React from "react"
import { Build } from "../../types"
import { Flex, Box } from "@chakra-ui/core"
import BuildCard from "../builds/BuildCard"
import useLocalStorage from "@rehooks/local-storage"
interface BuildTabProps {
builds: Build[]
canModifyBuilds: boolean
}
const BuildTab: React.FC<BuildTabProps> = ({ builds, canModifyBuilds }) => {
const [APView] = useLocalStorage<boolean>("prefersAPView")
return (
<>
<Flex flexWrap="wrap" justifyContent="center">
{builds.map(build => (
<Box key={build.id} p="0.2em">
<BuildCard
build={build}
defaultToAPView={APView !== null ? APView : false}
/>
</Box>
))}
</Flex>
</>
)
}
export default BuildTab

View File

@@ -21,6 +21,7 @@ import { Box, Tabs, TabList, Tab, TabPanels, TabPanel } from "@chakra-ui/core"
import useTheme from "../../hooks/useTheme"
import { Helmet } from "react-helmet-async"
import { SEARCH_FOR_BUILDS } from "../../graphql/queries/searchForBuilds"
import BuildTab from "./BuildTab"
interface Tab {
id: number
@@ -67,14 +68,17 @@ const UserPage: React.FC<RouteComponentProps & UserPageProps> = ({ id }) => {
const tabs = [] as Tab[]
if (builds.length > 0) {
if (builds.length > 0 || userLean?.discord_id === user.discord_id) {
tabs.push({
id: 1,
icon: FaTshirt,
title: "Builds",
content: (
<TabPanel key={1}>
<p>hi</p>
<BuildTab
builds={builds}
canModifyBuilds={userLean?.discord_id === user.discord_id}
/>
</TabPanel>
),
})
@@ -100,7 +104,7 @@ const UserPage: React.FC<RouteComponentProps & UserPageProps> = ({ id }) => {
</Helmet>
<AvatarWithInfo user={user} />
{user.weapons && user.weapons.length > 0 && (
<Box textAlign="center" mt="2em">
<Box textAlign="center" mt="1em">
<WeaponPool weapons={user.weapons} />
</Box>
)}

View File

@@ -1,7 +1,8 @@
import React from "react"
import { Weapon } from "../../types"
import { Box, Flex, useColorMode } from "@chakra-ui/core"
import { Box, Flex } from "@chakra-ui/core"
import WeaponImage from "../common/WeaponImage"
import useTheme from "../../hooks/useTheme"
interface WeaponPoolProps {
weapons: Weapon[]
@@ -13,7 +14,7 @@ const styles = {
} as const
const WeaponPool: React.FC<WeaponPoolProps> = ({ weapons }) => {
const { colorMode } = useColorMode()
const { colorMode, grayWithShade } = useTheme()
const borderStyle: string = styles[colorMode]
return (
@@ -28,12 +29,11 @@ const WeaponPool: React.FC<WeaponPoolProps> = ({ weapons }) => {
>
<Box
as="legend"
color="gray.500"
color={grayWithShade}
fontWeight="semibold"
letterSpacing="wide"
fontSize="xs"
textTransform="uppercase"
textAlign="left"
>
Weapon pool
</Box>

View File

@@ -3,11 +3,14 @@ import { useLocalStorage } from "@rehooks/local-storage"
import { ThemeColor } from "../types"
interface Theme {
colorMode: "light" | "dark"
bgColor: "#eff0f3" | "#232946"
darkerBgColor: "#D6D7DA" | "#0A102D"
textColor: "#0d0d0d" | "#fffffe"
borderStyle:
| "1px solid rgba(0, 0, 0, .2)"
| "1px solid rgba(255, 255, 255, .2)"
grayWithShade: "gray.300" | "gray.600"
themeColorWithShade: string
themeColorHex: string
themeColor: ThemeColor
@@ -18,7 +21,9 @@ function useTheme(): Theme {
const chakraTheme = useChakraTheme()
const light = colorMode === "light"
const bgColor = light ? "#eff0f3" : "#232946"
const darkerBgColor = light ? "#D6D7DA" : "#0A102D"
const textColor = light ? "#0d0d0d" : "#fffffe"
const grayWithShade = light ? "gray.600" : "gray.300"
const borderStyle = light
? "1px solid rgba(0, 0, 0, .2)"
: "1px solid rgba(255, 255, 255, .2)"
@@ -35,10 +40,13 @@ function useTheme(): Theme {
const themeColorHex = chakraTheme.colors[themeColor]["500"]
return {
colorMode,
bgColor,
darkerBgColor,
textColor,
borderStyle,
themeColorWithShade,
grayWithShade,
themeColorHex,
themeColor,
}

View File

@@ -5,7 +5,6 @@ import { ThemeProvider, ColorModeProvider, CSSReset } from "@chakra-ui/core"
import { ApolloProvider } from "@apollo/react-hooks"
import { HelmetProvider } from "react-helmet-async"
import ApolloClient from "apollo-boost"
import "./index.css"
import * as serviceWorker from "./serviceWorker"
const client = new ApolloClient({

View File

@@ -1 +1,6 @@
/// <reference types="react-scripts" />
declare module "*.png" {
const value: any
export = value
}

View File

@@ -21,10 +21,17 @@ type ElementType<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<
export type Weapon = ElementType<typeof weapons>
export type CountryCode = ElementType<typeof countryCodes>
export type ThemeColor = ElementType<typeof themeColors>
export type HeadOnlyAbility = ElementType<typeof headOnlyAbilities>
export type ClothingOnlyAbility = ElementType<typeof clothingOnlyAbilities>
export type ShoesOnlyAbility = ElementType<typeof shoesOnlyAbilities>
export type StackableAbility = ElementType<typeof stackableAbilities>
export type Ability =
| HeadOnlyAbility
| ClothingOnlyAbility
| ShoesOnlyAbility
| StackableAbility
export type HeadGear = ElementType<typeof headGearEnglish>
export type ClothingGear = ElementType<typeof clothingGearEnglish>
export type ShoesGear = ElementType<typeof shoesGearEnglish>

View File

@@ -67,8 +67,9 @@ passport.deserializeUser(function(discord_id, done) {
})
console.log("connecting to MongoDB")
const dbName =
let dbName =
process.env.NODE_ENV === "development" ? "development" : "production"
if (process.env.USE_PRODUCTION_DB) dbName = "production"
mongoose
.connect(process.env.MONGODB_URI, {

View File

@@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"start": "cross-env LOGGED_IN=TRUE node index.js",
"withprod": "cross-env LOGGED_IN=TRUE USE_PRODUCTION_DB=TRUE node index.js",
"loggedout": "node index.js",
"watch": "cross-env LOGGED_IN=TRUE nodemon index.js",
"build": "cd frontend-react && npm install && npm run build && mv build ../build",