mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: flesh out popular tanks
This commit is contained in:
1 parent
b6c4c4e852
commit
406ad52c8d
10 files changed
+85
-30
No files matched your search
@@ -2,6 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RootNamespace>BlitzKit.Game</RootNamespace>
|
<RootNamespace>BlitzKit.Game</RootNamespace>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<NodeApiAssemblyJSModuleType>esm</NodeApiAssemblyJSModuleType>
|
<NodeApiAssemblyJSModuleType>esm</NodeApiAssemblyJSModuleType>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from "../bin/Debug/net9.0/game";
|
export * from "../bin/Debug/net9.0/win-x64/game";
|
||||||
@@ -2,9 +2,8 @@
|
|||||||
import { api } from "../core/api/dynamic";
|
import { api } from "../core/api/dynamic";
|
||||||
import { tools } from "../core/tools/tools";
|
import { tools } from "../core/tools/tools";
|
||||||
import { Heading } from "./Heading";
|
import { Heading } from "./Heading";
|
||||||
import { Scroller } from "./Scroller";
|
import { HomeTanksPopular } from "./HomeTanksPopular";
|
||||||
import { Section } from "./Section";
|
import { Section } from "./Section";
|
||||||
import { TankCard } from "./TankCard";
|
|
||||||
import ToolCard from "./ToolCard.astro";
|
import ToolCard from "./ToolCard.astro";
|
||||||
import ToolsWrapper from "./ToolsWrapper.astro";
|
import ToolsWrapper from "./ToolsWrapper.astro";
|
||||||
|
|
||||||
@@ -13,37 +12,19 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { locale } = Astro.props;
|
const { locale } = Astro.props;
|
||||||
|
|
||||||
const strings = await api.strings(locale);
|
const strings = await api.strings(locale);
|
||||||
const popular = (await api.popularTanks()).tanks.slice(0, 8);
|
|
||||||
|
|
||||||
console.log(popular.length);
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.title {
|
.title {
|
||||||
margin-bottom: var(--space-3);
|
margin-bottom: var(--space-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tanks {
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
gap: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<Section>
|
<Section>
|
||||||
<Heading size="2" className="title">{strings.home.tanks}</Heading>
|
<Heading size="2" className="title">{strings.home.tanks}</Heading>
|
||||||
|
|
||||||
<Scroller client:load className="tanks">
|
<HomeTanksPopular {locale} client:load />
|
||||||
<div class="content">
|
|
||||||
{popular.map((tank) => <TankCard {...tank} />)}
|
|
||||||
</div>
|
|
||||||
</Scroller>
|
|
||||||
|
|
||||||
<ToolCard gradient {locale} tool={tools.tanks} />
|
<ToolCard gradient {locale} tool={tools.tanks} />
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
.tanks {
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { api } from "../../core/api/dynamic";
|
||||||
|
import { useAwait } from "../../hooks/useAwait";
|
||||||
|
import {
|
||||||
|
LocaleProvider,
|
||||||
|
type LocaleAcceptorProps,
|
||||||
|
} from "../../hooks/useLocale";
|
||||||
|
import { Scroller } from "../Scroller";
|
||||||
|
import { TankCard } from "../TankCard";
|
||||||
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
|
export function HomeTanksPopular({ locale }: LocaleAcceptorProps) {
|
||||||
|
return (
|
||||||
|
<LocaleProvider locale={locale}>
|
||||||
|
<Content />
|
||||||
|
</LocaleProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Content() {
|
||||||
|
const popular = useAwait(() => api.popularTanks(), "popular-tanks");
|
||||||
|
const trimmed = popular.tanks.slice(0, 32);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Scroller className={styles.tanks}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
{trimmed.map((tank) => (
|
||||||
|
<TankCard key={tank.id} {...tank} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Scroller>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,7 +2,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-2);
|
gap: var(--space-4);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: min-content;
|
||||||
|
|
||||||
.icon-wrapper {
|
.icon-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -20,12 +23,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 7rem;
|
width: 13rem;
|
||||||
aspect-ratio: 4 / 3;
|
height: 8rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
background-size: 150%;
|
background-size: 140%;
|
||||||
background-position: center;
|
background-position: 40% center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 100%;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,14 @@
|
|||||||
|
import { api } from "../../core/api/dynamic";
|
||||||
|
import { useAwait } from "../../hooks/useAwait";
|
||||||
|
import { useGameStrings } from "../../hooks/useGameStrings";
|
||||||
import type { PopularTank } from "../../protos/popular_tanks";
|
import type { PopularTank } from "../../protos/popular_tanks";
|
||||||
import { Text } from "../Text";
|
import { Text } from "../Text";
|
||||||
import styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
export function TankCard({ id }: PopularTank) {
|
export function TankCard({ id }: PopularTank) {
|
||||||
|
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
||||||
|
const gameStrings = useGameStrings("TankEntity");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["tank-card"]}>
|
<div className={styles["tank-card"]}>
|
||||||
<div className={styles["icon-wrapper"]}>
|
<div className={styles["icon-wrapper"]}>
|
||||||
@@ -21,7 +27,7 @@ export function TankCard({ id }: PopularTank) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Text className={styles.name}>{id}</Text>
|
<Text className={styles.name}>{gameStrings[tank.tank!.name!.value]}</Text>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import { fetchPB } from "@blitzkit/core";
|
import { fetchPB } from "@blitzkit/core";
|
||||||
import type { Strings } from "@blitzkit/i18n";
|
import type { Strings } from "@blitzkit/i18n";
|
||||||
import { Avatars } from "../../protos/avatars";
|
import { Avatars } from "../../protos/avatars";
|
||||||
|
import { PopularTanks } from "../../protos/popular_tanks";
|
||||||
|
import { Tank } from "../../protos/tank";
|
||||||
import { AbstractAPI } from "./abstract";
|
import { AbstractAPI } from "./abstract";
|
||||||
|
|
||||||
//@ts-expect-error
|
|
||||||
export class ClientAPI extends AbstractAPI {
|
export class ClientAPI extends AbstractAPI {
|
||||||
protected _avatars() {
|
protected _avatars() {
|
||||||
return fetchPB("/api/avatars/all.pb", Avatars);
|
return fetchPB("/api/avatars/all.pb", Avatars);
|
||||||
@@ -24,4 +25,12 @@ export class ClientAPI extends AbstractAPI {
|
|||||||
const json = (await response.json()) as Strings;
|
const json = (await response.json()) as Strings;
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected _popularTanks() {
|
||||||
|
return fetchPB("/api/tanks/popular.pb", PopularTanks);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _tank(id: string) {
|
||||||
|
return fetchPB(`/api/tanks/${id}.pb`, Tank);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GameInterface } from "@blitzkit/game";
|
import { GameInterface } from "@blitzkit/game";
|
||||||
|
|
||||||
export const game = new GameInterface(
|
export const game = new GameInterface(
|
||||||
"/mnt/c/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz Playtest",
|
"C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz Playtest",
|
||||||
);
|
);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { api } from "../../../core/api/dynamic";
|
||||||
|
import { PopularTanks } from "../../../protos/popular_tanks";
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const popular = await api.popularTanks();
|
||||||
|
return new Response(PopularTanks.encode(popular).finish());
|
||||||
|
}
|
||||||
Reference in new issue
Block a user