mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: skeletons
This commit is contained in:
1 parent
fe945cced1
commit
798ef10469
8 files changed
+78
-44
No files matched your search
@@ -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 (
|
||||
<Flex flexGrow="1" align="center" justify="center">
|
||||
<Text color="gray">
|
||||
No tanks found.{' '}
|
||||
<Link
|
||||
href="#"
|
||||
underline="always"
|
||||
color="red"
|
||||
onClick={() =>
|
||||
useTankopediaFilters.setState(
|
||||
useTankopediaFilters.getInitialState(),
|
||||
true,
|
||||
)
|
||||
}
|
||||
>
|
||||
{type === 'filters' ? 'Try clearing filters' : 'Try searching again'}
|
||||
</Link>
|
||||
.
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -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(() => {
|
||||
<Flex direction="column" gap="4" flexGrow="1">
|
||||
<SearchBar topResult={searchedTanks?.[0]} />
|
||||
|
||||
{!search && <FilterControl />}
|
||||
{!search && !searching && <FilterControl />}
|
||||
|
||||
{testing === 'only' && (
|
||||
<Flex justify="center" mt="4">
|
||||
@@ -346,11 +350,29 @@ export const Results = memo(() => {
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{!search && sort.by === 'meta.tier' && <TierCard tier={tier} />}
|
||||
{!search && sort.by === 'meta.tier' && !searching && (
|
||||
<TierCard tier={tier} />
|
||||
)}
|
||||
|
||||
{(search || sort.by !== 'meta.tier') && (
|
||||
<TankCardWrapper py="4">
|
||||
{searchedTanks?.map((tank) => <TankCard key={tank.id} tank={tank} />)}
|
||||
{(search || sort.by !== 'meta.tier') && !searching && searchedTanks && (
|
||||
<>
|
||||
{searchedTanks.length > 0 && (
|
||||
<TankCardWrapper>
|
||||
{searchedTanks.map((tank) => (
|
||||
<TankCard key={tank.id} tank={tank} />
|
||||
))}
|
||||
</TankCardWrapper>
|
||||
)}
|
||||
|
||||
{searchedTanks.length === 0 && <NoResults type="search" />}
|
||||
</>
|
||||
)}
|
||||
|
||||
{searching && (
|
||||
<TankCardWrapper>
|
||||
{times(Math.round(10 + 10 * Math.random()), (index) => (
|
||||
<SkeletonTankCard key={index} />
|
||||
))}
|
||||
</TankCardWrapper>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
@@ -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<HTMLInputElement>(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<KeyboardEventHandler>(
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Flex, Skeleton } from '@radix-ui/themes';
|
||||
|
||||
export function SkeletonTankCard() {
|
||||
return (
|
||||
<Flex direction="column" gap="2">
|
||||
<Skeleton height="64px" />
|
||||
<Skeleton height="1em" />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { Grid, GridProps } from '@radix-ui/themes';
|
||||
export function TankCardWrapper(props: GridProps) {
|
||||
return (
|
||||
<Grid
|
||||
py="4"
|
||||
columns="repeat(auto-fill, minmax(100px, 1fr))"
|
||||
gap="2"
|
||||
gapY="6"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Flex, Text } from '@radix-ui/themes';
|
||||
import { memo, use, useMemo } from 'react';
|
||||
import { Link } from '../../../../components/Link';
|
||||
import { TANK_CLASSES } from '../../../../components/Tanks/components/Item/constants';
|
||||
import { gameDefinitions } from '../../../../core/blitzkit/gameDefinitions';
|
||||
import {
|
||||
@@ -9,6 +7,7 @@ import {
|
||||
} from '../../../../core/blitzkit/tankDefinitions';
|
||||
import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank';
|
||||
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
|
||||
import { NoResults } from './NoResults';
|
||||
import { TankCard } from './TankCard';
|
||||
import { TankCardWrapper } from './TankCardWrapper';
|
||||
import { treeTypeOrder } from './TankSearch/constants';
|
||||
@@ -43,31 +42,10 @@ export const TierCard = memo(
|
||||
[tier, filters],
|
||||
);
|
||||
|
||||
if (tanks.length === 0)
|
||||
return (
|
||||
<Flex flexGrow="1" align="center" justify="center">
|
||||
<Text color="gray">
|
||||
No tanks found.{' '}
|
||||
<Link
|
||||
href="#"
|
||||
underline="always"
|
||||
color="red"
|
||||
onClick={() =>
|
||||
useTankopediaFilters.setState(
|
||||
useTankopediaFilters.getInitialState(),
|
||||
true,
|
||||
)
|
||||
}
|
||||
>
|
||||
Try clearing filters
|
||||
</Link>
|
||||
.
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
if (tanks.length === 0) return <NoResults />;
|
||||
|
||||
return (
|
||||
<TankCardWrapper mt="6">
|
||||
<TankCardWrapper>
|
||||
{tanks.map((tank) => (
|
||||
<TankCard key={tank.id} tank={tank} />
|
||||
))}
|
||||
|
||||
@@ -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 (
|
||||
<PageWrapper color="purple" size={1028}>
|
||||
<Flex
|
||||
gap="8"
|
||||
direction={{ initial: 'column', sm: 'row' }}
|
||||
py="4"
|
||||
flexGrow="1"
|
||||
>
|
||||
{/* <FilterControl /> */}
|
||||
<Results />
|
||||
</Flex>
|
||||
<Results />
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
@@ -15,6 +15,7 @@ export interface TankopediaFilters {
|
||||
by: TankopediaSortBy;
|
||||
direction: TankopediaSortDirection;
|
||||
};
|
||||
searching: boolean;
|
||||
}
|
||||
|
||||
export const useTankopediaFilters = create<TankopediaFilters>()(() => ({
|
||||
@@ -24,6 +25,7 @@ export const useTankopediaFilters = create<TankopediaFilters>()(() => ({
|
||||
direction: 'descending',
|
||||
},
|
||||
tier: 10,
|
||||
searching: false,
|
||||
}));
|
||||
|
||||
export function mutateTankopediaFilters(
|
||||
|
||||
Reference in new issue
Block a user