feat: code split

This commit is contained in:
TrèsAbhi committed 2025-05-30 15:06:44 -05:00
1 parent 2c2c3687c7
commit 3aafe4d9f1
6 files changed
+179 -83

No files matched your search

@@ -0,0 +1,78 @@
import type { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
import type { SellableComponent } from '@protos/blitz_static_sellable_component';
import type { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
import { Badge, Box, Flex, Text } from '@radix-ui/themes';
import { literals } from 'packages/i18n/src';
import { Var } from '../../core/radix/var';
import { useLocale } from '../../hooks/useLocale';
interface AvatarGroupProps {
name: string;
avatars: {
stuff: StuffUIComponent;
avatar: ProfileAvatarComponent;
sellable: SellableComponent;
}[];
}
const dx = '4px';
const MAX_AVATARS_PREVIEW = 5;
export function AvatarGroup({ avatars, name }: AvatarGroupProps) {
const { strings } = useLocale();
const avatarsReduced = [...avatars].reverse().slice(0, MAX_AVATARS_PREVIEW);
return (
<Flex direction="column" gap="3">
<Box width="100%" style={{ aspectRatio: '7 / 8' }} position="relative">
{avatarsReduced.map((avatar, index) => (
<Box
position="absolute"
top={`calc(${dx} * ${index})`}
left={`calc(${dx} * ${index})`}
width={`calc(100% - ${dx} * ${avatarsReduced.length - 1})`}
height={`calc(100% - ${dx} * ${avatarsReduced.length - 1})`}
style={{
filter: `brightness(${(index + 1) / avatarsReduced.length})`,
borderRadius: Var('radius-2'),
boxShadow: Var('shadow-3'),
backgroundImage: `url(${avatar.avatar.avatar})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
>
{avatars.length > 1 && (
<Box
width="100%"
height="100%"
style={{
background: `linear-gradient(-45deg, ${Var('black-a9')} 25%, ${Var('black-a1')} 50%)`,
}}
/>
)}
</Box>
))}
{avatars.length > 1 && (
<Box position="absolute" bottom="1" right="1">
<Badge variant="solid" color="gray" highContrast size="2">
{literals(strings.common.units.times, [`${avatars.length}`])}
</Badge>
</Box>
)}
</Box>
<Text
size="2"
wrap="nowrap"
align="center"
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{name}
</Text>
</Flex>
);
}
@@ -0,0 +1,33 @@
---
import { AstroSeo } from '@astrolib/seo';
import { type Tool } from '../constants/tools';
import { getStrings } from '../core/i18n/getStrings';
interface Props {
tool: Tool;
locale: string;
}
const { tool, locale } = Astro.props;
const strings = await getStrings(locale);
const toolStrings =
strings.website.tools[
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
];
---
<AstroSeo
title={toolStrings.name}
description={toolStrings.seo_description}
canonical={Astro.url.href}
openGraph={{
url: Astro.url.href,
images: [
{ url: `${Astro.url.origin}/assets/images/tools/${tool.id}.webp` },
],
title: toolStrings.name,
description: toolStrings.seo_description,
site_name: 'BlitzKit',
}}
twitter={{ cardType: 'summary_large_image' }}
/>
@@ -0,0 +1,45 @@
---
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
import ToolOpenGraph from '../components/ToolOpenGraph.astro';
import { type Tool } from '../constants/tools';
import { getStrings } from '../core/i18n/getStrings';
import BaseLayout from './BaseLayout.astro';
interface Props {
tool: Tool;
locale: string;
}
const { tool, locale } = Astro.props;
const strings = await getStrings(locale);
const toolStrings =
strings.website.tools[
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
];
---
<ToolOpenGraph {locale} tool={tool} />
<BaseLayout {locale}>
<Box
style={{
backgroundImage: `url(/assets/tool-backgrounds/${tool.id}.webp)`,
backgroundSize: 'cover',
}}
>
<Flex
direction="column"
align="center"
py="6"
style={{
backdropFilter: 'blur(4rem)',
WebkitBackdropFilter: 'blur(4rem)',
}}
>
<Heading size="7">{toolStrings.name}</Heading>
<Text>{toolStrings.description}</Text>
</Flex>
</Box>
<slot />
</BaseLayout>
@@ -1,12 +1,12 @@
import { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
import { SellableComponent } from '@protos/blitz_static_sellable_component';
import { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
import { BlitzkitAllAvatarsComponent } from '@protos/blitzkit_static_all_avatars_component';
import { Badge, Box, Flex, Grid, Text } from '@radix-ui/themes';
import { Grid } from '@radix-ui/themes';
import { CatalogItemAccessor } from 'packages/core/src/blitz/catalogItemAccessor';
import { literals } from 'packages/i18n/src';
import { AvatarGroup } from 'packages/website-ue/src/components/Avatars/Group';
import { PageWrapper } from 'packages/website-ue/src/components/PageWrapper';
import { metadata } from 'packages/website-ue/src/core/blitz/metadata';
import { Var } from 'packages/website-ue/src/core/radix/var';
import {
LocaleProvider,
useLocale,
@@ -30,27 +30,25 @@ export function Page({ localeData }: LocaleAcceptorProps) {
);
}
const dx = '4px';
const MAX_AVATARS_PREVIEW = 5;
function Content() {
const { gameStrings, strings } = useLocale();
const groups = useMemo(() => {
const avatars = allAvatars
.map((avatar) => {
const item = new CatalogItemAccessor(avatar);
const stuffComponent = item.get(StuffUIComponent, 'UIComponent');
const avatarComponent = item.get(
.map((id) => {
const item = new CatalogItemAccessor(id);
const stuff = item.get(StuffUIComponent, 'UIComponent');
const avatar = item.get(
ProfileAvatarComponent,
'profileAvatarComponent',
);
const sellable = item.get(SellableComponent, 'sellableComponent');
const name =
gameStrings[stuffComponent.display_name] ??
strings.website.tools.avatars.unnamed_avatar;
gameStrings[stuff.display_name] ??
strings.website.tools.avatars.unnamed_avatar; // maybe move to dumb component?
return { avatar, name, stuffComponent, avatarComponent };
return { avatar, name, stuff, sellable };
})
.sort((a, b) => a.stuffComponent.grade - b.stuffComponent.grade)
.sort((a, b) => a.stuff.grade - b.stuff.grade)
.sort((a, b) => a.name.localeCompare(b.name));
const groups: Record<string, typeof avatars> = {};
@@ -68,77 +66,18 @@ function Content() {
return (
<PageWrapper>
<Grid
columns="repeat(auto-fill, minmax(8rem, 1fr))"
columns={{
initial: 'repeat(auto-fill, minmax(6rem, 1fr))',
xs: 'repeat(auto-fill, minmax(8rem, 1fr))',
}}
flow="dense"
gapX="4"
gapY="6"
flexGrow="1"
>
{groups.map(([name, avatars]) => {
const avatarsReduced = [...avatars]
.reverse()
.slice(0, MAX_AVATARS_PREVIEW);
return (
<Flex direction="column" gap="3" key={name}>
<Box
width="100%"
style={{ aspectRatio: '7 / 8' }}
position="relative"
>
{avatarsReduced.map((avatar, index) => (
<Box
position="absolute"
top={`calc(${dx} * ${index})`}
left={`calc(${dx} * ${index})`}
width={`calc(100% - ${dx} * ${avatarsReduced.length - 1})`}
height={`calc(100% - ${dx} * ${avatarsReduced.length - 1})`}
style={{
filter: `brightness(${(index + 1) / avatarsReduced.length})`,
borderRadius: Var('radius-2'),
boxShadow: Var('shadow-3'),
backgroundImage: `url(${avatar.avatarComponent.avatar})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
>
{avatars.length > 1 && (
<Box
width="100%"
height="100%"
style={{
background: `linear-gradient(-45deg, ${Var('black-a9')} 25%, ${Var('black-a1')} 50%)`,
}}
/>
)}
</Box>
))}
{avatars.length > 1 && (
<Box position="absolute" bottom="1" right="1">
<Badge variant="solid" color="gray" highContrast size="3">
{literals(strings.common.units.times, [
`${avatars.length}`,
])}
</Badge>
</Box>
)}
</Box>
<Text
size="2"
wrap="nowrap"
align="center"
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{name}
</Text>
</Flex>
);
})}
{groups.map(([name, avatars]) => (
<AvatarGroup key={name} name={name} avatars={avatars} />
))}
</Grid>
</PageWrapper>
);
@@ -1,6 +1,7 @@
---
import { avatarsTool } from 'packages/website-ue/src/constants/tools';
import { metadata } from 'packages/website-ue/src/core/blitz/metadata';
import BaseLayout from 'packages/website-ue/src/layouts/BaseLayout.astro';
import ToolLayout from 'packages/website-ue/src/layouts/ToolLayout.astro';
import { Page } from './_index';
export { getStaticPaths } from '../index.astro';
@@ -12,6 +13,6 @@ const gameStrings = await metadata.stringsPartial(locale, [
]);
---
<BaseLayout {locale}>
<ToolLayout tool={avatarsTool} {locale}>
<Page localeData={{ locale, gameStrings }} client:load />
</BaseLayout>
</ToolLayout>