From c80a8461acac35755b1b3b34ef78eb92e97c66d6 Mon Sep 17 00:00:00 2001 From: Padreug Date: Thu, 7 May 2026 12:26:26 +0200 Subject: [PATCH 1/2] feat(layout): adopt unified AppShell across hub + 7 standalones (Phase B) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor every entry point to consume the Phase A primitives. Each App.vue collapses from 47-127 lines of shell boilerplate into a thin AppShell consumer that declares its own BottomTab[] and active-path matcher; Hub.vue now reuses ProfileSheetTrigger + PreferencesRow instead of inlining its own bottom row. The Settings tab is dropped from activities and libra (theme/lang/currency now live in the shared profile sheet — see #50 for cleanup of orphaned SettingsPage.vue routes). The redundant top-right LogIn icon is dropped from every standalone (the bottom-nav profile slot covers that affordance). BottomNav.vue gains optional `onClick`, `disabled`, and an optional `path` on BottomTab so consumers can express coming-soon toasts (forum's Spaces/ Search/Alerts) and auth-gated tabs (market's "My Store" → toast when logged out) without reaching back into shell internals. While in here: remove the page-level Refresh buttons in ActivitiesPage, EventsPage, MyTicketsPage, and NostrFeed. The relay-subscription + VisibilityService reconnect path keeps these views fresh; manual refresh was redundant and was now visually colliding with the new top-right HubPill. Net: -434 lines. --- src/accounting-app/App.vue | 87 ++---------- src/activities-app/App.vue | 82 +++-------- src/chat-app/App.vue | 47 ++----- src/components/layout/BottomNav.vue | 33 +++-- src/forum-app/App.vue | 107 +++------------ src/market-app/App.vue | 127 +++++------------- .../activities/views/ActivitiesPage.vue | 14 +- src/modules/activities/views/EventsPage.vue | 6 +- .../activities/views/MyTicketsPage.vue | 4 - .../nostr-feed/components/NostrFeed.vue | 10 -- src/pages/Hub.vue | 106 ++------------- src/tasks-app/App.vue | 47 ++----- src/wallet-app/App.vue | 48 ++----- 13 files changed, 142 insertions(+), 576 deletions(-) diff --git a/src/accounting-app/App.vue b/src/accounting-app/App.vue index 8fe3aa8..e5800f2 100644 --- a/src/accounting-app/App.vue +++ b/src/accounting-app/App.vue @@ -1,94 +1,29 @@ diff --git a/src/activities-app/App.vue b/src/activities-app/App.vue index 7214093..b7ff6d6 100644 --- a/src/activities-app/App.vue +++ b/src/activities-app/App.vue @@ -1,84 +1,38 @@ diff --git a/src/chat-app/App.vue b/src/chat-app/App.vue index 6e5a91d..e902645 100644 --- a/src/chat-app/App.vue +++ b/src/chat-app/App.vue @@ -1,47 +1,16 @@ diff --git a/src/components/layout/BottomNav.vue b/src/components/layout/BottomNav.vue index e74b67d..f52ba44 100644 --- a/src/components/layout/BottomNav.vue +++ b/src/components/layout/BottomNav.vue @@ -8,10 +8,16 @@ export interface BottomTab { name: string /** lucide-vue-next icon component. */ icon: Component - /** Router path to push on click. */ - path: string + /** Router path to push on click. Optional — coming-soon entries omit it. */ + path?: string /** Optional unread/cart badge count. Falsy values hide the badge. */ badge?: number | null + /** Click override. When provided, replaces the default router.push(path). + * Consumers use this for coming-soon toasts or auth-gated CTAs. */ + onClick?: () => void + /** Render the entry ghosted (opacity-reduced). Used for coming-soon and + * for auth-required tabs when the user is logged out. */ + disabled?: boolean } interface Props { @@ -28,6 +34,14 @@ interface Props { const props = withDefaults(defineProps(), { loggedOutOpensSheet: false }) const router = useRouter() + +function onTabClick(tab: BottomTab) { + if (tab.onClick) { + tab.onClick() + return + } + if (tab.path) router.push(tab.path) +}