feat: dialog

This commit is contained in:
TrèsAbhi committed 2025-05-30 20:30:16 -05:00
1 parent 3aafe4d9f1
commit 8373fb1b7a
5 files changed
+53 -22

No files matched your search

@@ -43,12 +43,16 @@ export class CatalogItemAccessor {
return this;
}
get<Type>(Message: MessageFns<Type>, component: string) {
getOptional<Type>(Message: MessageFns<Type>, component: string) {
if (component in this.components) {
return Message.decode(this.components[component].value);
}
}
throw new Error(`Unknown component: ${component}`);
get<Type>(Message: MessageFns<Type>, component: string) {
const value = this.getOptional(Message, component);
if (value === undefined) throw new Error(`Unknown component: ${component}`);
return value;
}
pack() {
+1 -1
View File
@@ -1260,7 +1260,7 @@
"seo_description": "All World of Tanks Blitz player profile avatars",
"description": "Player profile avatars",
"unnamed_avatar": "Unnamed avatar",
"unnamed_avatars": "Unnamed avatars",
"search": {
"hint": "Search avatars...",
"results": "%s1 avatars"
@@ -1,29 +1,48 @@
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 {
Badge,
Box,
Dialog,
Flex,
Text,
type FlexProps,
} 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;
name?: string;
avatars: {
stuff: StuffUIComponent;
avatar: ProfileAvatarComponent;
sellable: SellableComponent;
sellable?: SellableComponent;
}[];
}
const dx = '4px';
const MAX_AVATARS_PREVIEW = 5;
export function AvatarGroup({ avatars, name }: AvatarGroupProps) {
export function AvatarGroup({ name, avatars }: AvatarGroupProps) {
return (
<Dialog.Root>
<Dialog.Trigger>
<Content avatars={avatars} name={name} />
</Dialog.Trigger>
<Dialog.Content>asd</Dialog.Content>
</Dialog.Root>
);
}
function Content({ avatars, name, ...props }: FlexProps & AvatarGroupProps) {
const { strings } = useLocale();
const avatarsReduced = [...avatars].reverse().slice(0, MAX_AVATARS_PREVIEW);
return (
<Flex direction="column" gap="3">
<Flex direction="column" gap="3" style={{ cursor: 'pointer' }} {...props}>
<Box width="100%" style={{ aspectRatio: '7 / 8' }} position="relative">
{avatarsReduced.map((avatar, index) => (
<Box
@@ -35,7 +54,7 @@ export function AvatarGroup({ avatars, name }: AvatarGroupProps) {
style={{
filter: `brightness(${(index + 1) / avatarsReduced.length})`,
borderRadius: Var('radius-2'),
boxShadow: Var('shadow-3'),
boxShadow: Var('shadow-2'),
backgroundImage: `url(${avatar.avatar.avatar})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
@@ -69,9 +88,10 @@ export function AvatarGroup({ avatars, name }: AvatarGroupProps) {
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
fontStyle: name === undefined ? 'italic' : undefined,
}}
>
{name}
{name ?? strings.website.tools.avatars.unnamed_avatars}
</Text>
</Flex>
);
@@ -41,30 +41,37 @@ function Content() {
ProfileAvatarComponent,
'profileAvatarComponent',
);
const sellable = item.get(SellableComponent, 'sellableComponent');
const name =
gameStrings[stuff.display_name] ??
strings.website.tools.avatars.unnamed_avatar; // maybe move to dumb component?
const sellable = item.getOptional(
SellableComponent,
'sellableComponent',
);
const name = gameStrings[stuff.display_name] as string | undefined;
return { avatar, name, stuff, sellable };
})
.sort((a, b) => a.stuff.grade - b.stuff.grade)
.sort((a, b) => a.name.localeCompare(b.name));
const groups: Record<string, typeof avatars> = {};
.sort((a, b) =>
a.name === undefined
? 1
: b.name === undefined
? -1
: a.name.localeCompare(b.name),
);
const groups = new Map<string | undefined, typeof avatars>();
for (const avatar of avatars) {
if (avatar.name in groups) {
groups[avatar.name].push(avatar);
if (groups.has(avatar.name)) {
groups.get(avatar.name)!.push(avatar);
} else {
groups[avatar.name] = [avatar];
groups.set(avatar.name, [avatar]);
}
}
return Object.entries(groups);
return [...groups];
}, []);
return (
<PageWrapper>
<PageWrapper color="gold">
<Grid
columns={{
initial: 'repeat(auto-fill, minmax(6rem, 1fr))',
@@ -13,6 +13,6 @@ const gameStrings = await metadata.stringsPartial(locale, [
]);
---
<ToolLayout tool={avatarsTool} {locale}>
<ToolLayout tool={avatarsTool} {locale} >
<Page localeData={{ locale, gameStrings }} client:load />
</ToolLayout>