mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
ranks
This commit is contained in:
1 parent
eb0c35d6c6
commit
ae2839cb83
14 files changed
+452
-281
No files matched your search
@@ -1,16 +1,27 @@
|
||||
.characteristics-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: var(--space-4);
|
||||
margin: var(--space-4);
|
||||
|
||||
--base-cell-width: 20rem;
|
||||
--group-span: 7;
|
||||
|
||||
container-type: inline-size;
|
||||
.compare-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.characteristics {
|
||||
--N: round(down, 100cqw / var(--base-cell-width));
|
||||
--cell-width: calc(100cqw / var(--N));
|
||||
--cell-height: calc(var(--cell-width) / var(--group-span));
|
||||
|
||||
margin-bottom: calc(-1 * var(--cell-height));
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(
|
||||
auto-fill,
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import { TIER_ROMAN_NUMERALS } from "@blitzkit/core";
|
||||
import { literals } from "@blitzkit/i18n/src/literals";
|
||||
import { useRef } from "react";
|
||||
import { characteristicsGroups } from "../../config/characteristicsGroups";
|
||||
import { useCharacteristicRenderer } from "../../hooks/useCharacteristicRenderer";
|
||||
import { DuelModule, useDuel } from "../../hooks/useDuel";
|
||||
import { useRankings } from "../../hooks/useRankings";
|
||||
import { useStrings } from "../../hooks/useStrings";
|
||||
import { Tankopedia, TankopediaRelativeAgainst } from "../../stores/tankopedia";
|
||||
import type { CharacteristicRank } from "../../tankopedia/calculateRankings";
|
||||
import type {
|
||||
CharacteristicName,
|
||||
CharacteristicRenderConfig,
|
||||
CharacteristicReturnType,
|
||||
CharacteristicsGroup,
|
||||
ComputedCharacteristics,
|
||||
} from "../../types/characteristics";
|
||||
import { Heading } from "../Heading";
|
||||
import { SegmentedControl } from "../SegmentedControl";
|
||||
import { Text } from "../Text";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
@@ -18,8 +27,12 @@ interface TankopediaCharacteristicsProps {
|
||||
export function TankopediaCharacteristics({
|
||||
characteristics,
|
||||
}: TankopediaCharacteristicsProps) {
|
||||
const rankings = useRankings(characteristics);
|
||||
|
||||
return (
|
||||
<div className={styles["characteristics-wrapper"]}>
|
||||
<CompareOptions />
|
||||
|
||||
<div className={styles.characteristics}>
|
||||
{characteristicsGroups.map((group) => {
|
||||
const items = group.order.filter(
|
||||
@@ -34,6 +47,7 @@ export function TankopediaCharacteristics({
|
||||
key={group.name}
|
||||
group={group}
|
||||
characteristics={characteristics}
|
||||
rankings={rankings}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -45,9 +59,10 @@ export function TankopediaCharacteristics({
|
||||
interface GroupProps {
|
||||
group: CharacteristicsGroup;
|
||||
characteristics: ComputedCharacteristics;
|
||||
rankings: Map<CharacteristicName, CharacteristicRank>;
|
||||
}
|
||||
|
||||
function Group({ group, characteristics }: GroupProps) {
|
||||
function Group({ group, characteristics, rankings }: GroupProps) {
|
||||
const strings = useStrings();
|
||||
const toys = group.order.filter((item) => "toy" in item).length;
|
||||
const characteristicsCount = group.order.filter(
|
||||
@@ -95,7 +110,11 @@ function Group({ group, characteristics }: GroupProps) {
|
||||
{"toy" in item && <Toy {...item} />}
|
||||
{"label" in item && <Label {...item} />}
|
||||
{"name" in item && characteristics.has(item.name) && (
|
||||
<Item config={item} value={characteristics.get(item.name)!} />
|
||||
<Item
|
||||
config={item}
|
||||
value={characteristics.get(item.name)!}
|
||||
ranking={rankings.get(item.name)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
@@ -125,9 +144,10 @@ function Label({ label }: LabelProps) {
|
||||
interface ItemProps {
|
||||
config: CharacteristicRenderConfig;
|
||||
value: CharacteristicReturnType;
|
||||
ranking?: CharacteristicRank;
|
||||
}
|
||||
|
||||
function Item({ config, value }: ItemProps) {
|
||||
function Item({ config, value, ranking }: ItemProps) {
|
||||
const strings = useStrings();
|
||||
const renderCharacteristic = useCharacteristicRenderer();
|
||||
const hasUnits = config.units !== undefined;
|
||||
@@ -150,17 +170,64 @@ function Item({ config, value }: ItemProps) {
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className={styles.ranking}>
|
||||
<Bar value={Math.random()} />
|
||||
{ranking && (
|
||||
<div className={styles.ranking}>
|
||||
<Bar value={ranking.score} />
|
||||
|
||||
<Text lowContrast size="minor" className={styles.number}>
|
||||
1 / 132
|
||||
</Text>
|
||||
</div>
|
||||
<Text lowContrast size="minor" className={styles.number}>
|
||||
{literals(strings.units.fraction, {
|
||||
numerator: ranking.rank,
|
||||
denominator: ranking.total,
|
||||
})}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function CompareOptions() {
|
||||
const tank = useDuel("protagonist", DuelModule.Tank);
|
||||
const relativeAgainst = Tankopedia.use((state) => state.relative_against);
|
||||
|
||||
const strings = useStrings();
|
||||
|
||||
const options = useRef([
|
||||
{
|
||||
value: TankopediaRelativeAgainst.ClassAndTier,
|
||||
label: literals(strings.tanks.characteristics.compare.class, {
|
||||
tier: TIER_ROMAN_NUMERALS[tank.tier],
|
||||
class: strings.common.tank_class_short_plural_lowercase[tank.class],
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: TankopediaRelativeAgainst.Tier,
|
||||
label: literals(strings.tanks.characteristics.compare.tier, {
|
||||
tier: TIER_ROMAN_NUMERALS[tank.tier],
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: TankopediaRelativeAgainst.All,
|
||||
label: strings.tanks.characteristics.compare.all,
|
||||
},
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className={styles["compare-options"]}>
|
||||
<Text lowContrast>{strings.tanks.characteristics.compare.label}</Text>
|
||||
<SegmentedControl
|
||||
options={options.current}
|
||||
value={relativeAgainst}
|
||||
onValueChange={(value) => {
|
||||
Tankopedia.mutate((draft) => {
|
||||
draft.relative_against = value;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface BarProps {
|
||||
value: number;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user