User page in-game badge widget (#2841)
Some checks are pending
E2E Tests / e2e (push) Waiting to run
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run

This commit is contained in:
Kalle 2026-02-28 16:52:37 +02:00 committed by GitHub
parent 35fccae6f6
commit 4cc3a9807c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1601 changed files with 27026 additions and 3 deletions

1
.gitignore vendored
View File

@ -22,6 +22,7 @@ dump
!/scripts/output/.gitkeep
/scripts/dicts/**/*.json
/scripts/badge
/test-results/
/playwright-report/
/playwright/.cache/

View File

@ -0,0 +1,54 @@
.container {
display: flex;
flex-direction: column;
gap: var(--s-3);
}
.selectedBadges {
display: flex;
flex-wrap: wrap;
gap: var(--s-2);
align-items: center;
}
.count {
font-size: var(--fonts-xs);
color: var(--text-lighter);
font-weight: var(--semi-bold);
}
.badgeButton {
all: unset;
cursor: pointer;
border-radius: var(--rounded-sm);
padding: var(--s-0-5);
transition: background-color 0.15s;
}
.badgeButton:hover {
background-color: var(--bg-lightest);
}
.badgeButton:focus-visible {
outline: 2px solid var(--theme);
outline-offset: 2px;
}
.badgeImage {
display: block;
width: 48px;
height: 48px;
object-fit: contain;
}
.searchInput {
width: 100%;
}
.resultsGrid {
display: flex;
flex-wrap: wrap;
gap: var(--s-1);
max-height: 300px;
overflow-y: auto;
}

View File

@ -0,0 +1,101 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import type { CustomFieldRenderProps } from "~/form/FormField";
import {
GAME_BADGE_IDS,
type GameBadgeId,
} from "~/modules/in-game-lists/game-badge-ids";
import { gameBadgeUrl } from "~/utils/urls";
import styles from "./GameBadgeSelectField.module.css";
const MIN_SEARCH_LENGTH = 2;
export function GameBadgeSelectField({
value,
onChange,
maxCount,
}: CustomFieldRenderProps<string[]> & { maxCount: number }) {
const { t } = useTranslation(["user", "game-badges"]);
const [search, setSearch] = useState("");
const selectedIds = value ?? [];
const filteredBadges =
search.length >= MIN_SEARCH_LENGTH
? GAME_BADGE_IDS.filter(
(id) =>
t(`game-badges:${id}`)
.toLowerCase()
.includes(search.toLowerCase()) && !selectedIds.includes(id),
)
: [];
const handleAdd = (id: string) => {
if (selectedIds.length >= maxCount) return;
if (selectedIds.includes(id)) return;
onChange([...selectedIds, id]);
};
const handleRemove = (id: string) => {
onChange(selectedIds.filter((selectedId) => selectedId !== id));
};
return (
<div className={styles.container}>
<div>
<label>{t("user:widgets.forms.gameBadges")}</label>
<div className={styles.selectedBadges}>
{selectedIds.map((id) => {
const badgeId = id as GameBadgeId;
return (
<button
key={id}
type="button"
className={styles.badgeButton}
onClick={() => handleRemove(id)}
title={t(`game-badges:${badgeId}`)}
>
<img
src={gameBadgeUrl(id)}
alt={t(`game-badges:${badgeId}`)}
className={styles.badgeImage}
/>
</button>
);
})}
<span className={styles.count}>
{selectedIds.length}/{maxCount}
</span>
</div>
</div>
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder={t("user:widgets.forms.gameBadgesSearch")}
className={styles.searchInput}
/>
{filteredBadges.length > 0 ? (
<div className={styles.resultsGrid}>
{filteredBadges.map((id) => (
<button
key={id}
type="button"
className={styles.badgeButton}
onClick={() => handleAdd(id)}
title={t(`game-badges:${id}`)}
>
<img
src={gameBadgeUrl(id)}
alt={t(`game-badges:${id}`)}
className={styles.badgeImage}
/>
</button>
))}
</div>
) : null}
</div>
);
}

View File

@ -310,3 +310,20 @@
justify-content: center;
flex-wrap: wrap;
}
.gameBadgeGrid {
display: flex;
flex-wrap: wrap;
gap: var(--s-2);
justify-content: center;
}
.gameBadgeButton {
padding: 0;
}
.gameBadgeImage {
width: 48px;
height: 48px;
object-fit: contain;
}

