From f14eb46002b296927ae05c5ca46e13483f5288c9 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Thu, 19 Feb 2026 17:57:34 -0500 Subject: [PATCH 1/2] feat(achievement): sync initial tab --- .../Controllers/AchievementController.php | 4 ++++ .../Data/AchievementShowPagePropsData.php | 2 ++ app/Platform/Enums/AchievementPageTab.php | 16 ++++++++++++++++ .../achievements/hooks/useAchievementShowTabs.ts | 11 ++++++----- .../models/achievement-show-tab.model.ts | 1 - .../js/features/achievements/models/index.ts | 1 - .../achievements/models/tab-config.model.ts | 4 +--- .../achievements/state/achievements.atoms.ts | 4 +--- resources/js/pages/achievement/[achievement].tsx | 10 +++++++++- resources/js/types/generated.d.ts | 2 ++ 10 files changed, 41 insertions(+), 14 deletions(-) create mode 100644 app/Platform/Enums/AchievementPageTab.php delete mode 100644 resources/js/features/achievements/models/achievement-show-tab.model.ts diff --git a/app/Platform/Controllers/AchievementController.php b/app/Platform/Controllers/AchievementController.php index f65d583d45..264ea82dc0 100644 --- a/app/Platform/Controllers/AchievementController.php +++ b/app/Platform/Controllers/AchievementController.php @@ -19,6 +19,7 @@ use App\Platform\Data\AchievementShowPagePropsData; use App\Platform\Data\GameAchievementSetData; use App\Platform\Data\GameData; +use App\Platform\Enums\AchievementPageTab; use App\Platform\Enums\AchievementSetType; use Illuminate\Http\Request; use Illuminate\Support\Collection; @@ -67,6 +68,8 @@ public function show(Request $request, Achievement $achievement): InertiaRespons [$proximityAchievements, $promotedAchievementCount] = $this->buildProximityAchievements($achievement, $user); + $initialTab = AchievementPageTab::tryFrom($request->query('tab', '')) ?? AchievementPageTab::Comments; + $subscriptionService = new SubscriptionService(); $props = new AchievementShowPagePropsData( @@ -108,6 +111,7 @@ public function show(Request $request, Achievement $achievement): InertiaRespons : null, proximityAchievements: $proximityAchievements, promotedAchievementCount: $promotedAchievementCount, + initialTab: $initialTab, ); return Inertia::render('achievement/[achievement]', $props); diff --git a/app/Platform/Data/AchievementShowPagePropsData.php b/app/Platform/Data/AchievementShowPagePropsData.php index 2f418c8ffe..d54c2be7a6 100644 --- a/app/Platform/Data/AchievementShowPagePropsData.php +++ b/app/Platform/Data/AchievementShowPagePropsData.php @@ -6,6 +6,7 @@ use App\Community\Data\CommentData; use App\Data\UserPermissionsData; +use App\Platform\Enums\AchievementPageTab; use Illuminate\Support\Collection; use Spatie\LaravelData\Data; use Spatie\TypeScriptTransformer\Attributes\TypeScript; @@ -27,6 +28,7 @@ public function __construct( public ?GameAchievementSetData $gameAchievementSet = null, public ?array $proximityAchievements = null, public int $promotedAchievementCount = 0, + public AchievementPageTab $initialTab = AchievementPageTab::Comments, ) { } } diff --git a/app/Platform/Enums/AchievementPageTab.php b/app/Platform/Enums/AchievementPageTab.php new file mode 100644 index 0000000000..12f4a4ca1b --- /dev/null +++ b/app/Platform/Enums/AchievementPageTab.php @@ -0,0 +1,16 @@ + { - const index = tabValues.indexOf(value as AchievementShowTab); + const index = tabValues.indexOf(value as AchievementTab); if (index !== -1) { setActiveIndex(index); } - setCurrentTab(value as AchievementShowTab); + setCurrentTab(value as AchievementTab); }, [setActiveIndex, setCurrentTab], ); diff --git a/resources/js/features/achievements/models/achievement-show-tab.model.ts b/resources/js/features/achievements/models/achievement-show-tab.model.ts deleted file mode 100644 index 8c3e5758f0..0000000000 --- a/resources/js/features/achievements/models/achievement-show-tab.model.ts +++ /dev/null @@ -1 +0,0 @@ -export type AchievementShowTab = 'tips' | 'comments' | 'unlocks' | 'changelog'; diff --git a/resources/js/features/achievements/models/index.ts b/resources/js/features/achievements/models/index.ts index d1dd37f167..113638b7fb 100644 --- a/resources/js/features/achievements/models/index.ts +++ b/resources/js/features/achievements/models/index.ts @@ -1,2 +1 @@ -export * from './achievement-show-tab.model'; export * from './tab-config.model'; diff --git a/resources/js/features/achievements/models/tab-config.model.ts b/resources/js/features/achievements/models/tab-config.model.ts index a91db96cd7..a9d8832d21 100644 --- a/resources/js/features/achievements/models/tab-config.model.ts +++ b/resources/js/features/achievements/models/tab-config.model.ts @@ -1,8 +1,6 @@ import type { ReactNode } from 'react'; -import type { AchievementShowTab } from './achievement-show-tab.model'; - export interface TabConfig { - value: AchievementShowTab; + value: App.Platform.Enums.AchievementPageTab; label: ReactNode; } diff --git a/resources/js/features/achievements/state/achievements.atoms.ts b/resources/js/features/achievements/state/achievements.atoms.ts index bb78dbc3e7..622539d421 100644 --- a/resources/js/features/achievements/state/achievements.atoms.ts +++ b/resources/js/features/achievements/state/achievements.atoms.ts @@ -1,5 +1,3 @@ import { atom } from 'jotai'; -import type { AchievementShowTab } from '../models'; - -export const currentTabAtom = atom('comments'); +export const currentTabAtom = atom('comments'); diff --git a/resources/js/pages/achievement/[achievement].tsx b/resources/js/pages/achievement/[achievement].tsx index b560bcbe54..222f95050d 100644 --- a/resources/js/pages/achievement/[achievement].tsx +++ b/resources/js/pages/achievement/[achievement].tsx @@ -1,3 +1,5 @@ +import { useHydrateAtoms } from 'jotai/utils'; + import { SEO } from '@/common/components/SEO'; import { usePageProps } from '@/common/hooks/usePageProps'; import { AppLayout } from '@/common/layouts/AppLayout'; @@ -5,6 +7,7 @@ import type { AppPage } from '@/common/models'; import { AchievementShowRoot } from '@/features/achievements/components/+show'; import { AchievementShowSidebarRoot } from '@/features/achievements/components/+show-sidebar'; import { useAchievementMetaDescription } from '@/features/achievements/hooks/useAchievementMetaDescription'; +import { currentTabAtom } from '@/features/achievements/state/achievements.atoms'; import type { TranslatedString } from '@/types/i18next'; // The server always provides these fields on this page, but the generated @@ -18,7 +21,12 @@ type HydratedAchievement = App.Platform.Data.Achievement & { }; const AchievementShow: AppPage = () => { - const { achievement } = usePageProps(); + const { achievement, initialTab } = usePageProps(); + + useHydrateAtoms([ + [currentTabAtom, initialTab], + // + ]); const hydratedAchievement = achievement as HydratedAchievement; diff --git a/resources/js/types/generated.d.ts b/resources/js/types/generated.d.ts index 09e81992c4..7044e54b66 100644 --- a/resources/js/types/generated.d.ts +++ b/resources/js/types/generated.d.ts @@ -667,6 +667,7 @@ declare namespace App.Platform.Data { gameAchievementSet: App.Platform.Data.GameAchievementSet | null; proximityAchievements: Array | null; promotedAchievementCount: number; + initialTab: App.Platform.Enums.AchievementPageTab; }; export type AggregateAchievementSetCredits = { achievementsAuthors: Array; @@ -1212,6 +1213,7 @@ declare namespace App.Platform.Data { declare namespace App.Platform.Enums { export type UnlockMode = 0 | 1; export type AchievementAuthorTask = 'artwork' | 'design' | 'logic' | 'testing' | 'writing'; + export type AchievementPageTab = 'changelog' | 'comments' | 'tips' | 'unlocks'; export type AchievementSetAuthorTask = 'artwork' | 'banner'; export type AchievementSetType = | 'core' From d71085ce56945685fe5b89f5e14402fb74e23b32 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Thu, 19 Feb 2026 18:22:50 -0500 Subject: [PATCH 2/2] test: mitigate flake --- .../ForumCommentResultDisplay.test.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/js/features/search/components/ForumCommentResultDisplay/ForumCommentResultDisplay.test.tsx b/resources/js/features/search/components/ForumCommentResultDisplay/ForumCommentResultDisplay.test.tsx index 89f86663d3..5cb3b5a62e 100644 --- a/resources/js/features/search/components/ForumCommentResultDisplay/ForumCommentResultDisplay.test.tsx +++ b/resources/js/features/search/components/ForumCommentResultDisplay/ForumCommentResultDisplay.test.tsx @@ -72,7 +72,10 @@ describe('Component: ForumCommentResultDisplay', () => { it('given the comment has no forum topic, does not display a topic section', () => { // ARRANGE - const forumComment = createForumTopicComment({ forumTopic: undefined }); + const forumComment = createForumTopicComment({ + forumTopic: undefined, + body: 'Some post text.', + }); render(); @@ -82,7 +85,7 @@ describe('Component: ForumCommentResultDisplay', () => { it('displays when the comment was posted', () => { // ARRANGE - const forumComment = createForumTopicComment(); + const forumComment = createForumTopicComment({ body: 'Some post text.' }); render();