mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: large warning
This commit is contained in:
1 parent
7becb7b6ad
commit
437bbfdc89
2 files changed
+136
-74
No files matched your search
@@ -881,6 +881,13 @@
|
||||
"wins": "Wins"
|
||||
},
|
||||
|
||||
"large_warning": {
|
||||
"title": "That's a lot of tanks!",
|
||||
"description": "Are you sure you want to create a playlist of {count} tanks? That's {time} hours of gameplay at 50% winrate!",
|
||||
"cancel": "Cancel",
|
||||
"proceed": "Proceed"
|
||||
},
|
||||
|
||||
"generate": "Generate playlist",
|
||||
"name": "Playlist",
|
||||
"description": "Tank playlist generator",
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import { fisherYates, tankIcon } from "@blitzkit/core";
|
||||
import { literals } from "@blitzkit/i18n";
|
||||
import { Box, Button, Flex, Grid, Skeleton, Text } from "@radix-ui/themes";
|
||||
import { useMemo } from "react";
|
||||
import { ChevronRightIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
AlertDialog,
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Grid,
|
||||
Skeleton,
|
||||
Text,
|
||||
} from "@radix-ui/themes";
|
||||
import { useMemo, useState } from "react";
|
||||
import usePromise from "react-promise-suspense";
|
||||
import { awaitableTankDefinitions } from "../core/awaitables/tankDefinitions";
|
||||
import { filterTanks } from "../core/blitzkit/filterTanks";
|
||||
@@ -18,6 +27,7 @@ const tankDefinitions = await awaitableTankDefinitions;
|
||||
const POOL_HEIGHT = "16rem";
|
||||
|
||||
export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
const [largeWarningOpen, setLargeWarningOpen] = useState(false);
|
||||
const { strings, locale } = useLocale();
|
||||
const wargaming = App.use((state) => state.logins.wargaming);
|
||||
const filters = TankFilters.use();
|
||||
@@ -33,84 +43,129 @@ export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
const tanksTrimmed = useMemo(() => tanks.slice(0, 65), [filters]);
|
||||
|
||||
return (
|
||||
<Flex justify="center" width="100%" align="center">
|
||||
<Flex
|
||||
flexGrow="1"
|
||||
gap="9"
|
||||
align="center"
|
||||
justify="center"
|
||||
maxWidth="80rem"
|
||||
<>
|
||||
<AlertDialog.Root
|
||||
open={largeWarningOpen}
|
||||
onOpenChange={setLargeWarningOpen}
|
||||
>
|
||||
<Flex direction="column" gap="4" align="center">
|
||||
<FilterControl />
|
||||
|
||||
<Button onClick={generatePlaylist} size="3">
|
||||
{strings.website.tools.playlist.generate}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
direction="column"
|
||||
flexGrow="1"
|
||||
flexBasis="0"
|
||||
align="center"
|
||||
gap="4"
|
||||
>
|
||||
<Grid
|
||||
columns="repeat(auto-fill, minmax(4rem, 1fr))"
|
||||
flow="dense"
|
||||
overflow="hidden"
|
||||
position="relative"
|
||||
maxHeight={POOL_HEIGHT}
|
||||
width="100%"
|
||||
>
|
||||
{tanksTrimmed.map((tank) =>
|
||||
skeleton ? (
|
||||
<Box
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{ aspectRatio: "4 / 3" }}
|
||||
p="1"
|
||||
>
|
||||
<Skeleton width="100%" height="100%" />
|
||||
</Box>
|
||||
) : (
|
||||
<LinkI18n
|
||||
target="_blank"
|
||||
locale={locale}
|
||||
href={`/tanks/${tank.slug}`}
|
||||
key={tank.id}
|
||||
style={{
|
||||
aspectRatio: "4 / 3",
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
backgroundImage: `url(${tankIcon(tank.id)})`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
}}
|
||||
/>
|
||||
)
|
||||
<AlertDialog.Content>
|
||||
<AlertDialog.Title>
|
||||
{strings.website.tools.playlist.large_warning.title}
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description>
|
||||
{literals(
|
||||
strings.website.tools.playlist.large_warning.description,
|
||||
{
|
||||
count: tanks.length,
|
||||
time: Math.round(tanks.length * ((2 * 4) / 60)),
|
||||
}
|
||||
)}
|
||||
</AlertDialog.Description>
|
||||
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{
|
||||
pointerEvents: "none",
|
||||
background: `linear-gradient(transparent, var(--gray-1) ${POOL_HEIGHT})`,
|
||||
<Flex justify="end" gap="2" mt="4">
|
||||
<AlertDialog.Cancel>
|
||||
<Button variant="outline">
|
||||
{strings.website.tools.playlist.large_warning.cancel}
|
||||
</Button>
|
||||
</AlertDialog.Cancel>
|
||||
<AlertDialog.Action onClick={generatePlaylist}>
|
||||
<Button color="red">
|
||||
{strings.website.tools.playlist.large_warning.proceed}
|
||||
</Button>
|
||||
</AlertDialog.Action>
|
||||
</Flex>
|
||||
</AlertDialog.Content>
|
||||
</AlertDialog.Root>
|
||||
|
||||
<Flex justify="center" width="100%" align="center">
|
||||
<Flex
|
||||
flexGrow="1"
|
||||
gap="9"
|
||||
align="center"
|
||||
justify="center"
|
||||
maxWidth="80rem"
|
||||
>
|
||||
<Flex direction="column" gap="4" align="center">
|
||||
<FilterControl />
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (tanks.length >= 32) {
|
||||
setLargeWarningOpen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
generatePlaylist();
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
size="3"
|
||||
>
|
||||
{strings.website.tools.playlist.generate} <ChevronRightIcon />
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Text color="gray">
|
||||
{literals(strings.website.tools.playlist.pool_size, {
|
||||
count: tanks.length,
|
||||
})}
|
||||
</Text>
|
||||
<Flex
|
||||
direction="column"
|
||||
flexGrow="1"
|
||||
flexBasis="0"
|
||||
align="center"
|
||||
gap="4"
|
||||
>
|
||||
<Grid
|
||||
columns="repeat(auto-fill, minmax(4rem, 1fr))"
|
||||
flow="dense"
|
||||
overflow="hidden"
|
||||
position="relative"
|
||||
maxHeight={POOL_HEIGHT}
|
||||
width="100%"
|
||||
>
|
||||
{tanksTrimmed.map((tank) =>
|
||||
skeleton ? (
|
||||
<Box
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{ aspectRatio: "4 / 3" }}
|
||||
p="1"
|
||||
>
|
||||
<Skeleton width="100%" height="100%" />
|
||||
</Box>
|
||||
) : (
|
||||
<LinkI18n
|
||||
target="_blank"
|
||||
locale={locale}
|
||||
href={`/tanks/${tank.slug}`}
|
||||
key={tank.id}
|
||||
style={{
|
||||
aspectRatio: "4 / 3",
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
backgroundImage: `url(${tankIcon(tank.id)})`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{
|
||||
pointerEvents: "none",
|
||||
background: `linear-gradient(transparent, var(--gray-1) ${POOL_HEIGHT})`,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Text color="gray">
|
||||
{literals(strings.website.tools.playlist.pool_size, {
|
||||
count: tanks.length,
|
||||
})}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user