View File

@ -18,6 +18,7 @@ import { previewUrl } from "~/features/art/art-utils";
import { BadgeDisplay } from "~/features/badges/components/BadgeDisplay";
import { VodListing } from "~/features/vods/components/VodListing";
import { useTimeFormat } from "~/hooks/useTimeFormat";
import type { GameBadgeId } from "~/modules/in-game-lists/game-badge-ids";
import type {
MainWeaponId,
ModeShort,
@ -30,6 +31,7 @@ import {
brandImageUrl,
calendarEventPage,
controllerImageUrl,
gameBadgeUrl,
LEADERBOARDS_PAGE,
LFG_PAGE,
modeImageUrl,
@ -237,6 +239,11 @@ export function Widget({
);
case "tier-list":
return <TierListWidget searchParams={widget.data.searchParams} />;
case "game-badges":
case "game-badges-small":
return widget.data.length === 0 ? null : (
<GameBadgesDisplay badgeIds={widget.data} />
);
default:
assertUnreachable(widget);
}
@ -851,3 +858,35 @@ function TierListWidget({ searchParams }: { searchParams: string }) {
</div>
);
}
function GameBadgesDisplay({ badgeIds }: { badgeIds: string[] }) {
const { t } = useTranslation(["game-badges"]);
return (
<div className={styles.gameBadgeGrid}>
{badgeIds.map((id) => {
const badgeId = id as GameBadgeId;
return (
<SendouPopover
key={id}
trigger={
<SendouButton
variant="minimal"
className={styles.gameBadgeButton}
>
<img
src={gameBadgeUrl(id)}
alt={t(`game-badges:${badgeId}`)}
className={styles.gameBadgeImage}
loading="lazy"
/>
</SendouButton>
}
>
{t(`game-badges:${badgeId}`)}
</SendouPopover>
);
})}
</div>
);
}

View File

@ -9,6 +9,8 @@ import {
TIMEZONE_OPTIONS,
} from "../core/widgets/widget-form-schemas";
import styles from "../routes/u.$identifier.module.css";
import { USER } from "../user-page-constants";
import { GameBadgeSelectField } from "./GameBadgeSelectField";
export function WidgetSettingsForm({
widget,
@ -101,6 +103,28 @@ function WidgetFormFields({ widgetId }: { widgetId: string }) {
)}
</FormField>
);
case "game-badges":
return (
<FormField name="badgeIds">
{(props: CustomFieldRenderProps) => (
<GameBadgeSelectField
{...(props as CustomFieldRenderProps<string[]>)}
maxCount={USER.GAME_BADGES_MAX}
/>
)}
</FormField>
);
case "game-badges-small":
return (
<FormField name="badgeIds">
{(props: CustomFieldRenderProps) => (
<GameBadgeSelectField
{...(props as CustomFieldRenderProps<string[]>)}
maxCount={USER.GAME_BADGES_SMALL_MAX}
/>
)}
</FormField>
);
default:
return null;
}

View File

