Share sheet now pre-fills:
"I'm a BRONZE Explorer on Eventify Plus! 7 EP earned.
Let's connect on the platform for more.
https://app.eventifyplus.com"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add isLeaderboardLoading flag separate from isLoading
- Add loadLeaderboard() method that fires independently of loadAll TTL
- Remove leaderboard from loadAll() Future.wait (failures in dashboard/shop
no longer silently zero-out leaderboard data)
- setDistrict / setTimePeriod now use isLeaderboardLoading
- contribute_screen calls loadLeaderboard() alongside loadAll() on mount
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wrap Top Events skeleton Row in SingleChildScrollView to fix 225px
RenderFlex overflow when 3x 200px skeletons exceed container width
- Fix gamification service using POST for GET endpoints: dashboard,
leaderboard, and shop/items all use router.get() on the Node.js server
- CORS: add http://localhost:8080 to CORS_ALLOWED_ORIGINS (applied live
to eventify-django container + local settings.py)
Root cause: SearchScreen popped with a plain city label string; the
pincode was available in search results but discarded. home_screen only
saved the display label to prefs and never updated the 'pincode' key,
so every API call always sent {pincode:'all'} regardless of selection.
GPS path had the same issue — lat/lng were obtained but thrown away
after reverse-geocoding; only the label was passed back.
Fix:
- SearchScreen now pops with Map<String,dynamic> {label, pincode,
lat?, lng?} instead of a plain String
- Pincode results return their pincode; GPS returns actual coordinates;
popular city chips look up the first matching pincode from the
Kerala pincodes DB (fallback 'all' if not found)
- home_screen._openLocationSearch() saves pincode + lat/lng to prefs
and updates _pincode/_userLat/_userLng in state
- home_screen._loadUserDataAndEvents() prefers getEventsByLocation
(haversine) when GPS coords are saved, falls back to getEventsByPincode
- EventsService gains getEventsByLocation(lat, lng) which sends
latitude/longitude/radius_km to the existing Django haversine endpoint
and auto-expands radius 10→25→50→100 km until ≥ 6 events found
Changed getEventDetails to requiresAuth: false so guests can fetch
full event details without auth tokens. Added retry logic (2 attempts
with 1s delay) to _loadFullDetails for reliability on slow networks.
This ensures important_information, images, and other detail-only
fields are always fetched in the background after initial display.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New feature: Users can view, submit, and interact with event reviews.
Components added:
- ReviewModel, ReviewStatsModel, ReviewListResponse (models)
- ReviewService with getReviews, submitReview, markHelpful, flagReview
- StarRatingInput (interactive 5-star picker with labels)
- StarDisplay (read-only fractional star display)
- ReviewSummary (average rating + distribution bars)
- ReviewForm (star picker + comment field + submit/update)
- ReviewCard (avatar, timestamp, expandable comment, helpful/flag)
- ReviewSection (main container with pagination and state mgmt)
Integration:
- Added to LearnMoreScreen (both mobile and desktop layouts)
- Review API endpoints point to app.eventifyplus.com Node.js backend
- EventModel updated with averageRating/reviewCount fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: Rewrote EventListAPI to query per-type with DB-level LIMIT
instead of loading all 734 events into memory. Added slim serializer
(32KB vs 154KB). Added DB indexes on event_type_id and pincode.
Frontend: Category chips now filter locally from _allEvents (instant,
no API call). Top Events and category sections always show all types
regardless of selected category. Added TTL caching for event types
(30min) and events (5min). Reduced API timeout from 30s to 10s.
Added memCacheHeight to all CachedNetworkImage widgets. Batched
setState calls from 5 to 2 during startup. Cached _eventDates getter.
Switched baseUrl to em.eventifyplus.com (Django via Nginx+SSL).
Added initialEvent param to LearnMoreScreen for instant detail views.
Resolved relative media URLs for category icons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LearnMoreScreen now accepts an optional initialEvent parameter so it
can render immediately from already-loaded data instead of re-fetching
from the event-details API. This fixes the guest-mode flow where the
unauthenticated API call was failing. Also changed getEventDetails to
requiresAuth: true so logged-in users send their token when the API
path is used.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New file: lib/core/auth/auth_guard.dart
Static AuthGuard class with isGuest flag and requireLogin() helper
that shows a login prompt bottom sheet when guests try protected actions.
login_screen.dart / desktop_login_screen.dart:
Added "Continue as Guest" button below sign-up link.
Sets AuthGuard.isGuest = true, then navigates to HomeScreen.
api_client.dart:
_buildAuthBody() and GET auth check no longer throw when token is missing.
If no token (guest), request proceeds without auth — backend decides.
home_screen.dart:
Bottom nav guards: tapping Contribute (index 2) or Profile (index 3)
as guest shows login prompt instead of navigating.
auth_service.dart:
AuthGuard.setGuest(false) called on successful login AND register
so guest flag is always cleared when user authenticates.
Guest CAN: browse home, calendar, search, filter, view event details.
Guest CANNOT: contribute, view profile, book events (prompts login).