Tasks reuse NIP-52 kind 31922 but tag events with event-type:task.
Filter these out in parseNostrEventToActivity so household chores
don't show up as community activities.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The GET /tickets/{event_id}/user/{user_id} endpoint was a custom
addition not present in the upstream LNbits events extension. Use
the canonical POST /tickets/{event_id} with user_id in the body.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The activities module was only registered in the standalone Sortir app,
not the main app. When events module was removed, its registration was
deleted but activities was never added in its place.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Absorb the disabled events module into the active activities module,
eliminating duplicated LNbits events extension API surface and legacy
imports. Activities now owns all ticketing UI (EventsPage, MyTicketsPage
with QR codes, PurchaseTicketDialog, CreateEventDialog) alongside its
existing Nostr NIP-52 calendar event discovery.
- Internalize payInvoiceWithWallet in PaymentService (core LNbits endpoint)
- Enhance TicketApiService with createEvent and getCurrencies methods
- Add TICKET_API DI token for canonical ticket service access
- Port composables (useTicketPurchase, useUserTickets, useEvents) with DI
- Port components (PurchaseTicketDialog, CreateEventDialog)
- Replace MyTicketsPage placeholder with full QR-code ticket display
- Add /events route to activities module
- Delete src/modules/events/, src/lib/api/events.ts, src/lib/types/event.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Castle API returns positive = user owes castle, negative = castle owes
user. The display was inverted, showing "you owe" after submitting an
expense when it should show "owed to you".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restores LoginDemo.vue from the demo-login branch. When
VITE_DEMO_MODE=true, the main app uses LoginDemo.vue which allows
instant demo account creation with auto-generated credentials.
Production deployments are unaffected (flag defaults to false).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New standalone app at castle.html with its own Vite config, app shell,
and bottom nav (Record, Transactions, Balance, Wallet, Settings). Reuses
existing expenses and wallet modules with base module for a focused
accounting experience.
Features:
- Expense submission via existing AddExpense dialog
- Income submission placeholder (feature-flagged, pending backend)
- Balance page with pending expense tracking
- Expense drafts with receipt photo upload and BTC price snapshots
- Cross-subdomain auth token relay via ?token= URL parameter
- i18n support (en/fr/es)
- PWA with offline support
Also adds token relay to activities-app for consistent cross-app auth.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All hardcoded English strings now use t() with i18n keys: bottom nav
tabs, search placeholder, empty states, favorites page, settings page.
Added useDateLocale composable that maps the current i18n language to
the corresponding date-fns locale (fr/es/enUS). All date formatting
across ActivityCard, ActivityDetailPage, DatePickerStrip, calendar
view, and search overlay now passes the locale to date-fns format().
Month names, day names, and date labels change with language switch.
Added nav, search, favorites, and settings i18n sections to all three
locales (EN/FR/ES).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New ActivitySearchOverlay component: compact dropdown anchored to the
search input showing thumbnail, title, date, and location for each
result. Limited to 8 results, scrollable. Stays visible above the
keyboard on mobile. Tap a result to navigate, tap outside or clear
to dismiss. Uses the same Fuse.js fuzzy search under the hood.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents the map from resetting zoom/pan when new activities stream
in from relays. Users can now freely zoom and pan without being
snapped back to the world view.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces Calendar with CalendarSearch for better empty-state semantics.
Uses opacity-30 on the element instead of text color opacity to avoid
visible stroke overlaps on SVG icons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full activities i18n for Spanish: categories, detail page, tickets,
filters. Uses Latin American terminology (boleto instead of entrada,
charla instead of ponencia). Added Spanish to the standalone app
Settings language picker alongside French and English.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
VITE_DEFAULT_LOCALE (fr/en/es) sets the initial language for the
standalone app when no user preference is saved. VITE_DEFAULT_MAP_CENTER
(lat,lng) configures the default map center point. Both fall back to
sensible defaults (fr and France center) when not set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents RangeError from format() on activities with unparseable
start timestamps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Map view: Leaflet + OpenStreetMap with markers from NIP-52 geohash
tags. Click popup navigates to activity detail. Auto-fits bounds to
show all markers. Geohash decoding via ngeohash added to Activity
model conversion.
Calendar view: Month grid with activity dots (up to 3 per day).
Click a day to see activities listed below the calendar. Month
navigation with prev/next buttons.
New dependencies: leaflet, @types/leaflet, ngeohash, @types/ngeohash.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both BookmarkButton and RSVPButton now show a toast notification
with a "Log in" action button when tapped by unauthenticated users.
RSVP buttons are now always visible (not hidden behind v-if).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses the existing FuzzySearch component and useFuzzySearch composable
(same pattern as market module). Searches across title (50%), summary
(20%), description (15%), location (10%), and tags (5%) with threshold
0.35. Fuzzy search feeds into the display list after temporal/category/
date filters are applied. Removed manual string search from filter
composable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Heart is now next to the title text in the caption area where
it's always visible regardless of the background image.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use CSS grid (grid-cols-7) instead of flex with min-width so all days
always fit. Single-letter day names (M T W T F S S) instead of
three-letter abbreviations to save horizontal space.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- parseTimestamp now handles unix seconds, milliseconds, and ISO strings;
returns NaN for unparseable values instead of 0 (which caused Jan 1 1970)
- Events with unparseable start timestamps are rejected by the parser
- ActivityCard safely handles invalid dates without crashing
- DatePickerStrip day selection now filters activities to that date
- Selecting a day clears temporal pills; selecting a pill clears the day
- Feed shows all activities sorted by date (no more upcoming/past split)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use horizontal scroll with hidden scrollbar instead of flex-wrap.
Pills stay on one line and scroll on narrow screens.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refresh is now a ghost icon-only button next to the title instead of
a full-width outlined button. Create button text hidden on mobile
(icon-only). Saves vertical space on small screens.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CreateActivityDialog with vee-validate + Zod form: title, summary,
description, start/end date+time, location, categories (multi-select),
and image URL. Signs NIP-52 kind 31923 events with user's signing key
via nostr-tools finalizeEvent and publishes through RelayHub. Fixed
ActivitiesNostrService.publishCalendarEvent to properly sign events
before publishing. CategorySelector and LocationPicker helper components.
Create button visible only to authenticated users.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Second Vite entry point for deploying the activities module as an
independent PWA at sortir.ariege.io. Includes its own App.vue with
bottom navigation bar (p'a semana style: Feed, Calendar, Map, Favorites,
Settings), stripped-down app config (base + activities only), French
PWA manifest, and SPA fallback plugin for dev server. New routes for
calendar, map, and favorites views (placeholder). Settings page with
theme toggle, language switcher (FR/EN), and auth.
Build: npm run build:activities -> dist-activities/
Dev: npm run dev:activities -> localhost:5173
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Composables (useActivities, useActivityFilters, useActivityDetail) for
subscribing to NIP-52 calendar events, filtering by temporal range and
category, and loading single activity details. Components: ActivityCard
with image/placeholder, date, location, category badge; ActivityList
with responsive grid, loading skeletons, and empty state; TemporalFilterBar
(today/tomorrow/week/month pills); CategoryFilterBar (25 categories);
DatePickerStrip (horizontal week calendar). Full ActivitiesPage with
search, filters, upcoming/past tabs. ActivityDetailPage with hero image,
organizer info, and description. Activities nav link added (no auth required).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nostr-native communal events module using NIP-52 Calendar Events.
Includes types (activity, ticket, category, NIP-52 parsers/builders),
services (ActivitiesNostrService, TicketApiService, PaymentProvider
abstraction with LNbits implementation), Pinia store with deduplication,
module plugin with DI registration, i18n (EN/FR/ES), and placeholder views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents the dialog from shifting up/down as account search results
change the content height, which caused it to move behind the
virtual keyboard on mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Users can now type to search accounts instead of manually navigating
the hierarchy. Uses existing FuzzySearch component with Fuse.js.
Search matches against account names and descriptions. The hierarchical
browser remains available when the search input is empty.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The simplified Home.vue lost the useQuickActions system, which meant
module quick actions (expenses, submit link) were no longer accessible.
Restore the expandable FAB that shows all registered module actions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create links module (link aggregator from atio branch) with SubmissionService,
LinkPreviewService, voting, ranking, and full submission UI
- Create tasks module with TaskService (own relay subscription for kinds
31922/31925), extracted from nostr-feed's ScheduledEventService
- Promote ProfileService and ReactionService to base module as shared services
- Replace Home.vue feed with SubmissionList from links module
- Disable nostr-feed module (kept in codebase for future re-enablement)
- Add links and tasks to app.config, app.ts, navigation, and DI container
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The processIncomingMessage function was also being called for outgoing
messages from loadRecentMessagesForPeer, but was using the wrong pubkey
for decryption. NIP-04 requires YOUR private key + the OTHER party's
public key.
For outgoing messages, event.pubkey is the user's own pubkey, but it
should use the recipient's pubkey from the p-tag for decryption.
This fix:
- Detects if message is outgoing (event.pubkey === userPubkey)
- For outgoing: gets recipient pubkey from p-tag
- For incoming: uses event.pubkey (sender)
- Sets sent flag correctly based on direction
- Associates message with the correct peer
Fixes "aes/pcks5: wrong padding" console errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Powered by ⚡LNbits" link to both desktop and mobile sidebars
- Links to lnbits.com in new tab
- Includes separator divider above attribution
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Increase dropdown width from w-56 to w-64
- Prevents EverQuest-style coin display from being cut off
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Comment out Settings link in both desktop and mobile sidebars
- Comment out Relay Hub Status in user menu dropdown
- Add TODO comments to review implementing these in the future
- Comment out unused imports to fix TypeScript errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create ChatMessageContent component to detect and render order messages
- Display order details in a clean card format instead of raw JSON
- Show item count, shipping zone with truck icon, and short order ID
- Falls back to plain text for non-order messages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add query parameter support (?tab=orders) to Market Dashboard
- Update CheckoutPage to navigate with tab=orders query param
- Dashboard validates tab param against allowed values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Combine shipping and contact info into single step
- Remove BTC Onchain and Cashu payment options (Lightning only for now)
- Add collapsible section for optional contact info (email, npub, address)
- Keep shipping address visible when required for physical delivery
- Keep message to merchant visible by default
- Add TODO comment for future payment method expansion
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed updateStall from PATCH to PUT (LNbits API requirement)
- Updated to send full stall object instead of partial update
- Merges form values with existing stall data before sending
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed Home.vue sticky header from z-40 to z-30
- Changed SubmissionDetail.vue sticky header from z-40 to z-30
- AppTopBar remains at z-40, ensuring it stays above page content
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add new sidebar-based layout components:
- AppLayout.vue: Main layout wrapper with sidebar + topbar
- AppSidebar.vue: Desktop sidebar with navigation, theme, language
- AppTopBar.vue: Top bar with notifications, cart, profile
- MobileDrawer.vue: Slide-out drawer for mobile navigation
- Add Shadcn Sheet component for mobile drawer
- Update App.vue to use new AppLayout (except login page)
- Rename old Navbar.vue to Navbar.old.vue for reference
Layout structure:
- Desktop: Fixed 288px sidebar + offset content area
- Mobile: Hidden sidebar with drawer triggered from top bar
- Cart only shown when market module is enabled
- Combined notifications (chat unread count)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>