test #6

Closed
Marti wants to merge 22 commits from dev into main
Owner
No description provided.
Marti closed this pull request 2026-05-13 14:56:52 +02:00
First-time contributor

1. Executive Summary

This PR focuses on architectural refactoring, internationalization (i18n) migration, and feature enhancements. Key changes include replacing Prettier with oxfmt, migrating hardcoded UI strings to i18next, extracting reusable components (StatsLine, InfoRow, SocialsRow, etc.), and adding user social link management with Mania key filtering. API hooks have been refactored to return useQuery/useMutation objects directly, aligning with modern TanStack Query patterns. Dependency versions are also bumped across the board.

2. Critical Issues (High Priority)

  • src/components/user/panels/top/UserTopPanel.tsx: mode is passed to <UserGradeChart mode={mode} /> but is never destructured from useUserContext(). This will throw a ReferenceError and crash the component.
  • src/components/beatmap/BeatmapsetBeatmapInfo.tsx: The StatsLine component uses next || prev for the progress bar value. In osu!, 0 is a valid difficulty stat (e.g., AR 0). Using || will incorrectly fallback to prev when next is 0. Use next ?? prev instead.
  • src/utils/fetcher.ts: headers["Content-Type"] = "application/json"; unconditionally overwrites existing headers. This will break requests that require multipart/form-data or other content types. Revert to headers["Content-Type"] = headers["Content-Type"] ?? "application/json";.
  • src/components/user/panels/top/SocialsRow.tsx: if ((!socials || socials.length < 0) && !editable) return null; contains a logic bug. socials.length < 0 is always false. Use !socials?.length or socials.length === 0.
  • src/components/user/panels/medals/UserMedalsPanel.tsx: Uses t("no_medals"), but this key is missing from the translation.json diff (it was previously no_medals_yet). This will render the raw key in the UI.

3. Suggestions & Improvements

  • Debug Statements: Remove console.log(value); and the console.log block inside SocialsRow.tsx (EditForm) before merging.
  • Audio Volume Limiter: src/components/web/AudioVolume.tsx sets max={0.4}. Unless this is an intentional limiter for your audio player, volume sliders typically expect max={1}. Verify if this is deliberate.
  • XSS Prevention in SocialBadge.tsx: Directly replacing {{username}} in social.url without validation could be risky if URLs are user-controllable. Consider using new URL() to validate or sanitize the base URL before interpolation.
  • Map Construction Optimization: useMedals in masterdata.ts iterates twice (once to build the list Map, once to build groups). Consider combining into a single reduce pass for cleaner, more performant code.
  • Form Initialization: const NEW_SOCIAL: Partial<UserSocialCreate> = {}; is type-safe but may cause validation errors if social_code or username are required by the backend. Ensure the form's onSubmit handles missing fields gracefully or sets sensible defaults.
  • i18n Sync: Ensure all newly added translation keys are synced to other locale files in public/locales/ to prevent missing translations in non-English builds.

4. Actionable Checklist

🐛 Bug Fixes

  • Fix UserTopPanel.tsx: Destructure mode from useUserContext() (const { user, mode } = useUserContext();)
  • Fix StatsLine.tsx: Replace next || prev with next ?? prev to correctly handle 0 values
  • Revert fetcher.ts Content-Type logic to headers["Content-Type"] = headers["Content-Type"] ?? "application/json";
  • Fix SocialsRow.tsx: Change socials.length < 0 to !socials?.length
  • Add missing "no_medals" translation key to public/locales/en/translation.json

🧹 Cleanup & Best Practices

  • Remove all console.log statements from SocialsRow.tsx
  • Verify AudioVolume.tsx max={0.4} is intentional; change to 1 if not
  • Sanitize or validate social.url in SocialBadge.tsx before string replacement
  • Refactor useMedals in masterdata.ts to use a single-pass reduce for map construction and grouping
  • Sync new i18n keys across all locale files in public/locales/

📦 Dependency & Tooling

  • Verify package.json peer dependency compatibility after major bumps (React 19, TanStack v1/v5, Vite 6)
  • Confirm .oxfmtrc.json configuration aligns with existing project linting rules
