From 16f544ef2ba46fc49e8aa71de173d6303d54c93a Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 6 Sep 2026 15:55:13 +0300 Subject: [PATCH] Misc edit widgets page tweaks --- .../components/WidgetSettingsForm.tsx | 7 +- .../user-page/core/widgets/portfolio.ts | 2 +- .../core/widgets/widget-form-schemas.ts | 28 +++++--- .../u.$identifier.edit-widgets.module.css | 11 +++ .../routes/u.$identifier.edit-widgets.tsx | 21 ++++-- app/features/user-page/user-page-constants.ts | 8 +++ .../user-page/user-page-schemas.test.ts | 69 +++++++++++++++++++ app/features/user-page/user-page-schemas.ts | 3 + locales/da/user.json | 18 +---- locales/de/user.json | 18 +---- locales/en/user.json | 18 +---- locales/es-ES/user.json | 18 +---- locales/es-US/user.json | 18 +---- locales/fr-CA/user.json | 18 +---- locales/fr-EU/user.json | 18 +---- locales/he/user.json | 18 +---- locales/it/user.json | 18 +---- locales/ja/user.json | 18 +---- locales/ko/user.json | 18 +---- locales/nl/user.json | 18 +---- locales/pl/user.json | 18 +---- locales/pt-BR/user.json | 18 +---- locales/ru/user.json | 18 +---- locales/zh/user.json | 18 +---- 24 files changed, 161 insertions(+), 276 deletions(-) diff --git a/app/features/user-page/components/WidgetSettingsForm.tsx b/app/features/user-page/components/WidgetSettingsForm.tsx index 83c32f805..fd74a6767 100644 --- a/app/features/user-page/components/WidgetSettingsForm.tsx +++ b/app/features/user-page/components/WidgetSettingsForm.tsx @@ -10,7 +10,7 @@ import { TIMEZONE_OPTIONS, } from "../core/widgets/widget-form-schemas"; import type { loader } from "../loaders/u.$identifier.edit-widgets.server"; -import { USER } from "../user-page-constants"; +import { SENS_OPTIONS, USER } from "../user-page-constants"; import { GameBadgeSelectField } from "./GameBadgeSelectField"; export function WidgetSettingsForm({ @@ -144,11 +144,6 @@ function FavoriteBadgesField() { ); } -const SENS_OPTIONS = [ - -50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, - 40, 45, 50, -]; - function SensFields() { const { t } = useTranslation(["user"]); const { values, setValue, onFieldChange } = useFormFieldContext(); diff --git a/app/features/user-page/core/widgets/portfolio.ts b/app/features/user-page/core/widgets/portfolio.ts index 973573d50..0d63d7104 100644 --- a/app/features/user-page/core/widgets/portfolio.ts +++ b/app/features/user-page/core/widgets/portfolio.ts @@ -246,7 +246,7 @@ export const DEFAULT_WIDGETS: StoredWidget[] = [ { id: "teams" }, { id: "sens", - settings: { controller: "s2-pro-con", motionSens: null, stickSens: null }, + settings: { controller: "s1-pro-con", motionSens: null, stickSens: null }, }, { id: "join-date" }, ]; diff --git a/app/features/user-page/core/widgets/widget-form-schemas.ts b/app/features/user-page/core/widgets/widget-form-schemas.ts index 195c4a7b6..e58643a20 100644 --- a/app/features/user-page/core/widgets/widget-form-schemas.ts +++ b/app/features/user-page/core/widgets/widget-form-schemas.ts @@ -19,7 +19,8 @@ import { } from "~/form/fields"; import type { FormObjectSchema, SelectOption } from "~/form/types"; import { GAME_BADGE_IDS } from "~/modules/in-game-lists/game-badge-ids"; -import { USER } from "../../user-page-constants"; +import { superRefine } from "~/utils/schema"; +import { SENS_OPTIONS, USER } from "../../user-page-constants"; export const bioSchema = v.object({ bio: textAreaOptional({ @@ -47,11 +48,18 @@ export const xRankPeaksSchema = v.object({ }), }); -export const timezoneSchema = v.object({ - timezone: selectDynamic({ - label: "labels.timezone", +export const timezoneSchema = v.pipe( + v.object({ + timezone: selectDynamic({ + label: "labels.timezone", + }), }), -}); + superRefine((data, ctx) => { + if (TIMEZONES.includes(data.timezone)) return; + + ctx.addIssue({ message: "Invalid timezone", path: ["timezone"] }); + }), +); export const TIMEZONE_OPTIONS: SelectOption[] = TIMEZONES.map((tz) => ({ value: tz, @@ -67,8 +75,9 @@ export const favoriteStageSchema = v.object({ export const peakXpUnverifiedSchema = v.object({ peakXp: numberField({ label: "labels.peakXp", - minLength: 4, maxLength: 4, + min: USER.PEAK_XP_MIN, + max: USER.PEAK_XP_MAX, }), division: select({ label: "labels.division", @@ -87,6 +96,8 @@ export const peakXpWeaponSchema = v.object({ const CONTROLLERS = ["s1-pro-con", "s2-pro-con", "grip", "handheld"] as const; +const sensValueSchema = v.nullable(v.picklist(SENS_OPTIONS)); + export const sensSchema = v.object({ controller: select({ label: "labels.controller", @@ -94,10 +105,9 @@ export const sensSchema = v.object({ value: controller, label: `options.controller.${controller}` as const, })), - initialValue: "s2-pro-con", }), - motionSens: customField({ initialValue: null }, v.nullable(v.number())), - stickSens: customField({ initialValue: null }, v.nullable(v.number())), + motionSens: customField({ initialValue: null }, sensValueSchema), + stickSens: customField({ initialValue: null }, sensValueSchema), }); export const artSchema = v.object({ diff --git a/app/features/user-page/routes/u.$identifier.edit-widgets.module.css b/app/features/user-page/routes/u.$identifier.edit-widgets.module.css index f5eca1c4e..5299195ee 100644 --- a/app/features/user-page/routes/u.$identifier.edit-widgets.module.css +++ b/app/features/user-page/routes/u.$identifier.edit-widgets.module.css @@ -223,6 +223,17 @@ display: flex; flex-direction: column; gap: var(--s-4); + + /** Narrow profiles show the side widgets above the main ones, so the editor lists them in that order too. */ + & .sideSlotSection { + order: -1; + } + + @container (min-width: 768px) { + & .sideSlotSection { + order: 0; + } + } } .empty { diff --git a/app/features/user-page/routes/u.$identifier.edit-widgets.tsx b/app/features/user-page/routes/u.$identifier.edit-widgets.tsx index c93ef1e22..7255dc762 100644 --- a/app/features/user-page/routes/u.$identifier.edit-widgets.tsx +++ b/app/features/user-page/routes/u.$identifier.edit-widgets.tsx @@ -35,6 +35,7 @@ import { findWidgetById, maxWidgetsPerSlot, } from "~/features/user-page/core/widgets/portfolio"; +import type { WidgetId } from "~/features/user-page/core/widgets/types"; import { getWidgetFormSchema } from "~/features/user-page/core/widgets/widget-form-schemas"; import { USER } from "~/features/user-page/user-page-constants"; import { useUnsavedChangesChecker } from "~/form/UnsavedChangesGuard"; @@ -291,7 +292,7 @@ function AvailableWidgetsList({ if (!searchLower) return true; return [ - t(`user:widget.${widget.id}` as const), + t(widgetNameKey(widget.id)), t( `user:widgets.description.${widget.id}` as const, widgetDescriptionParams(widget.id), @@ -338,7 +339,7 @@ function AvailableWidgetsList({