Commit graph

1,004 commits

Author SHA1 Message Date
c035fc2bfc feat(libra): flag the "Other" account hint on the account step
Add a compact inline amber warning (icon + text) next to the
"Select the account…" instruction on both the expense and income
account-selection steps, so users know to fall back to the "Other"
account when unsure.

Splits the income i18n into selectAccount + a new otherAccountHint
key (en/fr/es + types).
2026-06-26 11:07:37 +02:00
9f8f2a233b Merge pull request 'feat(libra): expense/income form UI fixes' (#139) from feat/libra-expense-ui-fixes into dev
Reviewed-on: #139
2026-06-25 20:43:35 +00:00
8a9ea269de feat(libra): trim amount/currency/reference helper text
Remove the "Amount in selected currency" and "Currency for this
income/expense" helper lines on both forms, drop the Reference helper
line, and mark the field as "Reference (optional)" in the label
instead. Also drops the now-unused FormDescription import from the
income form.
2026-06-25 22:39:51 +02:00
87f86647e7 feat(libra): match income Description field to the expense form
Fold the description guidance into the placeholder and drop the
separate FormDescription helper line, so the income Description field
mirrors the expense form's structure.
2026-06-25 22:37:29 +02:00
3ffb3bf983 feat(libra): mention the "Other" account on the income account step
Append the same "Other" account guidance to the income form's Step 1
(libra.income.selectAccount) that the expense form already shows, for
consistency. Updated across en / fr / es locales.
2026-06-25 22:21:55 +02:00
49e7afb0ab feat(libra): put Amount and Currency on the same row
Wrap the Amount and Currency fields in a two-column grid on both the
expense (AddExpense.vue) and income (AddIncome.vue) forms, and add
w-full to the currency SelectTrigger so the dropdown fills its column.
Tightens the vertical layout of the entry dialogs.
2026-06-25 22:16:44 +02:00
807f8200b1 feat(libra): guide expense account choice + description copy
Step 1 (account selection) now tells the user to pick the "Other"
account if they're not sure. The Description field's placeholder is
rewritten to prompt for a detailed description of the purchase /
invoice / bill and what it was used for (event/project/etc), replacing
the redundant helper line.

Client feedback: with no fixed category taxonomy yet, steering unsure
users to the Other account plus a richer free-text description lets us
reconcile/recategorize later.

Refs aiolabs/webapp#137
2026-06-25 22:10:41 +02:00
eb9ae54215 Merge pull request 'feat(events): handle free tickets in the purchase flow' (#131) from feat/free-tickets-client into dev
Reviewed-on: #131
2026-06-20 09:58:39 +00:00
afb57a3918 feat(events): handle free tickets in the purchase flow
Companion to aiolabs/events#31. Free events (price 0 / 100%-off promo)
now come back from POST /tickets/{event_id} as paid=true with the row
ids inline and no payment_request — the backend issued them
already-paid, no invoice to settle.

Previously the composable's `!paymentRequest` guard treated any
invoice-less response as fiat and threw "This event uses fiat
checkout", so free tickets were unbuyable.

- TicketPurchaseInvoice gains `paid` + `ticketIds`; TicketApiService
  maps them.
- purchaseTicketForEvent short-circuits on `invoice.paid`: skip the QR /
  payment-poll and go straight to the ticket-QR success state. The fiat
  error now only fires for an actual fiat (not-paid) response.
- The ticket-QR rendering (refresh owned tickets, one QR per row, toast)
  is extracted into a shared finalizePurchasedTickets() used by both the
  Lightning-poll path and the free path.
- PurchaseTicketDialog: for free events drop the payment-method selector
  and price line, show "Free", and label the CTA "Get ticket".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 09:09:46 +02:00
36791c8121 feat(hub): hide standalones not provisioned on this deploy (aiolabs/webapp#129)
The hub rendered all 8 standalones statically and greyed out any whose
VITE_HUB_<APP>_URL was unset — so an events-only deploy showed 7 dead
"coming soon" tiles. The greyed path was overloaded: hubLink() returned
null for both "not deployed" and "logged out", which the template then
couldn't tell apart.

Replace that with a registry → resolver → view-model pipeline:

- availabilityOf(m) resolves an explicit state from deploy config + auth:
  available | auth-locked | inactive | unavailable.
- A `tiles` computed maps the catalog to view-models and drops
  'unavailable' (not provisioned) entirely — no more ghost tiles.
- 'auth-locked' keeps today's greyed + login-prompt behavior for
  deployed-but-logged-out apps (wallet, chat, tasks, libra).
- 'inactive' (active:false) is wired as a greyed, inert state — an unused
  seam for a future install/disable model; no app sets it yet.

The view treats the catalog as an opaque list, so the source can later
move from this in-code array to a runtime feed (LNbits /hub/apps or a
NIP-78 event) without touching the render path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 08:50:07 +02:00
2cc8e34b9d feat(layout): re-enable "Back to hub" with a sticky sheet footer
Reverses the events-only hide (c037d45) now that the link has a real
home. Three parts:

- Add a @brand-hub-logo alias (brandHubLogoAliasEntry) resolving to the
  brand's primary/global logo — the HUB's logo, never the per-standalone
  @brand-app-logo. Wired into all 9 app vite configs since the shared
  ProfileSheetContent renders it.
- Restructure the profile sheet into a fixed-height flex column: a
  flex-1 min-h-0 overflow-y-auto scroll region over a shrink-0 footer,
  so "Back to hub" + the log-in/out bar stay pinned to the bottom while
  the identity/preferences area scrolls.
- Move the edit-profile Dialog out of the flex root (it portals to body,
  so it's not part of the sheet flow).

Logo bumped to w-8 h-8, centered, with tightened footer padding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 00:26:52 +02:00
8419ca4660 fix(events): collapse own-event draft + relay copy into one card
Coordinate-keying the events store (kind:pubkey:d-tag) regressed the
own-events merge: a creator's own event showed up twice in the feed.

`loadOwnEvents` surfaces the caller's own LNbits events via REST
(`ticketedEventToEvent`) so drafts appear before their NIP-52 event is
on a relay. That adapter stamps an empty `organizer.pubkey`, `isMine`,
and no ticket info. The relay-published copy lands under the real
publisher pubkey (`resolve_for_wallet` — NOT the user's Nostr login
key) with full ticket counts. Pre-coordinate-keying both collapsed on
the bare d-tag so the relay copy replaced the draft; under
`kind:pubkey:d-tag` the empty-pubkey draft and the real-pubkey copy are
distinct keys, so both render — the empty "..."/no-tickets card next to
the real one. Only the logged-in owner sees it, since only own events
get the REST merge.

upsertEvent now reconciles by d-tag: the published copy supersedes the
provisional draft and inherits its `isMine`, so the creator keeps the
Yours badge + Hosting filter even though the publisher key differs from
their login key. Handles both arrival orderings; a draft with no
published copy yet (pending review) still shows alone; genuinely
distinct authors sharing a d-tag are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 00:46:12 +02:00
a7fd686cdd fix(nix): regenerate pnpmDeps hash for the vitest lockfile change
Adding vitest (#124) updated pnpm-lock.yaml (pulled in @standard-schema/spec
and other vitest deps) but the fixed-output pnpmDeps.hash in mkWebapp was
not regenerated, so the build reused the stale offline store and failed
with ERR_PNPM_NO_OFFLINE_TARBALL during `pnpm install --offline`. Rehash
so the deps FOD is refetched from the current lockfile.

Verified: `nix build .#chat` succeeds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:50:36 +02:00
f3612f82ac fix(events): clarify the scan-tickets "Remaining" stat as "Not scanned"
The scan station's third stat card (sold minus scanned) was labeled
"Remaining", which read like leftover sales capacity. Relabel it "Not
scanned" so the trio reads unambiguously: Scanned + Not scanned = Sold.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:45:49 +00:00
0e98a21db3 style(events): center the header logo on the profile-icon axis
The page header used py-4, putting the logo/banner ~6px below the fixed
top-right profile icon's center. Use pt-2.5 so the header sits centered
on the same horizontal axis as the profile icon (both centers at 30px).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:45:29 +00:00
c037d45255 feat(layout): hide "Back to hub" for the events-only launch
Comment out the profile sheet's "Back to hub" link (and its hubRootUrl)
since only the events app ships first — nothing to go back to yet. The
commented markup swaps the old Home icon for the HUB's brand-kit logo
(noted as a @brand-hub-logo alias to add when re-enabled — the hub logo,
not the per-standalone @brand-app-logo) so it's ready to re-enable when
the hub launches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:45:29 +00:00
bdf015f817 fix(layout): use the generic user icon (not login) for the logged-out menu trigger
The top-right menu trigger showed a LogIn (arrow-into-door) icon when
logged out; use the generic User icon instead — it reads as "your
account / profile" and matches the avatar shown when logged in. Still
opens the same profile/menu sheet (with the login CTA).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:45:29 +00:00
8ade942c32 fix(events): keep event detail's ticket counts live (subscribe even when cached)
useEventDetail.load() early-returned when the event was already in the
store, so arriving from the feed (cached) set up no live subscription.
NIP-52 calendar events are replaceable and the events extension
republishes them when a ticket sells (updating tickets_sold/available),
but with no subscription the detail page never received the update —
counts went stale until a manual reload.

Always open the dTag-scoped subscription (only the one-shot query +
loading state are skipped on a cache hit), and unsubscribe a prior sub
before re-subscribing so reload() can't leak one. The reactive `event`
computed then reflects republished counts without a reload.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:43:38 +00:00
83ea3e609c Merge pull request 'feat(events): calendar popup respects the selected category filter' (#115) from feat/calendar-respect-categories into dev
Reviewed-on: #115
2026-06-18 12:41:17 +00:00
3514d93451 feat(events): show selected categories as deselectable chips in calendar popup
The calendar popup already narrows its day-dots to the active category
filter; surface those categories inside the popup so the user can see —
and loosen — what's narrowing it without closing. Renders only the
selected categories as removable chips; clicking one emits toggle-category
to the parent, which reactively re-widens the dots in place.

- EventCalendarPopup: optional selectedCategories prop (defaults to none
  for callers like My Tickets) + toggle-category emit; chip row between
  the header and the month grid.
- EventsPage: wire selectedCategories + toggleCategory through.
- i18n: events.filters.filteringBy + removeCategory (en/fr/es + schema).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:31:39 +02:00
2febf0926d docs(nostr-patterns): point monotonic created_at at the shared helper
The "strictly-monotonic created_at per coord" section named useRSVP.ts as
canonical, but that file no longer exists. monotonicCreatedAt() in
src/lib/nostr/timestamp.ts is now the single implementation — make the
doc reference it and show both the per-coord-Map and single-field
tracking shapes. Keeps doc and code aligned per the docs discipline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:03:58 +00:00
c6f626df08 fix(events): publish bookmarks with monotonic created_at (#122)
Relays only push a replaceable-event update to OPEN subscriptions when
its created_at is strictly newer than the held version. created_at is
second-resolution, so useBookmarks' `Math.floor(Date.now()/1000)` lets
two rapid toggles collide in the same second — the second is treated as
not-newer and never reaches live subscribers (only a reload shows it).
This is the same root cause found while debugging the live ticket count.

- Add `monotonicCreatedAt(lastCreatedAt, now?)` = max(now, last+1), a
  reusable helper for any replaceable-event publisher.
- Use it in `toggleBookmark`; track `lastCreatedAt` as a typed field on
  BookmarkState (drops the `(state as any)` casts).

Unit tests cover no-prior, same-second bump, wall-clock tracking,
future-dated prior, and a strictly-increasing same-second burst.

The aiolabs/events extension's nostr_publisher uses int(time.time()) the
same way — flagged in #122 for a follow-up on the backend.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:03:58 +00:00
4b3b905225 fix(events): key the events store by addressable coordinate (#121)
NIP-52 calendar events (kinds 31922/31923) are addressable: their d-tag
is author-scoped, so the replacement key is kind:pubkey:d-tag, not the
bare d-tag. The store keyed `eventsMap` by `event.id` (d-tag) and
replaced on newer `created_at` ignoring pubkey, so a different author
republishing the same d-tag could overwrite a legit event in the store
(cross-author hijack). NDK (`event.coordinate()`) and welshman
(`eventsByAddress`) both key addressable events by the full coordinate.

- Key `eventsMap` by `eventCoordinate()` = `${kind}:${pubkey}:${dtag}`;
  same-coordinate-newer-wins replacement, different authors stored apart.
- Keep the d-tag as the route identifier: `getEventById(dtag)` scans and
  returns the newest match (single-publisher in practice). Add
  `getByCoordinate()` for precise, author-known lookups.
- `removeEvent(dtag)` deletes every coordinate sharing that d-tag.

Client-side only — the store is rebuilt from relays each session, so no
demo-DB surgery. Covered by vitest unit tests including the cross-author
no-overwrite case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:28:18 +02:00
327092c022 chore(test): add vitest runner + smoke test
No test runner existed in the repo. Add vitest (node env, *.spec.ts
discovery) with a minimal config mirroring only the `@`→src alias, plus
`test`/`test:watch` scripts and a smoke test as a known-good baseline.

Precursor for the nostr-patterns review fixes (events store coordinate
keying #121, monotonic created_at #122), which ship with unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:25:34 +02:00
db4c9b8bf3 feat(events): calendar popup respects the selected category filter
The date-picker popup showed dots for all events regardless of the
active category filter. Feed it a category-filtered set so its per-day
dots reflect what the user is browsing (temporal/day filters still don't
apply — the calendar is for picking any date). No categories selected
behaves as before (all events).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 19:06:52 +02:00
628f85a074 Merge pull request 'style(events): frosted-glass calendar popup that shows the feed through it' (#113) from feat/calendar-popup-frosted-glass into dev
Reviewed-on: #113
2026-06-17 10:42:59 +00:00
a9d39b341e style(events): frosted-glass calendar popup that shows the feed through it
Rebuild the calendar popup on the reka-ui dialog primitives instead of
the shared DialogContent, so it can use a light, blurred overlay
(bg-background/20 + backdrop-blur-md) instead of the usual opaque dark
dim. The panel itself is translucent + blurred (bg-background/70 +
backdrop-blur-xl). Result: the feed stays visible, softly blurred,
behind the frosted glass. Scoped to this popup — other dialogs keep
their solid dark overlay.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 12:41:30 +02:00
8f85a5819b Merge pull request 'fix(events): decrement the live like count on un-like' (#112) from fix/events-like-count-unlike into dev
Reviewed-on: #112
2026-06-17 10:05:07 +00:00
35c62d6ff1 fix(events): decrement the live like count on un-like
The like count only watched bookmark lists by #a, so when someone removed
an event their new (replaceable) list no longer matched the filter and
never arrived — the count stayed stale until reload. Also watch known
likers by `authors` and track each author's current liked-coords, diffing
prev vs next on every update so a dropped coord decrements live. Verified
end-to-end against a relay: a like incremented the count and the same
key's updated list (coord dropped) decremented it with no reload.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:27:16 +02:00
568e6267d8 Merge pull request 'fix(wallet): stop double-deducting balance on outgoing payments' (#109) from fix/wallet-double-deduct-balance into dev
Reviewed-on: #109
2026-06-17 08:38:05 +00:00
fddc26387e fix(wallet): stop double-deducting balance on outgoing payments
The wallet WebSocket handler assumed LNbits sends the PRE-payment balance
for outgoing payments and subtracted the amount again. LNbits actually
re-fetches the wallet AFTER the payment settles before emitting the
notification (core payments.py `_send_payment_notification_in_background`
→ "fetch balance again" → notifications.py `send_ws_payment_notification`
→ `wallet.balance`), so `wallet_balance` is already POST-payment for both
directions. The extra subtraction double-deducted: 100 sats, send 10 →
balance showed 80, then a refresh (which reads the authoritative
/api/v1/wallet balance) corrected it to 90.

Use `wallet_balance` as-is for all messages, matching the polling
fallback which already trusts the API balance directly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:37:45 +00:00
e17b4e05ad Merge pull request 'feat(events): real-time favoriting + live like count + post-purchase refresh' (#111) from feat/events-realtime into dev
Reviewed-on: #111
2026-06-17 08:36:46 +00:00
b6d1626951 feat(events): show a live like count on the favorite heart
Display how many people have favorited (liked) an event next to its
heart, updating in real time. A like == the event appearing in someone's
NIP-51 bookmark list (kind 10003) — the same action the heart performs.

New useEventLikes composable keeps ONE batched subscription over every
mounted heart's event coordinate (filtered by #a). It stays open after
EOSE, so a like published by anyone is pushed live and the count ticks
up for everyone — verified end-to-end against a relay (a like from a
fresh key bumped the shown count 2→3 with no reload). The heart also
pops on a live increment (gated past the initial historical-load
window), and the user's own like/un-like reflects instantly via the
optimistic heart state.

Caveat: an un-like by another user only reflects on next load — a
replaceable list that no longer contains the coord stops matching the #a
filter, so the removal isn't pushed. Counts are correct on fresh load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:36:27 +00:00
3d37b7393d fix(events): refresh owned tickets after purchase (no reload needed)
After a successful ticket purchase, the feed/calendar "My tickets" filter
and EventCard owned badges didn't update until a full page reload — the
shared useOwnedTickets singleton was never refreshed. Its own docs note a
successful purchase should call refresh(); wire that in at the payment-
confirmed point in useTicketPurchase so every surface reflects the new
ticket immediately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:36:27 +00:00
4f4452057a feat(events): make favoriting instant (optimistic) + pop animation
The heart took ~1s to fill because toggleBookmark awaited the remote
LNbits signer + relay publish before updating state. Flip local state
optimistically so the heart responds on tap, then sign/publish in the
background and roll back (with an error toast) if it fails. Add a brief
scale pop on the heart when a favorite is added for tactile feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:36:27 +00:00
9810b11cc5 Merge pull request 'feat(events): calendar date-picker popup, remove calendar page, My Tickets filtering' (#110) from feat/events-calendar-popup into dev
Reviewed-on: #110
2026-06-17 08:36:13 +00:00
9d98f3fdf2 fix(events): close calendar popup on route leave
Defensive guard so the date-picker popup can never linger across
navigation (reported: it appeared open on the feed after returning from
an event detail page). Force calendarOpen=false in onBeforeRouteLeave on
both the feed and My Tickets, the two popup hosts. Modals shouldn't
survive a route change regardless of how the close/navigation interleave.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
76af245192 feat(events): add calendar date visual to My Tickets
Replaces the My-tickets filter that lived on the removed calendar page.
A calendar button opens the date-picker popup with per-day dots over the
user's own events; picking a day filters the ticket list to it (a
removable date chip overrides the upcoming/past toggle while active).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
e54938ef06 refactor(events): remove the standalone calendar page
The calendar is now a date-picker popup on the feed (and, next, a visual
on My Tickets), so the dedicated /events/calendar page and route are no
longer needed. Delete EventsCalendarPage.vue, drop its route, and update
the stale openCreate comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
5753e34499 feat(events): filter the feed by day via the calendar popup
The calendar button now opens the date-picker popup instead of
navigating to a separate page. Picking a day filters the feed to that
day (button highlights while active) and shows a removable date chip
whose ✕ clears ONLY the date selection — distinct from category
clearing, which keeps its own clear in the filter dropdown. Dots in the
popup come from the full (unfiltered) event set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
b665e3de07 feat(events): re-add specific-day filter (calendar popup picks it)
Bring back selectedDate filtering, now driven by the calendar popup
instead of the removed week-strip: when a day is picked it takes
priority over the temporal pills and bypasses the past/upcoming split.
Add a dedicated clearSelectedDate() so the date selection can be cleared
independently of categories (a preset pill also clears it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
f7642db611 feat(events): add reusable calendar date-picker popup
Add a pickerMode to EventCalendarView (month grid only, emits selectDate
on every day tap, no selected-day events panel) and a new
EventCalendarPopup dialog wrapping it. Picking a day emits the date and
closes. Groundwork for replacing the standalone calendar page with an
on-feed date-picker popup and a My-Tickets event-date visual.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
8c9a8ab945 feat(events): put calendar My-tickets filter next to the Back button
The My-tickets filter chip sat on its own row below the Back link,
wasting vertical space. Move it onto the Back-button row (still
left-aligned to clear the fixed top-right hamburger), reclaiming a row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
3d1b888307 feat(events): compact the calendar month grid
The aspect-square day cells made the month grid ~350px tall on mobile,
pushing the selected-day event list well below the fold. Switch cells to
a fixed h-12 (still a comfortable 48px tap target) and tighten the
section spacing (space-y-4 → space-y-2), so the grid + day's events fit
with less scrolling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
c53bc525ef fix(events): move My Tickets upcoming/past toggle off the hamburger
The toggle sat in the header's top-right corner, where it collided with
the fixed top-right hamburger menu (the Past button rendered behind it).
Move it to its own left-aligned row above the tabs — same approach the
calendar page uses to clear the hamburger.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
1433a2039b feat(events): add upcoming/past toggle to My Tickets
My Tickets listed every ticket with no way to separate events that
already happened. Add an Upcoming/Past segmented toggle (defaults to
upcoming) that filters the grouped tickets by their event's date, with
the tab counts (All/Paid/Pending/Registered) derived from the visible
set so badges match what's shown. Events not yet resolved from relays
stay visible under Upcoming until their date is known.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
084bfc52eb refactor(events): remove dead specific-date filter logic
With the DatePickerStrip gone, selectedDate/selectDate in useEventFilters
were unreachable — nothing set a specific date anymore (the calendar page
only navigates to event detail). Delete the orphaned DatePickerStrip
component and strip the now-dead date-filter branch, state, and actions.
The feed filters purely by temporal pills + past/upcoming + categories.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
cdc8158e1b feat(events): drop the week-day strip, move calendar next to filters
The feed had two redundant day controls — the DatePickerStrip week strip
and the temporal preset pills — on top of the calendar page. Remove the
week strip (the calendar already covers picking a specific date) and move
the calendar shortcut to the end of the temporal-filter row, next to the
pills. Frees a row and keeps coarse windows (Today/This Week/…) inline
with one-tap access to the full calendar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
52e9d11ea9 feat(events): add Back button to the calendar page
The calendar page had no way back to the feed except the browser/back
gesture. Add a top-bar ghost Back link (ArrowLeft + "Back" → events feed)
mirroring EventDetailPage's pattern for navigation consistency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00
32a7389d0b feat(events): default calendar selection to today
The month-grid calendar opened with no day selected, so the events panel
below was empty until the user clicked a day. Initialise the selection to
today (currentMonth already starts on the current month) so it opens
showing today's events.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:35:28 +00:00