feat(activities): UI tweaks across feed, detail, hosting, calendar, scan, shell #91
No reviewers
Labels
No labels
app:activities
app:chat
app:events
app:forum
app:libra
app:market
app:restaurant
app:tasks
app:wallet
app:webapp
bug
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aiolabs/webapp!91
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/ui-tweaks"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #86 (pending events now visually grey out, not just badge-only).
A pass of UI tweaks across the activities standalone plus a small shell-level change that touches every standalone. Each commit is narrowly scoped so individual pieces can be reverted/picked.
Shell (every standalone)
13ece88). The fixed top-right "Back to hub" pill is gone; a hamburger button opens a right-side sheet reusingProfileSheetContent(identity card, back-to-hub link, theme/lang/currency prefs, profile settings or log-in CTA). The Profile entry is removed fromBottomNavand theloggedOutOpensSheetplumbing is dropped —Hub.vuestill mountsProfileSheetTriggerdirectly so it's unaffected.ProfileSheetContentgains anapp-navslot;AppShellexposes an optionalsidebarNavprop.Activities feed (ActivitiesPage)
b292cdb). Past events folds into the existing collapsible (renamed "Filters") alongside Categories; the trigger badge counts past-events + categories so hidden toggles stay discoverable. The standalone "Filters active / Clear all" notice is gone — Clear all sits inline next to the trigger. Header tightened, inter-row margins reduced.ce7f062). Filters icon + Clear-all sit in a stationary left-aligned column; only the temporal pills scroll horizontally. Clear all tucked tightly under the Filters icon. Badge no longer clipped by an overflow-x container.Activity cards (ActivityCard / ActivityList)
ea1e408). Cards without an image skip the 16:9 placeholder and surface badges inline at the top of the content block.0382f02→917d4c4→0382f02, plus folded follow-ups via the same commit). Pending/rejected events wash out (opacity-50 grayscaleon a wrapper div); the status badge is pulled outside the wash-out wrapper as an absolute overlay (-bottom-1 right-2, slight downward spill) so it keeps full color — both pending and rejected use the destructive token. Compact rows in the Hosting view now show a small left-aligned thumbnail (w-20 h-20,self-center,ml-3,rounded-md) when the event carries an image; Card root becomesrelative(no overflow-hidden), the hero block picks uprounded-t-lgso corners still match.Activity detail page (ActivityDetailPage)
4924e70). Bookmark heart moves from the top bar to the right of the title; When/Where become caption-style lines directly under the title (no info cards); description moves directly under the title/info separator; organizer card moves to the bottom; the owned-tickets CTA is promoted to filled primary while Buy-another is demoted to outline so the My-Tickets path jumps out; ticket availability is rendered as anxsmuted caption directly under the buy CTA.f01d5aa). When the user owns the LNbits event: top-bar Scan + Edit buttons are dropped; Edit becomes a prominent filled-primary icon button right of the title; the Buy CTA is replaced with a full-width Scan tickets CTA (hoisted outside theticketInfogate so it always renders for the host). BookmarkButton + RSVPButton are hidden (favoriting / RSVPing your own event are noise). The badge row leads with "Yours" in the highlighted secondary variant; category and tags drop to outline.Hosting feed (ActivitiesPage when onlyHosting)
f01d5aa). Date picker strip + calendar shortcut and the entire Filters/temporal-pills row are hidden; search bar stays. Activity list renders compact rows via a newcompactprop onActivityList+ActivityCard.Bottom navigation
a48e3ac). Tabs become Home, My tickets, Hosting, Map, Favorites. Feed is relabeled "Home" (en/fr; es already "Inicio"). Hosting is a synthetic tab — no path of its own; it toggles the existingonlyHostingfeed filter and lands on/activities, with Home as the inverse (clears the filter on tap). Calendar leaves the bottom nav: a small calendar icon button sits to the right of the week strip in ActivitiesPage. Create activity leaves the bottom nav too; a full-width "+ Create activity" CTA appears at the top of the feed only when the Hosting tab is active.BottomTabgains an optionalisActive()predicate so tabs whose active condition doesn't reduce to "current path starts with x" can compute their own state.Calendar (ActivitiesCalendarPage)
0823b0f). Small filter chip above the month grid that, when on, limits the calendar to events the signed-in user holds a paid ticket for. Hidden when logged out. State is local to the page on purpose — narrowing the calendar shouldn't also narrow the feed. Left-aligned so it doesn't collide with the fixed top-right hamburger.Scan tickets page (ScanTicketsPage)
e05f276). The "Scanned" tab becomes "Tickets" and lists the full event roster (sold tickets), not just the registered subset. Unregistered rows lead the list with a Register button so the host can manually mark someone present without a QR scan — e.g. lost phone, known in person, or alternate proof of identity.useTicketScannergainsregisterManually(ticketId)which reusesPUT /tickets/register/{id}(inheriting the ownership gate + unpaid/already-registered checks), refreshes stats, and mirrors the session-local dedup so a subsequent QR scan on the same ticket reports "Already scanned" instead of round-tripping. Header reads "registered / total · N to go".9753c4a). Search box matches holder name + ticket id via the shareduseFuzzySearch(Fuse.js) composable. Empty query keeps the unregistered-first sort; typing reorders by relevance. Empty-state distinguishes "no tickets sold yet" from "no matches".e3f665c). Wrap eachTabsTrigger's icon+label in aninline-flex items-center gap-1.5span — TabsTrigger wraps its slot in an inline<span class="truncate">, sogap-1.5on the trigger itself never reached the children. (1aeea23was an interim attempt to relocate the counts strip below the camera;e3f665creverts that and lands the actual fix.)Purchase ticket dialog
67a070e). The Lightning rail CTA now reads "Proceed" (or "Proceed buying (N tickets)" for multi-qty) to match the language used on the fiat rails.Bugfix
useActivitiesconsumers (df7ab30).useActivityFiltersallocated a fresh set of refs on every call — soactivities-app/App.vue(Hosting tab) andActivitiesPageeach held independentonlyHosting/temporal/etc state. Tapping Hosting toggled the App.vue ref; the page never saw the change. Filter refs hoisted to module scope so every consumer shares one instance.i18n
common.nav.menu,activities.filters.filters,activities.filters.clearAllacross en/es/fr +types.ts.activities.nav.feedto "Home" (en) / "Accueil" (fr); es already "Inicio".Test plan
gap-4between them./activities/calendar.The "Scanned" tab becomes "Tickets" and now lists the full event roster (sold tickets), not just the registered subset. Unregistered rows lead the list with a Register button so the host can manually mark someone present without a QR scan — e.g. lost phone, known in person, or alternate proof of identity. useTicketScanner gains registerManually(ticketId), which calls the same PUT /tickets/register/{id} the scanner uses (so it inherits the event-ownership gate and the unpaid/already-registered backend checks), then refreshes stats. It skips the scanner pause + full- screen banner since the operator initiated the action from the list, and mirrors the session-local dedup so a subsequent QR scan on the same ticket reports "Already scanned" instead of a duplicate register round-trip. The header now reads "registered / total · N to go" so the host sees roster progress at a glance; failures from the manual register surface as a sonner toast and the row reverts.The lightning rail's CTA in PurchaseTicketDialog now reads "Proceed" (or "Proceed (N tickets)" for multi-quantity) instead of "Get invoice". Matches the language used on the fiat rails ("Continue to Stripe checkout" etc.) and reads as a generic forward action regardless of which payment path the user picks.67a070e9b3to08f1743557d7105f9570to136a4c92fb136a4c92fbtoc88df44545c88df44545to34ecbd570a34ecbd570ato4f7a5dcd88Replace the bare "Events" h1 with the brand-kit logo paired with the standalone's localized name. Deployers get per-standalone logo control via branding/<dep>/icons/events/logo.{svg,png}; the component itself stays brand-agnostic. Brand-kit plumbing: - `resolveAppLogo(app?)` in vite-branding.ts mirrors the resolution chain pwa-assets.config.ts already uses for PWA icons (per-standalone svg → png → global svg → png). - `brandAppLogoAliasEntry(app)` returns a vite alias array entry. A regex matches `@brand-app-logo` with or without a `?url` query so the file resolves cleanly under either form. - vite.events.config.ts switches its resolve.alias to the array form so the per-standalone regex doesn't clash with the bare `@brand` string alias. Component side: a single `import brandAppLogoUrl from '@brand-app-logo?url'` gives EventsPage the best-resolved logo without any fallback chain in the component. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>