@ -280,6 +280,18 @@ export const WIDGET_LOADERS = {
links: async (_userId: number, settings: ExtractWidgetSettings<"links">) => {
return settings.links;
},
"game-badges": async (
_userId: number,
settings: ExtractWidgetSettings<"game-badges">,
) => {
return settings.badgeIds;
},
"game-badges-small": async (
_userId: number,
settings: ExtractWidgetSettings<"game-badges-small">,
) => {
return settings.badgeIds;
},
};
async function getTop500WeaponsByCategory(

View File

@ -6,6 +6,8 @@ import {
bioMdSchema,
bioSchema,
favoriteStageSchema,
gameBadgesSchema,
gameBadgesSmallSchema,
linksSchema,
peakXpUnverifiedSchema,
peakXpWeaponSchema,
@ -134,6 +136,20 @@ export const ALL_WIDGETS = {
defaultSettings: { source: "ALL" },
}),
],
"game-badges": [
defineWidget({
id: "game-badges",
slot: "main",
schema: gameBadgesSchema,
defaultSettings: { badgeIds: [] },
}),
defineWidget({
id: "game-badges-small",
slot: "side",
schema: gameBadgesSmallSchema,
defaultSettings: { badgeIds: [] },
}),
],
} as const;
export function allWidgetsFlat() {

View File

@ -14,6 +14,7 @@ import {
weaponSelect,
} from "~/form/fields";
import type { SelectOption } from "~/form/types";
import { GAME_BADGE_IDS } from "~/modules/in-game-lists/game-badge-ids";
import { USER } from "../../user-page-constants";
export const bioSchema = z.object({
@ -129,6 +130,24 @@ export const tierListSchema = z.object({
}),
});
const gameBadgeId = z
.string()
.refine((val) => (GAME_BADGE_IDS as readonly string[]).includes(val));
export const gameBadgesSchema = z.object({
badgeIds: customField(
{ initialValue: [] },
z.array(gameBadgeId).max(USER.GAME_BADGES_MAX),
),
});
export const gameBadgesSmallSchema = z.object({
badgeIds: customField(
{ initialValue: [] },
z.array(gameBadgeId).max(USER.GAME_BADGES_SMALL_MAX),
),
});
const WIDGET_FORM_SCHEMAS: Record<string, z.ZodObject<z.ZodRawShape>> = {
bio: bioSchema,
"bio-md": bioMdSchema,
@ -142,6 +161,8 @@ const WIDGET_FORM_SCHEMAS: Record<string, z.ZodObject<z.ZodRawShape>> = {
art: artSchema,
links: linksSchema,
"tier-list": tierListSchema,
"game-badges": gameBadgesSchema,
"game-badges-small": gameBadgesSmallSchema,
};
export function getWidgetFormSchema(widgetId: string) {

View File

@ -274,7 +274,10 @@ function AvailableWidgetsList({
</div>
<div className="text-xs font-bold">{"//"}</div>
<div className={styles.widgetDescription}>
{t(`user:widgets.description.${widget.id}` as const)}
{t(
`user:widgets.description.${widget.id}` as const,
widgetDescriptionParams(widget.id),
)}
</div>
</div>
</div>
@ -451,3 +454,12 @@ function DraggableWidgetItem({
</div>
);
}
const WIDGET_DESCRIPTION_PARAMS: Record<string, Record<string, unknown>> = {
"game-badges": { max: USER.GAME_BADGES_MAX },
"game-badges-small": { max: USER.GAME_BADGES_SMALL_MAX },
};
function widgetDescriptionParams(widgetId: string) {
return WIDGET_DESCRIPTION_PARAMS[widgetId];
}

View File

@ -43,7 +43,17 @@ import styles from "./u.$identifier.module.css";
export { loader };
export const handle: SendouRouteHandle = {
i18n: ["badges", "team", "org", "vods", "lfg", "builds", "weapons", "gear"],
i18n: [
"badges",
"team",
"org",
"vods",
"lfg",
"builds",
"weapons",
"gear",
"game-badges",
],
};
export default function UserInfoPage() {

View File

@ -40,7 +40,7 @@ export const meta: MetaFunction<typeof loader> = (args) => {
};
export const handle: SendouRouteHandle = {
i18n: ["user", "badges"],
i18n: ["user", "badges", "game-badges"],
breadcrumb: ({ match }) => {
const data = match.data as UserPageLoaderData | undefined;

View File

@ -14,6 +14,8 @@ export const USER = {
MOD_NOTE_MAX_LENGTH: 2000,
MAX_MAIN_WIDGETS: 5,
MAX_SIDE_WIDGETS: 7,
GAME_BADGES_MAX: 8,
GAME_BADGES_SMALL_MAX: 4,
};
export const MATCHES_PER_SEASONS_PAGE = 8;

View File

@ -8,6 +8,7 @@ import contributions from "../../../locales/en/contributions.json";
import faq from "../../../locales/en/faq.json";
import forms from "../../../locales/en/forms.json";
import front from "../../../locales/en/front.json";
import gameBadges from "../../../locales/en/game-badges.json";
import gameMisc from "../../../locales/en/game-misc.json";
import gear from "../../../locales/en/gear.json";
import lfg from "../../../locales/en/lfg.json";
@ -33,6 +34,7 @@ export const resources = {
faq,
forms,
front,
"game-badges": gameBadges,
"game-misc": gameMisc,
gear,
lfg,

View File

@ -8,6 +8,7 @@ import contributionsDa from "../../../locales/da/contributions.json";
import faqDa from "../../../locales/da/faq.json";
import formsDa from "../../../locales/da/forms.json";
import frontDa from "../../../locales/da/front.json";
import gameBadgesDa from "../../../locales/da/game-badges.json";
import gameMiscDa from "../../../locales/da/game-misc.json";
import gearDa from "../../../locales/da/gear.json";
import lfgDa from "../../../locales/da/lfg.json";
@ -30,6 +31,7 @@ import contributionsDe from "../../../locales/de/contributions.json";
import faqDe from "../../../locales/de/faq.json";
import formsDe from "../../../locales/de/forms.json";
import frontDe from "../../../locales/de/front.json";
import gameBadgesDe from "../../../locales/de/game-badges.json";
import gameMiscDe from "../../../locales/de/game-misc.json";
import gearDe from "../../../locales/de/gear.json";
import lfgDe from "../../../locales/de/lfg.json";
@ -52,6 +54,7 @@ import contributions from "../../../locales/en/contributions.json";
import faq from "../../../locales/en/faq.json";
import forms from "../../../locales/en/forms.json";
import front from "../../../locales/en/front.json";
import gameBadges from "../../../locales/en/game-badges.json";
import gameMisc from "../../../locales/en/game-misc.json";
import gear from "../../../locales/en/gear.json";
import lfg from "../../../locales/en/lfg.json";
@ -74,6 +77,7 @@ import contributionsEsEs from "../../../locales/es-ES/contributions.json";
import faqEsEs from "../../../locales/es-ES/faq.json";
import formsEsEs from "../../../locales/es-ES/forms.json";
import frontEsEs from "../../../locales/es-ES/front.json";
import gameBadgesEsEs from "../../../locales/es-ES/game-badges.json";
import gameMiscEsEs from "../../../locales/es-ES/game-misc.json";
import gearEsEs from "../../../locales/es-ES/gear.json";
import lfgEsEs from "../../../locales/es-ES/lfg.json";
@ -96,6 +100,7 @@ import contributionsEsUs from "../../../locales/es-US/contributions.json";
import faqEsUs from "../../../locales/es-US/faq.json";
import formsEsUs from "../../../locales/es-US/forms.json";
import frontEsUs from "../../../locales/es-US/front.json";
import gameBadgesEsUs from "../../../locales/es-US/game-badges.json";
import gameMiscEsUs from "../../../locales/es-US/game-misc.json";
import gearEsUs from "../../../locales/es-US/gear.json";
import lfgEsUs from "../../../locales/es-US/lfg.json";
@ -118,6 +123,7 @@ import contributionsFrCa from "../../../locales/fr-CA/contributions.json";
import faqFrCa from "../../../locales/fr-CA/faq.json";
import formsFrCa from "../../../locales/fr-CA/forms.json";
import frontFrCa from "../../../locales/fr-CA/front.json";
import gameBadgesFrCa from "../../../locales/fr-CA/game-badges.json";
import gameMiscFrCa from "../../../locales/fr-CA/game-misc.json";
import gearFrCa from "../../../locales/fr-CA/gear.json";
import lfgFrCa from "../../../locales/fr-CA/lfg.json";
@ -140,6 +146,7 @@ import contributionsFrEu from "../../../locales/fr-EU/contributions.json";
import faqFrEu from "../../../locales/fr-EU/faq.json";
import formsFrEu from "../../../locales/fr-EU/forms.json";
import frontFrEu from "../../../locales/fr-EU/front.json";
import gameBadgesFrEu from "../../../locales/fr-EU/game-badges.json";
import gameMiscFrEu from "../../../locales/fr-EU/game-misc.json";
import gearFrEu from "../../../locales/fr-EU/gear.json";
import lfgFrEu from "../../../locales/fr-EU/lfg.json";
@ -162,6 +169,7 @@ import contributionsHe from "../../../locales/he/contributions.json";
import faqHe from "../../../locales/he/faq.json";
import formsHe from "../../../locales/he/forms.json";
import frontHe from "../../../locales/he/front.json";
import gameBadgesHe from "../../../locales/he/game-badges.json";
import gameMiscHe from "../../../locales/he/game-misc.json";
import gearHe from "../../../locales/he/gear.json";
import lfgHe from "../../../locales/he/lfg.json";
@ -184,6 +192,7 @@ import contributionsIt from "../../../locales/it/contributions.json";
import faqIt from "../../../locales/it/faq.json";
import formsIt from "../../../locales/it/forms.json";
import frontIt from "../../../locales/it/front.json";
import gameBadgesIt from "../../../locales/it/game-badges.json";
import gameMiscIt from "../../../locales/it/game-misc.json";
import gearIt from "../../../locales/it/gear.json";
import lfgIt from "../../../locales/it/lfg.json";
@ -206,6 +215,7 @@ import contributionsJa from "../../../locales/ja/contributions.json";
import faqJa from "../../../locales/ja/faq.json";
import formsJa from "../../../locales/ja/forms.json";
import frontJa from "../../../locales/ja/front.json";
import gameBadgesJa from "../../../locales/ja/game-badges.json";
import gameMiscJa from "../../../locales/ja/game-misc.json";
import gearJa from "../../../locales/ja/gear.json";
import lfgJa from "../../../locales/ja/lfg.json";
@ -228,6 +238,7 @@ import contributionsKo from "../../../locales/ko/contributions.json";
import faqKo from "../../../locales/ko/faq.json";
import formsKo from "../../../locales/ko/forms.json";
import frontKo from "../../../locales/ko/front.json";
import gameBadgesKo from "../../../locales/ko/game-badges.json";
import gameMiscKo from "../../../locales/ko/game-misc.json";
import gearKo from "../../../locales/ko/gear.json";
import lfgKo from "../../../locales/ko/lfg.json";
@ -250,6 +261,7 @@ import contributionsNl from "../../../locales/nl/contributions.json";
import faqNl from "../../../locales/nl/faq.json";
import formsNl from "../../../locales/nl/forms.json";
import frontNl from "../../../locales/nl/front.json";
import gameBadgesNl from "../../../locales/nl/game-badges.json";
import gameMiscNl from "../../../locales/nl/game-misc.json";
import gearNl from "../../../locales/nl/gear.json";
import lfgNl from "../../../locales/nl/lfg.json";
@ -272,6 +284,7 @@ import contributionsPl from "../../../locales/pl/contributions.json";
import faqPl from "../../../locales/pl/faq.json";
import formsPl from "../../../locales/pl/forms.json";
import frontPl from "../../../locales/pl/front.json";
import gameBadgesPl from "../../../locales/pl/game-badges.json";
import gameMiscPl from "../../../locales/pl/game-misc.json";
import gearPl from "../../../locales/pl/gear.json";
import lfgPl from "../../../locales/pl/lfg.json";
@ -294,6 +307,7 @@ import contributionsPtBr from "../../../locales/pt-BR/contributions.json";
import faqPtBr from "../../../locales/pt-BR/faq.json";
import formsPtBr from "../../../locales/pt-BR/forms.json";
import frontPtBr from "../../../locales/pt-BR/front.json";
import gameBadgesPtBr from "../../../locales/pt-BR/game-badges.json";
import gameMiscPtBr from "../../../locales/pt-BR/game-misc.json";
import gearPtBr from "../../../locales/pt-BR/gear.json";
import lfgPtBr from "../../../locales/pt-BR/lfg.json";
@ -316,6 +330,7 @@ import contributionsRu from "../../../locales/ru/contributions.json";
import faqRu from "../../../locales/ru/faq.json";
import formsRu from "../../../locales/ru/forms.json";
import frontRu from "../../../locales/ru/front.json";
import gameBadgesRu from "../../../locales/ru/game-badges.json";
import gameMiscRu from "../../../locales/ru/game-misc.json";
import gearRu from "../../../locales/ru/gear.json";
import lfgRu from "../../../locales/ru/lfg.json";
@ -338,6 +353,7 @@ import contributionsZh from "../../../locales/zh/contributions.json";
import faqZh from "../../../locales/zh/faq.json";
import formsZh from "../../../locales/zh/forms.json";
import frontZh from "../../../locales/zh/front.json";
import gameBadgesZh from "../../../locales/zh/game-badges.json";
import gameMiscZh from "../../../locales/zh/game-misc.json";
import gearZh from "../../../locales/zh/gear.json";
import lfgZh from "../../../locales/zh/lfg.json";
@ -359,6 +375,7 @@ export const resources = {
weapons: weaponsEsUs,
scrims: scrimsEsUs,
common: commonEsUs,
"game-badges": gameBadgesEsUs,
"game-misc": gameMiscEsUs,
tournament: tournamentEsUs,
front: frontEsUs,
@ -383,6 +400,7 @@ export const resources = {
weapons: weapons,
scrims: scrimsEn,
common: common,
"game-badges": gameBadges,
"game-misc": gameMisc,
tournament: tournament,
front: front,
@ -407,6 +425,7 @@ export const resources = {
weapons: weaponsKo,
scrims: scrimsKo,
common: commonKo,
"game-badges": gameBadgesKo,
"game-misc": gameMiscKo,
tournament: tournamentKo,
front: frontKo,
@ -431,6 +450,7 @@ export const resources = {
weapons: weaponsDe,
scrims: scrimsDe,
common: commonDe,
"game-badges": gameBadgesDe,
"game-misc": gameMiscDe,
tournament: tournamentDe,
front: frontDe,
@ -455,6 +475,7 @@ export const resources = {
weapons: weaponsNl,
scrims: scrimsNl,
common: commonNl,
"game-badges": gameBadgesNl,
"game-misc": gameMiscNl,
tournament: tournamentNl,
front: frontNl,
@ -479,6 +500,7 @@ export const resources = {
weapons: weaponsPtBr,
scrims: scrimsPtBr,
common: commonPtBr,
"game-badges": gameBadgesPtBr,
"game-misc": gameMiscPtBr,
tournament: tournamentPtBr,
front: frontPtBr,
@ -503,6 +525,7 @@ export const resources = {
weapons: weaponsZh,
scrims: scrimsZh,
common: commonZh,
"game-badges": gameBadgesZh,
"game-misc": gameMiscZh,
tournament: tournamentZh,
front: frontZh,
@ -527,6 +550,7 @@ export const resources = {
weapons: weaponsFrCa,
scrims: scrimsFrCa,
common: commonFrCa,
"game-badges": gameBadgesFrCa,
"game-misc": gameMiscFrCa,
tournament: tournamentFrCa,
front: frontFrCa,
@ -551,6 +575,7 @@ export const resources = {
weapons: weaponsRu,
scrims: scrimsRu,
common: commonRu,
"game-badges": gameBadgesRu,
"game-misc": gameMiscRu,
tournament: tournamentRu,
front: frontRu,
@ -575,6 +600,7 @@ export const resources = {
weapons: weaponsIt,
scrims: scrimsIt,
common: commonIt,
"game-badges": gameBadgesIt,
"game-misc": gameMiscIt,
tournament: tournamentIt,
front: frontIt,
@ -599,6 +625,7 @@ export const resources = {
weapons: weaponsJa,
scrims: scrimsJa,
common: commonJa,
"game-badges": gameBadgesJa,
"game-misc": gameMiscJa,
tournament: tournamentJa,
front: frontJa,
@ -623,6 +650,7 @@ export const resources = {
weapons: weaponsDa,
scrims: scrimsDa,
common: commonDa,
"game-badges": gameBadgesDa,
"game-misc": gameMiscDa,
tournament: tournamentDa,
front: frontDa,
@ -647,6 +675,7 @@ export const resources = {
weapons: weaponsEsEs,
scrims: scrimsEsEs,
common: commonEsEs,
"game-badges": gameBadgesEsEs,
"game-misc": gameMiscEsEs,
tournament: tournamentEsEs,
front: frontEsEs,
@ -671,6 +700,7 @@ export const resources = {
weapons: weaponsHe,
scrims: scrimsHe,
common: commonHe,
"game-badges": gameBadgesHe,
"game-misc": gameMiscHe,
tournament: tournamentHe,
front: frontHe,
@ -695,6 +725,7 @@ export const resources = {
weapons: weaponsFrEu,
scrims: scrimsFrEu,
common: commonFrEu,
"game-badges": gameBadgesFrEu,
"game-misc": gameMiscFrEu,
tournament: tournamentFrEu,
front: frontFrEu,
@ -719,6 +750,7 @@ export const resources = {
weapons: weaponsPl,
scrims: scrimsPl,
common: commonPl,
"game-badges": gameBadgesPl,
"game-misc": gameMiscPl,
tournament: tournamentPl,
front: frontPl,

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ const ALL_NAMESPACES = [
"contributions",
"faq",
"forms",
"game-badges",
"game-misc",
"gear",
"user",

View File

@ -454,6 +454,8 @@ export const badgeUrl = ({
code: Tables["Badge"]["code"];
extension?: "gif";
}) => `/static-assets/badges/${code}${extension ? `.${extension}` : ""}`;
export const gameBadgeUrl = (id: string) =>
`/static-assets/img/badges/${id}.avif`;
export const articlePreviewUrl = (slug: string) =>
`/static-assets/img/article-previews/${slug}.png`;

1552
locales/da/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/de/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/en/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "Commissions",
"widget.social-links": "Verified Social Links",
"widget.links": "Links",
"widget.game-badges": "Game Badges",
"widget.game-badges-small": "Game Badges",
"widget.tier-list": "Featured Tier List",
"widget.link.all": "All",
"widgets.edit": "Edit Widgets",
@ -68,6 +70,7 @@
"widgets.category.vods": "Videos",
"widgets.category.builds": "Builds",
"widgets.category.art": "Art",
"widgets.category.game-badges": "Game Badges",
"widgets.description.bio": "Share freeform information about yourself",
"widgets.description.bio-md": "Share freeform information about yourself with markdown formatting",
"widgets.description.badges-owned": "Display your earned badges",
@ -108,6 +111,8 @@
"widgets.description.commissions": "Show your commission status and details",
"widgets.description.social-links": "Display your social media links from Discord",
"widgets.description.links": "Share your custom social media and website links",
"widgets.description.game-badges": "Display up to {{max}} in-game badges on your profile",
"widgets.description.game-badges-small": "Display up to {{max}} in-game badges on your profile",
"widgets.description.tier-list": "Display a tier list you have made",
"widgets.forms.bio": "Bio",
"widgets.forms.bio.markdownSupport": "Supports Markdown",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "Made by me",
"widgets.forms.source.MADE-OF": "Made of me",
"widgets.forms.links": "Links",
"widgets.forms.gameBadges": "Badges",
"widgets.forms.gameBadgesSearch": "Search badges by name...",
"widgets.forms.tierListUrl": "Tier List URL",
"widget.tier-list.untitled": "Untitled Tier List",
"controllers.s1-pro-con": "Switch 1 Pro Controller",

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/he/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/it/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/ja/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/ko/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/nl/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/pl/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/ru/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

1552
locales/zh/game-badges.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,8 @@
"widget.commissions": "",
"widget.social-links": "",
"widget.links": "",
"widget.game-badges": "",
"widget.game-badges-small": "",
"widget.tier-list": "",
"widget.link.all": "",
"widgets.edit": "",
@ -68,6 +70,7 @@
"widgets.category.vods": "",
"widgets.category.builds": "",
"widgets.category.art": "",
"widgets.category.game-badges": "",
"widgets.description.bio": "",
"widgets.description.bio-md": "",
"widgets.description.badges-owned": "",
@ -108,6 +111,8 @@
"widgets.description.commissions": "",
"widgets.description.social-links": "",
"widgets.description.links": "",
"widgets.description.game-badges": "",
"widgets.description.game-badges-small": "",
"widgets.description.tier-list": "",
"widgets.forms.bio": "",
"widgets.forms.bio.markdownSupport": "",
@ -125,6 +130,8 @@
"widgets.forms.source.MADE-BY": "",
"widgets.forms.source.MADE-OF": "",
"widgets.forms.links": "",
"widgets.forms.gameBadges": "",
"widgets.forms.gameBadgesSearch": "",
"widgets.forms.tierListUrl": "",
"widget.tier-list.untitled": "",
"controllers.s1-pro-con": "",

Some files were not shown because too many files have changed in this diff Show More