From c0508a2f22c90c66694d633e152c8bc447c7ed73 Mon Sep 17 00:00:00 2001 From: Hafiz Date: Tue, 5 Aug 2025 11:59:11 -0500 Subject: [PATCH] Fix profile modal tab navigation URLs for both own and other users profiles - Add routes for /user/profile, /user/stats, and /user/achievements - Update selectPage() to properly update URLs when switching tabs - Own profile uses /user/{tab} format - Other users' profiles use /profile/{userId}#{tab} format - Parse hash fragments when navigating to other users' profile tabs - Ensure direct navigation to tab URLs opens correct tab --- .../src/components/userMenu/profile.vue | 23 ++++++++++++++++--- website/client/src/router/index.js | 7 ++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/website/client/src/components/userMenu/profile.vue b/website/client/src/components/userMenu/profile.vue index c85e69f968..09fd792e07 100644 --- a/website/client/src/components/userMenu/profile.vue +++ b/website/client/src/components/userMenu/profile.vue @@ -1126,7 +1126,12 @@ export default { this.loadUser(); this.oldTitle = this.$store.state.title; this.handleExternalLinks(); - this.selectPage(this.startingPage); + // Check if there's a hash in the URL to determine the starting page + let pageToSelect = this.startingPage; + if (window.location.hash && (window.location.hash === '#stats' || window.location.hash === '#achievements')) { + pageToSelect = window.location.hash.substring(1); + } + this.selectPage(pageToSelect); this.$root.$on('habitica:report-profile-result', () => { this.loadUser(); }); @@ -1211,10 +1216,22 @@ export default { }, selectPage (page) { this.selectedPage = page || 'profile'; - window.history.replaceState(null, null, ''); + // Update URL based on whether viewing own profile or another user's profile + let newPath; + if (this.userId === this.userLoggedIn._id) { + // Own profile - use /user/profile, /user/stats, /user/achievements + newPath = `/user/${page}`; + } else { + // Other user's profile - use /profile/:userId#stats, /profile/:userId#achievements + newPath = `/profile/${this.userId}`; + if (page !== 'profile') { + newPath += `#${page}`; + } + } + window.history.replaceState(null, null, newPath); this.$store.dispatch('common:setTitle', { section: this.$t('user'), - subSection: this.$t(this.startingPage), + subSection: this.$t(page), }); }, getNextIncentive () { diff --git a/website/client/src/router/index.js b/website/client/src/router/index.js index 5c02b358d5..7adef8675b 100644 --- a/website/client/src/router/index.js +++ b/website/client/src/router/index.js @@ -98,6 +98,9 @@ const router = new VueRouter({ path: '/profile/:userId', props: true, }, + { name: 'profile', path: '/user/profile' }, + { name: 'stats', path: '/user/stats' }, + { name: 'achievements', path: '/user/achievements' }, { path: '/inventory', component: InventoryContainer, @@ -332,6 +335,10 @@ router.beforeEach(async (to, from, next) => { if (to.params.startingPage !== undefined) { startingPage = to.params.startingPage; } + // Check if there's a hash in the URL for stats or achievements + if (to.hash === '#stats' || to.hash === '#achievements') { + startingPage = to.hash.substring(1); + } if (from.name === null) { store.state.postLoadModal = `profile/${to.params.userId}`; return next({ name: 'tasks' });