From 798ef10469101e7566992c7dcb30d610a11b6933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:10:23 -0500 Subject: [PATCH] feat: skeletons --- .../tools/tankopedia/components/NoResults.tsx | 30 +++++++++++++++++ .../tools/tankopedia/components/Results.tsx | 32 ++++++++++++++++--- .../tools/tankopedia/components/SearchBar.tsx | 8 ++--- .../components/SkeletonTankCard.tsx | 10 ++++++ .../tankopedia/components/TankCardWrapper.tsx | 1 + .../tools/tankopedia/components/TierCard.tsx | 28 ++-------------- src/app/tools/tankopedia/page.tsx | 11 +------ src/stores/tankopediaFilters.ts | 2 ++ 8 files changed, 78 insertions(+), 44 deletions(-) create mode 100644 src/app/tools/tankopedia/components/NoResults.tsx create mode 100644 src/app/tools/tankopedia/components/SkeletonTankCard.tsx diff --git a/src/app/tools/tankopedia/components/NoResults.tsx b/src/app/tools/tankopedia/components/NoResults.tsx new file mode 100644 index 000000000..c4c32c300 --- /dev/null +++ b/src/app/tools/tankopedia/components/NoResults.tsx @@ -0,0 +1,30 @@ +import { Flex, Link, Text } from '@radix-ui/themes'; +import { useTankopediaFilters } from '../../../../stores/tankopediaFilters'; + +interface NoResultsProps { + type?: 'filters' | 'search'; +} + +export function NoResults({ type = 'filters' }: NoResultsProps) { + return ( + + + No tanks found.{' '} + + useTankopediaFilters.setState( + useTankopediaFilters.getInitialState(), + true, + ) + } + > + {type === 'filters' ? 'Try clearing filters' : 'Try searching again'} + + . + + + ); +} diff --git a/src/app/tools/tankopedia/components/Results.tsx b/src/app/tools/tankopedia/components/Results.tsx index 7285b3bef..440ab02ad 100644 --- a/src/app/tools/tankopedia/components/Results.tsx +++ b/src/app/tools/tankopedia/components/Results.tsx @@ -1,5 +1,6 @@ import { Callout, Flex } from '@radix-ui/themes'; import { go } from 'fuzzysort'; +import { times } from 'lodash'; import { memo, use, useMemo } from 'react'; import { ExperimentIcon } from '../../../../components/ExperimentIcon'; import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration'; @@ -16,7 +17,9 @@ import { import { unionBoundingBox } from '../../../../core/blitzkit/unionBoundingBox'; import { useTankopediaFilters } from '../../../../stores/tankopediaFilters'; import { FilterControl } from './FilterControl'; +import { NoResults } from './NoResults'; import { SearchBar } from './SearchBar'; +import { SkeletonTankCard } from './SkeletonTankCard'; import { TankCard } from './TankCard'; import { TankCardWrapper } from './TankCardWrapper'; import { TierCard } from './TierCard'; @@ -30,6 +33,7 @@ export const Results = memo(() => { const search = useTankopediaFilters((state) => state.search); const tier = useTankopediaFilters((state) => state.tier); const sort = useTankopediaFilters((state) => state.sort); + const searching = useTankopediaFilters((state) => state.searching); const searchedTanks = useMemo(() => { if (search !== undefined) { const searchedRaw = go(search, awaitedTankNames, { @@ -330,7 +334,7 @@ export const Results = memo(() => { - {!search && } + {!search && !searching && } {testing === 'only' && ( @@ -346,11 +350,29 @@ export const Results = memo(() => { )} - {!search && sort.by === 'meta.tier' && } + {!search && sort.by === 'meta.tier' && !searching && ( + + )} - {(search || sort.by !== 'meta.tier') && ( - - {searchedTanks?.map((tank) => )} + {(search || sort.by !== 'meta.tier') && !searching && searchedTanks && ( + <> + {searchedTanks.length > 0 && ( + + {searchedTanks.map((tank) => ( + + ))} + + )} + + {searchedTanks.length === 0 && } + + )} + + {searching && ( + + {times(Math.round(10 + 10 * Math.random()), (index) => ( + + ))} )} diff --git a/src/app/tools/tankopedia/components/SearchBar.tsx b/src/app/tools/tankopedia/components/SearchBar.tsx index 0deb97b33..e5287fcba 100644 --- a/src/app/tools/tankopedia/components/SearchBar.tsx +++ b/src/app/tools/tankopedia/components/SearchBar.tsx @@ -2,7 +2,7 @@ import { CaretRightIcon, MagnifyingGlassIcon } from '@radix-ui/react-icons'; import { Button, Flex, Spinner, TextField } from '@radix-ui/themes'; import { debounce } from 'lodash'; import { useRouter } from 'next/navigation'; -import { KeyboardEventHandler, useCallback, useRef, useState } from 'react'; +import { KeyboardEventHandler, useCallback, useRef } from 'react'; import { Link } from '../../../../components/Link'; import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions'; import { useTankopediaFilters } from '../../../../stores/tankopediaFilters'; @@ -14,11 +14,11 @@ interface SearchBarProps { export function SearchBar({ topResult }: SearchBarProps) { const router = useRouter(); - const [searching, setSearching] = useState(false); const input = useRef(null); + const searching = useTankopediaFilters((state) => state.searching); const search = useCallback( debounce(() => { - setSearching(false); + useTankopediaFilters.setState({ searching: false }); if (!input.current) return; @@ -31,7 +31,7 @@ export function SearchBar({ topResult }: SearchBarProps) { [], ); const handleChange = useCallback(() => { - setSearching(true); + useTankopediaFilters.setState({ searching: true }); search(); }, []); const handleKeyDown = useCallback( diff --git a/src/app/tools/tankopedia/components/SkeletonTankCard.tsx b/src/app/tools/tankopedia/components/SkeletonTankCard.tsx new file mode 100644 index 000000000..5aaff521e --- /dev/null +++ b/src/app/tools/tankopedia/components/SkeletonTankCard.tsx @@ -0,0 +1,10 @@ +import { Flex, Skeleton } from '@radix-ui/themes'; + +export function SkeletonTankCard() { + return ( + + + + + ); +} diff --git a/src/app/tools/tankopedia/components/TankCardWrapper.tsx b/src/app/tools/tankopedia/components/TankCardWrapper.tsx index 73bbde572..67fc8940d 100644 --- a/src/app/tools/tankopedia/components/TankCardWrapper.tsx +++ b/src/app/tools/tankopedia/components/TankCardWrapper.tsx @@ -3,6 +3,7 @@ import { Grid, GridProps } from '@radix-ui/themes'; export function TankCardWrapper(props: GridProps) { return ( - - No tanks found.{' '} - - useTankopediaFilters.setState( - useTankopediaFilters.getInitialState(), - true, - ) - } - > - Try clearing filters - - . - - - ); + if (tanks.length === 0) return ; return ( - + {tanks.map((tank) => ( ))} diff --git a/src/app/tools/tankopedia/page.tsx b/src/app/tools/tankopedia/page.tsx index 76231debb..f27557f56 100644 --- a/src/app/tools/tankopedia/page.tsx +++ b/src/app/tools/tankopedia/page.tsx @@ -1,21 +1,12 @@ 'use client'; -import { Flex } from '@radix-ui/themes'; import PageWrapper from '../../../components/PageWrapper'; import { Results } from './components/Results'; export default function Page() { return ( - - {/* */} - - + ); } diff --git a/src/stores/tankopediaFilters.ts b/src/stores/tankopediaFilters.ts index fb1c4a154..ffcaeb958 100644 --- a/src/stores/tankopediaFilters.ts +++ b/src/stores/tankopediaFilters.ts @@ -15,6 +15,7 @@ export interface TankopediaFilters { by: TankopediaSortBy; direction: TankopediaSortDirection; }; + searching: boolean; } export const useTankopediaFilters = create()(() => ({ @@ -24,6 +25,7 @@ export const useTankopediaFilters = create()(() => ({ direction: 'descending', }, tier: 10, + searching: false, })); export function mutateTankopediaFilters(