### 1. Executive Summary This PR focuses on architectural refactoring, internationalization (i18n) migration, and feature enhancements. Key changes include replacing Prettier with `oxfmt`, migrating hardcoded UI strings to `i18next`, extracting reusable components (`StatsLine`, `InfoRow`, `SocialsRow`, etc.), and adding user social link management with Mania key filtering. API hooks have been refactored to return `useQuery`/`useMutation` objects directly, aligning with modern TanStack Query patterns. Dependency versions are also bumped across the board. ### 2. Critical Issues (High Priority) - **`src/components/user/panels/top/UserTopPanel.tsx`**: `mode` is passed to `<UserGradeChart mode={mode} />` but is never destructured from `useUserContext()`. This will throw a `ReferenceError` and crash the component. - **`src/components/beatmap/BeatmapsetBeatmapInfo.tsx`**: The `StatsLine` component uses `next || prev` for the progress bar value. In osu!, `0` is a valid difficulty stat (e.g., AR 0). Using `||` will incorrectly fallback to `prev` when `next` is `0`. Use `next ?? prev` instead. - **`src/utils/fetcher.ts`**: `headers["Content-Type"] = "application/json";` unconditionally overwrites existing headers. This will break requests that require `multipart/form-data` or other content types. Revert to `headers["Content-Type"] = headers["Content-Type"] ?? "application/json";`. - **`src/components/user/panels/top/SocialsRow.tsx`**: `if ((!socials || socials.length < 0) && !editable) return null;` contains a logic bug. `socials.length < 0` is always `false`. Use `!socials?.length` or `socials.length === 0`. - **`src/components/user/panels/medals/UserMedalsPanel.tsx`**: Uses `t("no_medals")`, but this key is missing from the `translation.json` diff (it was previously `no_medals_yet`). This will render the raw key in the UI. ### 3. Suggestions & Improvements - **Debug Statements**: Remove `console.log(value);` and the `console.log` block inside `SocialsRow.tsx` (`EditForm`) before merging. - **Audio Volume Limiter**: `src/components/web/AudioVolume.tsx` sets `max={0.4}`. Unless this is an intentional limiter for your audio player, volume sliders typically expect `max={1}`. Verify if this is deliberate. - **XSS Prevention in `SocialBadge.tsx`**: Directly replacing `{{username}}` in `social.url` without validation could be risky if URLs are user-controllable. Consider using `new URL()` to validate or sanitize the base URL before interpolation. - **Map Construction Optimization**: `useMedals` in `masterdata.ts` iterates twice (once to build the `list` Map, once to build `groups`). Consider combining into a single `reduce` pass for cleaner, more performant code. - **Form Initialization**: `const NEW_SOCIAL: Partial<UserSocialCreate> = {};` is type-safe but may cause validation errors if `social_code` or `username` are required by the backend. Ensure the form's `onSubmit` handles missing fields gracefully or sets sensible defaults. - **i18n Sync**: Ensure all newly added translation keys are synced to other locale files in `public/locales/` to prevent missing translations in non-English builds. ### 4. Actionable Checklist **🐛 Bug Fixes** - [ ] Fix `UserTopPanel.tsx`: Destructure `mode` from `useUserContext()` (`const { user, mode } = useUserContext();`) - [ ] Fix `StatsLine.tsx`: Replace `next || prev` with `next ?? prev` to correctly handle `0` values - [ ] Revert `fetcher.ts` Content-Type logic to `headers["Content-Type"] = headers["Content-Type"] ?? "application/json";` - [ ] Fix `SocialsRow.tsx`: Change `socials.length < 0` to `!socials?.length` - [ ] Add missing `"no_medals"` translation key to `public/locales/en/translation.json` **🧹 Cleanup & Best Practices** - [ ] Remove all `console.log` statements from `SocialsRow.tsx` - [ ] Verify `AudioVolume.tsx` `max={0.4}` is intentional; change to `1` if not - [ ] Sanitize or validate `social.url` in `SocialBadge.tsx` before string replacement - [ ] Refactor `useMedals` in `masterdata.ts` to use a single-pass `reduce` for map construction and grouping - [ ] Sync new i18n keys across all locale files in `public/locales/` **📦 Dependency & Tooling** - [ ] Verify `package.json` peer dependency compatibility after major bumps (React 19, TanStack v1/v5, Vite 6) - [ ] Confirm `.oxfmtrc.json` configuration aligns with existing project linting rules

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
wysi/client!6
No description provided.