From 18aaff12e21cada9f7932eee5d703a812d48affe Mon Sep 17 00:00:00 2001 From: Padreug Date: Mon, 21 Sep 2026 14:51:24 +0200 Subject: [PATCH] fix(chatelet): root-relative routes so room deep links and refreshes work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chatelet module hardcoded '/chatelet' in its route paths while the standalone also mounts under a Vite base path ('/chatelet/'), which the router applies too. The two stacked: in-app URLs came out double-prefixed ('/chatelet/chatelet/'), and a direct load or refresh of a room URL stripped the base to '/', matched nothing, and fell back to the room list — so room deep links and page refreshes were broken. Make the routes root-relative ('/' list, '/:id' detail, '/my-bookings') and let the base path supply the prefix. Drop the now-redundant '/' -> '/chatelet' redirect, point the list/detail/browse links and the Rooms tab at the new paths, and key the tab's active state off the route name (a '/' prefix test would match everything). Verified on a production build served under '/chatelet/' like nginx: deep link to a room, refresh on it, list, and in-app room clicks all resolve to the detail page with a single-prefixed URL. vue-tsc build passes. Co-Authored-By: Claude Fable 5.1 --- src/chatelet-app/App.vue | 6 +++++- src/chatelet-app/app.ts | 3 ++- src/modules/chatelet/index.ts | 12 ++++++++---- src/modules/chatelet/views/ChateletPage.vue | 2 +- src/modules/chatelet/views/MyBookingsPage.vue | 4 ++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/chatelet-app/App.vue b/src/chatelet-app/App.vue index b98cf17..359d50f 100644 --- a/src/chatelet-app/App.vue +++ b/src/chatelet-app/App.vue @@ -15,7 +15,7 @@ const { isAuthenticated } = useAuth() // auth-gated the same way events gates My tickets: ghosted when logged out, // and a tap explains instead of bouncing to /login. const tabs = computed(() => [ - { name: 'Rooms', icon: BedDouble, path: '/chatelet' }, + { name: 'Rooms', icon: BedDouble, path: '/' }, { name: 'My bookings', icon: CalendarCheck, @@ -34,6 +34,10 @@ const tabs = computed(() => [ ]) function isActive(path: string): boolean { + // "/" is the Rooms tab: active on the room list and any room detail + // ("/:id"). A prefix test would match every route, so key off the route + // name instead. + if (path === '/') return route.name === 'chatelet' || route.name === 'chatelet-detail' return route.path === path || route.path.startsWith(path + '/') } diff --git a/src/chatelet-app/app.ts b/src/chatelet-app/app.ts index 13a76af..da735a4 100644 --- a/src/chatelet-app/app.ts +++ b/src/chatelet-app/app.ts @@ -39,7 +39,8 @@ export async function createAppInstance() { const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ - { path: '/', redirect: '/chatelet' }, + // "/" is the room list (chatelet module route). No redirect: the + // standalone's base path already scopes every route under it. { path: '/login', name: 'login', diff --git a/src/modules/chatelet/index.ts b/src/modules/chatelet/index.ts index f71e445..0c6fd69 100644 --- a/src/modules/chatelet/index.ts +++ b/src/modules/chatelet/index.ts @@ -17,7 +17,11 @@ export const chateletModule = createModulePlugin({ routes: [ { - path: '/chatelet', + // Root-relative: the standalone mounts under a base path (Vite base, + // e.g. "/chatelet/") that the router already applies, so hardcoding + // "/chatelet" here double-prefixed every URL ("/chatelet/chatelet/…") + // and made deep links / refreshes fall back to the list. + path: '/', name: 'chatelet', component: () => import('./views/ChateletPage.vue'), meta: { @@ -26,14 +30,14 @@ export const chateletModule = createModulePlugin({ }, }, { - path: '/chatelet/:id', + path: '/:id', name: 'chatelet-detail', component: () => import('./views/ChateletDetailPage.vue'), meta: { title: 'Room', requiresAuth: false }, }, { - // Mirrors events' /my-tickets; kept off /chatelet/* so it never - // collides with the :id room route. + // Mirrors events' /my-tickets. A static path, so it ranks above the + // "/:id" room route and never resolves as a room id. path: '/my-bookings', name: 'chatelet-my-bookings', component: () => import('./views/MyBookingsPage.vue'), diff --git a/src/modules/chatelet/views/ChateletPage.vue b/src/modules/chatelet/views/ChateletPage.vue index 04418ff..cbe2202 100644 --- a/src/modules/chatelet/views/ChateletPage.vue +++ b/src/modules/chatelet/views/ChateletPage.vue @@ -14,7 +14,7 @@ const { rooms, isLoading, loadRooms } = useChatelet() onMounted(loadRooms) function open(id: string) { - router.push(`/chatelet/${id}`) + router.push(`/${id}`) } function priceLabel(r: Room): string { diff --git a/src/modules/chatelet/views/MyBookingsPage.vue b/src/modules/chatelet/views/MyBookingsPage.vue index 8dfbc36..8eea28f 100644 --- a/src/modules/chatelet/views/MyBookingsPage.vue +++ b/src/modules/chatelet/views/MyBookingsPage.vue @@ -76,7 +76,7 @@ function statusBadge(b: GuestBooking): { label: string; variant: BadgeVariant } {{ group.title }} - +

No bookings yet.