mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-14 15:16:09 -05:00
builds link to analyzer
This commit is contained in:
5
TODO.md
5
TODO.md
@@ -2,9 +2,10 @@
|
||||
|
||||
- [x] Can log in
|
||||
- [x] Can update builds
|
||||
- [ ] Build Analyzer
|
||||
- [x] Build Analyzer
|
||||
- [x] Import /analyzer
|
||||
- [ ] Builds link to /analyzer
|
||||
- [x] Builds link to /analyzer
|
||||
- [ ] Check that user page fallback / redirect works
|
||||
- [ ] Builds mode icons
|
||||
- [ ] Script to parse data from Top 500 .json to the DB
|
||||
- [ ] Top 500 Leaderboards
|
||||
|
||||
@@ -41,7 +41,6 @@ const BuildCard: React.FC<BuildCardProps & BoxProps> = ({
|
||||
...props
|
||||
}) => {
|
||||
const [apView, setApView] = useState(false);
|
||||
const [showStats, setShowStats] = useState(false);
|
||||
|
||||
const { themeColorShade, secondaryBgColor, gray } = useMyTheme();
|
||||
|
||||
@@ -49,9 +48,6 @@ const BuildCard: React.FC<BuildCardProps & BoxProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* {showStats && (
|
||||
<BuildCardStats build={build} closeModal={() => setShowStats(false)} />
|
||||
)} */}
|
||||
<Box
|
||||
w="300px"
|
||||
rounded="lg"
|
||||
@@ -126,15 +122,22 @@ const BuildCard: React.FC<BuildCardProps & BoxProps> = ({
|
||||
icon={<FiTarget />}
|
||||
mr="0.5em"
|
||||
/>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
isRound
|
||||
onClick={() => setShowStats(!showStats)}
|
||||
aria-label="Show build stats view"
|
||||
fontSize="20px"
|
||||
icon={<FiBarChart2 />}
|
||||
mr="0.5em"
|
||||
/>
|
||||
<Link
|
||||
href={encodeURI(
|
||||
`/analyzer?weapon=${build.weapon}&head=${build.headAbilities}&clothing=${build.clothingAbilities}&shoes=${build.shoesAbilities}`
|
||||
)}
|
||||
>
|
||||
<a>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
isRound
|
||||
aria-label="Show build stats view"
|
||||
fontSize="20px"
|
||||
icon={<FiBarChart2 />}
|
||||
mr="0.5em"
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
{build.description && (
|
||||
<Popover placement="top">
|
||||
<PopoverTrigger>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// TODO: this whole file should probably get replaced with something like react-window
|
||||
// TODO: render less than 12?
|
||||
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import { ReactElement, ReactNodeArray, useState } from "react";
|
||||
|
||||
@@ -61,3 +61,21 @@ export const isSlotOnlyAbility = (
|
||||
(abilityObject) =>
|
||||
abilityObject.code === ability && abilityObject.type === slot
|
||||
);
|
||||
|
||||
export function isAbilityArray(
|
||||
arr: any[],
|
||||
type: "HEAD" | "CLOTHING" | "SHOES"
|
||||
) {
|
||||
if (arr.length !== 4) return false;
|
||||
|
||||
return arr.every((value, index) => {
|
||||
const ability = abilities.find(
|
||||
(abilityCodeInArray) => value === abilityCodeInArray.code
|
||||
);
|
||||
if (!ability) return false;
|
||||
|
||||
if (index === 0) return ["STACKABLE", type].includes(ability.type);
|
||||
|
||||
return ability.type === "STACKABLE";
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,3 +142,5 @@ export const altWeaponToNormal = new Map([
|
||||
["Hero Brella Replica", "Splat Brella"],
|
||||
["Octo Shot Replica", "Tentatek Splattershot"],
|
||||
]);
|
||||
|
||||
export const isWeapon = (value: any) => weapons.includes(value);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { abilities } from "lib/lists/abilities";
|
||||
import { isAbilityArray } from "lib/lists/abilities";
|
||||
import { clothingGear, headGear, shoesGear } from "lib/lists/gear";
|
||||
import { weaponsWithHero } from "lib/lists/weaponsWithHero";
|
||||
import * as z from "zod";
|
||||
@@ -75,18 +75,3 @@ export const buildSchema = z.object({
|
||||
.nullable(),
|
||||
id: z.number().optional(),
|
||||
});
|
||||
|
||||
function isAbilityArray(arr: any[], type: "HEAD" | "CLOTHING" | "SHOES") {
|
||||
if (arr.length !== 4) return false;
|
||||
|
||||
return arr.every((value, index) => {
|
||||
const ability = abilities.find(
|
||||
(abilityCodeInArray) => value === abilityCodeInArray.code
|
||||
);
|
||||
if (!ability) return false;
|
||||
|
||||
if (index === 0) return ["STACKABLE", type].includes(ability.type);
|
||||
|
||||
return ability.type === "STACKABLE";
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,10 +13,13 @@ import EditableBuilds from "components/analyzer/EditableBuilds";
|
||||
import { ViewSlotsAbilities } from "components/builds/ViewSlots";
|
||||
import Breadcrumbs from "components/common/Breadcrumbs";
|
||||
import WeaponSelector from "components/common/WeaponSelector";
|
||||
import { isAbilityArray } from "lib/lists/abilities";
|
||||
import { isWeapon } from "lib/lists/weapons";
|
||||
import { AbilityOrUnknown } from "lib/types";
|
||||
import useAbilityEffects from "lib/useAbilityEffects";
|
||||
import { useMyTheme } from "lib/useMyTheme";
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { FiSettings } from "react-icons/fi";
|
||||
|
||||
const CURRENT_PATCH = "5.3.";
|
||||
@@ -28,7 +31,8 @@ const defaultBuild: ViewSlotsAbilities = {
|
||||
};
|
||||
|
||||
const BuildAnalyzerPage = () => {
|
||||
const { themeColorShade, gray } = useMyTheme();
|
||||
const router = useRouter();
|
||||
const { gray } = useMyTheme();
|
||||
const [build, setBuild] = useState<ViewSlotsAbilities>({
|
||||
...defaultBuild,
|
||||
});
|
||||
@@ -65,36 +69,7 @@ const BuildAnalyzerPage = () => {
|
||||
lde: otherLde,
|
||||
});
|
||||
|
||||
// function getBuildFromUrl() {
|
||||
// const buildToReturn: AnalyzerBuild = {
|
||||
// ...defaultBuild,
|
||||
// weapon: "Splattershot Jr.",
|
||||
// };
|
||||
// const decoded = new URLSearchParams(location.search);
|
||||
|
||||
// for (const [key, value] of decoded) {
|
||||
// switch (key) {
|
||||
// case "weapon":
|
||||
// buildToReturn.weapon = value;
|
||||
// break;
|
||||
// case "headgear":
|
||||
// case "clothing":
|
||||
// case "shoes":
|
||||
// const abilityKey = key as "headgear" | "clothing" | "shoes";
|
||||
// buildToReturn[abilityKey] = value.split(",") as any;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return buildToReturn;
|
||||
// }
|
||||
|
||||
// useEffect(() => {
|
||||
// const { weapon, ...buildFromUrl } = getBuildFromUrl();
|
||||
|
||||
// setWeapon(weapon);
|
||||
// setBuild(buildFromUrl);
|
||||
// // eslint-disable-next-line
|
||||
// }, []);
|
||||
useEffect(parseQuery, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -200,6 +175,34 @@ const BuildAnalyzerPage = () => {
|
||||
</Wrap>
|
||||
</>
|
||||
);
|
||||
|
||||
function parseQuery() {
|
||||
const query = router.query;
|
||||
|
||||
const weapon = isWeapon(query.weapon) ? query.weapon : "Splattershot Jr.";
|
||||
const headAbilities =
|
||||
typeof query.head === "string" &&
|
||||
isAbilityArray(query.head.split(","), "HEAD")
|
||||
? query.head.split(",")
|
||||
: ["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"];
|
||||
const clothingAbilities =
|
||||
typeof query.clothing === "string" &&
|
||||
isAbilityArray(query.clothing.split(","), "CLOTHING")
|
||||
? query.clothing.split(",")
|
||||
: ["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"];
|
||||
const shoesAbilities =
|
||||
typeof query.shoes === "string" &&
|
||||
isAbilityArray(query.shoes.split(","), "SHOES")
|
||||
? query.shoes.split(",")
|
||||
: ["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"];
|
||||
|
||||
setWeapon(weapon as string);
|
||||
setBuild({
|
||||
headAbilities: headAbilities as AbilityOrUnknown[],
|
||||
clothingAbilities: clothingAbilities as AbilityOrUnknown[],
|
||||
shoesAbilities: shoesAbilities as AbilityOrUnknown[],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default BuildAnalyzerPage;
|
||||
|
||||
Reference in New Issue
Block a user