From 9d4dd00765dc1a6e7dcbae1e3d6a9a79636a2123 Mon Sep 17 00:00:00 2001 From: "DESKTOP-8SRFDDM\\cam95" Date: Wed, 19 Jun 2024 22:12:27 -0500 Subject: [PATCH] Move Wiki into Sidebar --- .../component/main-sidebar/main-sidebar.css | 20 +- .../component/main-sidebar/main-sidebar.tsx | 371 ++++++++++-------- .../main-sidebar/sidebar-section-template.tsx | 19 + .../component/typeahead/pokemon-typeahead.css | 2 +- .../component/typeahead/pokemon-typeahead.tsx | 1 + .../src/pages/component/typeahead/types.ts | 2 +- .../src/pages/component/wiki/wiki-ability.tsx | 44 ++- .../component/wiki/wiki-panel-pokemon.tsx | 104 +++++ .../src/pages/component/wiki/wiki-panel.css | 151 +++++++ .../src/pages/component/wiki/wiki-panel.tsx | 95 +++++ .../pages/component/wiki/wiki-pokemons.tsx | 65 ++- app/public/src/pages/component/wiki/wiki.css | 16 +- app/public/src/pages/component/wiki/wiki.tsx | 10 +- 13 files changed, 698 insertions(+), 202 deletions(-) create mode 100644 app/public/src/pages/component/main-sidebar/sidebar-section-template.tsx create mode 100644 app/public/src/pages/component/wiki/wiki-panel-pokemon.tsx create mode 100644 app/public/src/pages/component/wiki/wiki-panel.css create mode 100644 app/public/src/pages/component/wiki/wiki-panel.tsx diff --git a/app/public/src/pages/component/main-sidebar/main-sidebar.css b/app/public/src/pages/component/main-sidebar/main-sidebar.css index 2b14112528..e1273127ac 100644 --- a/app/public/src/pages/component/main-sidebar/main-sidebar.css +++ b/app/public/src/pages/component/main-sidebar/main-sidebar.css @@ -3,6 +3,12 @@ aside.sidebar { height: 100%; z-index: 100; background-color: var(--color-bg-primary); + max-width: 20vw; +} + +aside.sidebar-wide { + width: 100%; + min-width: 340px; } .sidebar-logo { @@ -64,7 +70,7 @@ aside.sidebar { } .ps-menu-root { - height: 100%; + min-height: 100%; background-color: var(--color-bg-primary); } @@ -212,3 +218,15 @@ aside.sidebar { opacity: 1; } } + +.sidebar-section { + position: relative; + min-height: 100%; + background-color: var(--color-bg-primary); +} + +li.go-back-btn { + position: sticky; + bottom: 0; + +} diff --git a/app/public/src/pages/component/main-sidebar/main-sidebar.tsx b/app/public/src/pages/component/main-sidebar/main-sidebar.tsx index e68eab8638..c9333e1e94 100644 --- a/app/public/src/pages/component/main-sidebar/main-sidebar.tsx +++ b/app/public/src/pages/component/main-sidebar/main-sidebar.tsx @@ -20,7 +20,8 @@ import { usePatchVersion } from "../patchnotes/usePatchVersion" import Profile from "../profile/profile" import { ServerAnnouncementForm } from "../server-announcement/server-announcement-form" import { TournamentsAdmin } from "../tournaments-admin/tournaments-admin" -import Wiki from "../wiki/wiki" +import { SidebarSectionTemplate } from "./sidebar-section-template" +import { WikiPanel } from "../wiki/wiki-panel" import "./main-sidebar.css" @@ -35,24 +36,15 @@ interface MainSidebarProps { export function MainSidebar(props: MainSidebarProps) { const { page, leave, leaveLabel } = props const [collapsed, setCollapsed] = useState(true) - const navigate = useNavigate() const [modal, setModal] = useState() const changeModal = useCallback( (nextModal: Modals) => setModal(nextModal), [] ) + const [view, setView] = useState("links") const sidebarRef = useRef(null) const { t } = useTranslation() - const user = useAppSelector((state) => state.lobby.user) - const profile = useAppSelector((state) => state.network.profile) - const profileLevel = profile?.level ?? 0 - - const { isNewPatch, updateVersionChecked } = usePatchVersion() - - const version = pkg.version - - const numberOfBooster = profile?.booster ?? 0 useEffect(() => { if (!sidebarRef.current) { @@ -76,184 +68,243 @@ export function MainSidebar(props: MainSidebarProps) { }, [collapsed]) return ( - + -
setCollapsed(!collapsed)}> - -
-

Pokemon Auto Chess

- v{version} -
-
+ {view === "links" && ( + <> + + + + )} - - window.open( - "https://github.com/keldaanCommunity/pokemonAutoChess/blob/master/policy.md", - "_blank" - ) + {view === "wiki" && ( + setView("links")}> + + + )} +
+
+ ) +} + +interface SidebarMenuProps { + collapsed: boolean + setCollapsed: (value: boolean) => void + changeModal: (modal: Modals) => void + page: Page + t: (text: string) => string + leave: () => void + leaveLabel: string + setView: (value: Modals) => void +} + +function SidebarMenu({ + collapsed, + setCollapsed, + changeModal, + page, + t, + leave, + leaveLabel, + setView, +}: SidebarMenuProps) { + const navigate = useNavigate() + const user = useAppSelector((state) => state.lobby.user) + const profile = useAppSelector((state) => state.network.profile) + const { isNewPatch, updateVersionChecked } = usePatchVersion() + const profileLevel = profile?.level ?? 0 + + const version = pkg.version + + const numberOfBooster = profile?.booster ?? 0 + return ( + <> +
setCollapsed(!collapsed)}> + +
+

Pokemon Auto Chess

+ v{version} +
+
+ + + window.open( + "https://github.com/keldaanCommunity/pokemonAutoChess/blob/master/policy.md", + "_blank" + ) + } + > + {t("policy")} + + + { + changeModal(newModal) + if (isNewPatch) { + updateVersionChecked() } - > - {t("policy")} + }} + shimmer={isNewPatch} + > + {t("news")} + + + {page === "main_lobby" && ( + + {t("profile")} + )} + {page === "main_lobby" && profileLevel >= GADGETS.BAG.levelRequired && ( { - changeModal(newModal) - if (isNewPatch) { - updateVersionChecked() - } - }} - shimmer={isNewPatch} + location="collection" + svg="collection" + className="blue" + handleClick={changeModal} > - {t("news")} + {t("collection")} - - {page === "main_lobby" && ( - - {t("profile")} - - )} - - {page === "main_lobby" && profileLevel >= GADGETS.BAG.levelRequired && ( - - {t("collection")} - - )} - {page === "main_lobby" && profileLevel >= GADGETS.BAG.levelRequired && ( - 0} - > - {t("boosters")} - - )} + )} + {page === "main_lobby" && profileLevel >= GADGETS.BAG.levelRequired && ( 0} > - {t("wiki")} + {t("boosters")} + )} + + {t("wiki")} + + + {t("meta")} + + + {profileLevel >= GADGETS.TEAM_PLANNER.levelRequired && ( - {t("meta")} + {t("team_builder")} + )} + + {page !== "game" && + user?.anonymous === false && + profileLevel >= GADGETS.BOT_BUILDER.levelRequired && ( + navigate("/bot-builder")}> + {t("bot_builder")} + + )} - {profileLevel >= GADGETS.TEAM_PLANNER.levelRequired && ( + {page !== "game" && user?.role === Role.ADMIN && ( + <> + navigate("/sprite-viewer")} + > + Sprite Viewer + + navigate("/map-viewer")}> + Map Viewer + - {t("team_builder")} + Announcement - )} - - {page !== "game" && - user?.anonymous === false && - profileLevel >= GADGETS.BOT_BUILDER.levelRequired && ( - navigate("/bot-builder")}> - {t("bot_builder")} - - )} - - {page !== "game" && user?.role === Role.ADMIN && ( - <> - navigate("/sprite-viewer")} - > - Sprite Viewer - - navigate("/map-viewer")}> - Map Viewer - - - Announcement - - - Tournaments - - - )} - - {page === "game" && profileLevel >= GADGETS.JUKEBOX.levelRequired && ( - Jukebox + Tournaments - )} + + )} - - {t("options")} + {page === "game" && profileLevel >= GADGETS.JUKEBOX.levelRequired && ( + + Jukebox + )} -
+ + {t("options")} + - {page !== "game" && ( - - window.open("https://en.tipeee.com/pokemon-auto-chess", "_blank") - } - > - {t("donate")} - - - )} +
- {page !== "game" && ( - window.open("https://discord.gg/6JMS7tr", "_blank")} - > - Discord - - )} + {page !== "game" && ( + + window.open("https://en.tipeee.com/pokemon-auto-chess", "_blank") + } + > + {t("donate")} + + + )} - - {leaveLabel} + {page !== "game" && ( + window.open("https://discord.gg/6JMS7tr", "_blank")} + > + Discord - + )} - -
+ + {leaveLabel} + + ) } @@ -270,7 +321,7 @@ type NavPageLink = { handleClick?: (update: Modals) => void } -function NavLink(props: NavLinkProps) { +export function NavLink(props: NavLinkProps) { const { children, location, @@ -280,7 +331,7 @@ function NavLink(props: NavLinkProps) { png, icon, className = "default", - onClick + onClick, } = props return ( @@ -331,7 +382,7 @@ export type Modals = function Modals({ modal, setModal, - page + page, }: { modal?: Modals setModal: (nextModal?: Modals) => void @@ -379,7 +430,7 @@ function Modals({ } + body={} /> void +}) { + return ( +
+ {children} + + Back + +
+ ) +} diff --git a/app/public/src/pages/component/typeahead/pokemon-typeahead.css b/app/public/src/pages/component/typeahead/pokemon-typeahead.css index b42c604611..83f23e92d7 100644 --- a/app/public/src/pages/component/typeahead/pokemon-typeahead.css +++ b/app/public/src/pages/component/typeahead/pokemon-typeahead.css @@ -6,7 +6,7 @@ width: 100%; border: var(--border-thin); padding: 0 0.75rem; - min-height: 1em; + min-height: 2em; } .pokemon-typeahead .form-control::placeholder { diff --git a/app/public/src/pages/component/typeahead/pokemon-typeahead.tsx b/app/public/src/pages/component/typeahead/pokemon-typeahead.tsx index e1a2172d11..e15513b926 100644 --- a/app/public/src/pages/component/typeahead/pokemon-typeahead.tsx +++ b/app/public/src/pages/component/typeahead/pokemon-typeahead.tsx @@ -19,6 +19,7 @@ export function PokemonTypeahead({ onChange, value }: TypeaheadProps) { return ( { - value: string + value?: string onChange: (value: T) => void } diff --git a/app/public/src/pages/component/wiki/wiki-ability.tsx b/app/public/src/pages/component/wiki/wiki-ability.tsx index 395b2c91e4..f25cc40f57 100644 --- a/app/public/src/pages/component/wiki/wiki-ability.tsx +++ b/app/public/src/pages/component/wiki/wiki-ability.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react" +import React, { useCallback, useState } from "react" import ReactDOM from "react-dom" import { useTranslation } from "react-i18next" import { Tooltip } from "react-tooltip" @@ -10,16 +10,54 @@ import { getPortraitSrc } from "../../../utils" import { addIconsToDescription } from "../../utils/descriptions" import { cc } from "../../utils/jsx" import { GamePokemonDetail } from "../game/game-pokemon-detail" +import { debounce } from "../../../../../utils/function" export default function WikiAbility() { const { t } = useTranslation() const [hoveredPokemon, setHoveredPokemon] = useState() + const [search, setSearch] = useState() + + const updateSearch = useCallback( + debounce((e) => setSearch(e.target.value), 300), + [] + ) + + const searchAbilityName = useCallback( + (ability: Ability) => + search && + t(`ability.${ability}`).toLowerCase().includes(search.toLowerCase()), + [search] + ) + + const searchAbilityPokemon = useCallback( + (ability: Ability) => { + if (search == null) { + return true + } + + const pkmList = PRECOMPUTED_POKEMONS_PER_ABILITY[ability] + const found = pkmList.find((pkm) => + pkm.toLowerCase().includes(search.toLowerCase()) + ) + return found != null + }, + [search] + ) return (
+
    {(Object.keys(Ability) as Ability[]) - .filter((a) => a !== Ability.DEFAULT) + .filter( + (a) => + a !== Ability.DEFAULT && + (searchAbilityName(a) || searchAbilityPokemon(a)) + ) .sort((a, b) => t(`ability.${a}`).localeCompare(t(`ability.${b}`))) .map((ability) => { return ( @@ -39,7 +77,7 @@ export default function WikiAbility() {
    { diff --git a/app/public/src/pages/component/wiki/wiki-panel-pokemon.tsx b/app/public/src/pages/component/wiki/wiki-panel-pokemon.tsx new file mode 100644 index 0000000000..f9b0ff47fb --- /dev/null +++ b/app/public/src/pages/component/wiki/wiki-panel-pokemon.tsx @@ -0,0 +1,104 @@ +import React, { memo, useState, useMemo, useCallback, ChangeEvent } from "react" +import { Pkm, PkmIndex } from "../../../../../types/enum/Pokemon" +import { PokemonTypeahead } from "../typeahead/pokemon-typeahead" +import { Rarity } from "../../../../../types/enum/Game" +import { RarityColor } from "../../../../../types/Config" +import { t } from "i18next" +import { WikiAllPokemons, WikiPokemon } from "./wiki-pokemons" +import { GamePokemonDetail } from "../game/game-pokemon-detail" +import { getPokemonData } from "../../../../../models/precomputed/precomputed-pokemon-data" +import { getPortraitSrc } from "../../../utils" +import Credits from "./Credits" + +export const WikiPanelPokemon = memo(() => { + const [pokemon, setPokemon] = useState() + const options = useMemo(() => [...Object.values(Rarity), "all"], []) + const [optionIndex, setOptionIndex] = useState(0) + const view = options[optionIndex] + + const updateOption = useCallback((e: ChangeEvent) => { + setOptionIndex(Number(e.currentTarget.value)) + setPokemon(undefined) + }, []) + + return ( +
    + + + + {!pokemon && + (view === "all" ? ( + + ) : ( + + ))} + + {pokemon && ( + <> + + + + )} +
    + ) +}) + +export const WikiPanelPokemonDetail = memo(({ pokemon }: { pokemon: Pkm }) => { + const data = useMemo(() => getPokemonData(pokemon), [pokemon]) + return ( +
    +
    + +
    +
    +
    {t("index")}
    +
    {data.index}
    +
    {t("pool_label")}
    +
    + {t( + `pool.${ + data.regional + ? "regional" + : data.additional + ? "additional" + : "regular" + }` + )} +
    +
    {t("evolution")}
    +
    + {!data.evolution ? ( + "No evolution" + ) : ( + <> + + {t(`pkm.${data.evolution}`)} + + )} +
    +
    {t("portrait_credit")}
    + + +
    {t("sprite_credit")}
    + +
    +
    + ) +}) diff --git a/app/public/src/pages/component/wiki/wiki-panel.css b/app/public/src/pages/component/wiki/wiki-panel.css new file mode 100644 index 0000000000..bfd73a10b2 --- /dev/null +++ b/app/public/src/pages/component/wiki/wiki-panel.css @@ -0,0 +1,151 @@ +.wiki-panel { + --top-height: 40px; + --top-padding: 12px; + + display: grid; + grid-template-areas: 'select' 'content'; + grid-template-rows: var(--top-height) 1fr; + gap: var(--top-padding); + padding: var(--top-padding) 8px; + min-height: calc(100vh - var(--top-height) - var(--top-padding)); + max-width: 20vw; + +} + +.wiki-page-select { + grid-area: select; + position: sticky; + top: 12px; + z-index: 1; +} + +.wiki-content { + grid-area: content; + width: 100%; + min-width: 300px; +} + +.wiki-content li { + list-style: none; +} + +.wiki-content ul { + padding: 0; + display: flex; + flex-direction: column; + gap: 8px; +} + +.uppercase { + text-transform: uppercase; +} + +.wiki-panel-pokemon { + display: flex; + flex-direction: column; + gap: 8px; +} + +.wiki-content .wiki-panel-pokemon ul { + flex-direction: row; + flex-wrap: wrap; + gap: 4px; +} + +.wiki-panel-pokemon li { + padding: 4px; + background: none; +} + +.wiki-panel-pokemon-detail { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; +} + +.wiki-panel-pokemon-detail-pokemon { +} + +.wiki-panel-pokemon-detail-list { + display: grid; + grid-template-columns: 1fr 1fr; + color: white; + width: 316px; + column-gap: 12px; +} + +button.close { + position: absolute; + right: 16px; + top: 6px; + color: white; +} + +.wiki-panel-pokemon #wiki-pokemons-all { + display: flex; + flex-direction: column; + gap: 8px; +} + +.wiki-panel-pokemon #wiki-pokemons-all section { + width: 100%; +} + +.wiki-types ul, +#wiki-items article ul, +#wiki-weather .my-box ul, +#wiki-ability .my-box ul { + flex-direction: row; + flex-wrap: wrap; +} + +#wiki-ability { + display: flex; + flex-direction: column; + gap: 8px; +} + +#wiki-ability input { + width: 100%; +} + +#wiki-dungeon .my-box img { + max-width: -webkit-fill-available; + max-width: fill-available; +} + +#wiki-weather img { + max-width: 100px; +} + +#wiki-items img { + width: 100%; + min-width: 30px; + max-width: 50px; +} + +.wiki-types table tbody { + display: flex; + flex-direction: column; + gap: 8px; +} + +.wiki-types table tr td:last-of-type { + display: flex; + flex-wrap: wrap; +} + +.wiki-types div { + flex-direction: column; + align-items: flex-start !important; +} + +#wiki-types-all section { + width: 100%; +} + +.wiki-types > ul { + width: 100%; + min-width: 320px; +} diff --git a/app/public/src/pages/component/wiki/wiki-panel.tsx b/app/public/src/pages/component/wiki/wiki-panel.tsx new file mode 100644 index 0000000000..acb516c75d --- /dev/null +++ b/app/public/src/pages/component/wiki/wiki-panel.tsx @@ -0,0 +1,95 @@ +import { t } from "i18next" +import React, { memo, useMemo, useState } from "react" +import WikiAbility from "./wiki-ability" +import { WikiDungeon } from "./wiki-dungeon" +import WikiFaq from "./wiki-faq" +import WikiItems from "./wiki-items" +import WikiStatistic from "./wiki-statistic" +import WikiStatus from "./wiki-status" +import WikiTutorials from "./wiki-tutorials" +import WikiTypes from "./wiki-types" +import WikiWeather from "./wiki-weather" + +import "./wiki-panel.css" +import { WikiPanelPokemon } from "./wiki-panel-pokemon" + +const PAGES = [ + { + displayName: "faq.faq", + Component: WikiFaq, + showInGame: false, + }, + { + displayName: "how_to_play", + Component: WikiTutorials, + showInGame: false, + }, + { + displayName: "pokemons_label", + Component: WikiPanelPokemon, + showInGame: true, + }, + { + displayName: "abilities_label", + Component: WikiAbility, + showInGame: true, + }, + { + displayName: "items_label", + Component: WikiItems, + showInGame: true, + }, + { + displayName: "synergies_label", + Component: WikiTypes, + showInGame: true, + }, + { + displayName: "statistics_label", + Component: WikiStatistic, + showInGame: true, + }, + { + displayName: "status_label", + Component: WikiStatus, + showInGame: true, + }, + { + displayName: "weather_label", + Component: WikiWeather, + showInGame: true, + }, + { + displayName: "dungeon_label", + Component: WikiDungeon, + showInGame: true, + }, +] + +export const WikiPanel = memo(({ inGame }: { inGame: boolean }) => { + const validPages = useMemo( + () => PAGES.filter((page) => !inGame || page.showInGame), + [inGame] + ) + const [tabIndex, setTabIndex] = useState(0) + + const Component = validPages[tabIndex].Component + + return ( +
    + +
    + +
    +
    + ) +}) diff --git a/app/public/src/pages/component/wiki/wiki-pokemons.tsx b/app/public/src/pages/component/wiki/wiki-pokemons.tsx index 7d2933c188..29672b8efe 100644 --- a/app/public/src/pages/component/wiki/wiki-pokemons.tsx +++ b/app/public/src/pages/component/wiki/wiki-pokemons.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useMemo } from "react" +import React, { useEffect, useState, useMemo, useCallback } from "react" import { useTranslation } from "react-i18next" import { Tab, TabList, TabPanel, Tabs } from "react-tabs" import { RarityColor } from "../../../../../types/Config" @@ -21,31 +21,27 @@ import ReactDOM from "react-dom" export default function WikiPokemons() { const { t } = useTranslation() const tabs = Object.values(Rarity) as Rarity[] - const [selectedPkm, setSelectedPkm] = useState("") + const [selectedPkm, setSelectedPkm] = useState() const [tabIndex, setTabIndex] = useState(0) - useEffect(() => { - if (selectedPkm) { - setTabIndex(tabs.indexOf(getPokemonData(selectedPkm).rarity)) + + const selectPokemon = useCallback((pokemon: Pkm | number) => { + if (typeof pokemon === "number") { + setTabIndex(pokemon) + setSelectedPkm(selectedPkm) + } else { + const index = tabs.indexOf(getPokemonData(pokemon).rarity) + setTabIndex(index) + setSelectedPkm(pokemon) } - }, [selectedPkm, tabs]) + }, []) return ( { - setSelectedPkm("") - setTabIndex(index) - }} + onSelect={selectPokemon} > - { - if (pkm) { - setSelectedPkm(pkm) - } - }} - /> + {tabs.map((r) => { return ( @@ -77,10 +73,10 @@ export default function WikiPokemons() { export function WikiPokemon(props: { rarity: Rarity - selected: Pkm | "" + selected?: Pkm onSelect: (pkm: Pkm) => void }) { - const pokemons = useMemo( + const pokemons: Pkm[] = useMemo( () => PRECOMPUTED_POKEMONS_PER_RARITY[props.rarity] .filter((p) => p !== Pkm.DEFAULT) @@ -97,18 +93,21 @@ export function WikiPokemon(props: { selectedIndex={props.selected ? pokemons.indexOf(props.selected) : -1} onSelect={(index) => props.onSelect(pokemons[index])} > - - {pokemons.map((pkm) => { - return ( - - - - ) - })} - + { + + {!props.selected && + pokemons.map((pkm) => { + return ( + + + + ) + })} + + } {pokemons.map((pkm) => { return ( @@ -156,7 +155,7 @@ export function WikiAllPokemons() { key={p.name} className={cc("pokemon-portrait", { additional: p.additional, - regional: p.regional + regional: p.regional, })} onMouseOver={() => { setHoveredPokemon(p.name) diff --git a/app/public/src/pages/component/wiki/wiki.css b/app/public/src/pages/component/wiki/wiki.css index 4eda1061dc..a8e03eb107 100644 --- a/app/public/src/pages/component/wiki/wiki.css +++ b/app/public/src/pages/component/wiki/wiki.css @@ -52,7 +52,7 @@ } #wiki-page .wiki-pokemons .pokemon-typeahead { - float: right; + float: left; } #wiki-page p.description { @@ -305,3 +305,17 @@ padding: 4px; } } + +#wiki-page.wiki-sidebar { + width: 100%; +} + +#wiki-page.wiki-sidebar ul { + flex-direction: row; + flex-wrap: wrap; +} + +#wiki-page.wiki-sidebar .my-container { + border-radius: 0; + border: 0; +} diff --git a/app/public/src/pages/component/wiki/wiki.tsx b/app/public/src/pages/component/wiki/wiki.tsx index 4a87e05b48..fe41b3d91c 100644 --- a/app/public/src/pages/component/wiki/wiki.tsx +++ b/app/public/src/pages/component/wiki/wiki.tsx @@ -13,10 +13,16 @@ import WikiTypes from "./wiki-types" import WikiWeather from "./wiki-weather" import "./wiki.css" -export default function Wiki({ inGame = false }: { inGame: boolean }) { +export default function Wiki({ + inGame = false, + inSidebar = false, +}: { + inGame: boolean + inSidebar?: boolean +}) { const { t } = useTranslation() return ( -
    +