feat: add guest mode — browse events without login
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).
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../features/auth/services/auth_service.dart';
|
||||
import '../core/auth/auth_guard.dart';
|
||||
import 'home_desktop_screen.dart';
|
||||
import '../core/app_decoration.dart';
|
||||
|
||||
@@ -241,7 +242,17 @@ class _DesktopLoginScreenState extends State<DesktopLoginScreen> with SingleTick
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(onPressed: _openRegister, child: const Text("Don't have an account? Register")),
|
||||
TextButton(onPressed: () {}, child: const Text('Contact support'))
|
||||
TextButton(onPressed: () {}, child: const Text('Contact support')),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
AuthGuard.setGuest(true);
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (_) => const HomeDesktopScreen(skipSidebarEntranceAnimation: true)),
|
||||
(route) => false,
|
||||
);
|
||||
},
|
||||
child: const Text('Continue as Guest'),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../core/auth/auth_guard.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
import '../features/events/models/event_models.dart';
|
||||
@@ -448,7 +449,11 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
|
||||
final active = _selectedIndex == index;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => setState(() => _selectedIndex = index),
|
||||
onTap: () {
|
||||
if (index == 2 && !AuthGuard.requireLogin(context, reason: 'Sign in to contribute events and earn rewards.')) return;
|
||||
if (index == 3 && !AuthGuard.requireLogin(context, reason: 'Sign in to view your profile.')) return;
|
||||
setState(() => _selectedIndex = index);
|
||||
},
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
import '../features/auth/services/auth_service.dart';
|
||||
import '../core/auth/auth_guard.dart';
|
||||
import 'home_screen.dart';
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
@@ -509,6 +510,30 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Continue as Guest
|
||||
Center(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
AuthGuard.setGuest(true);
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (_) => const HomeScreen()),
|
||||
(route) => false,
|
||||
);
|
||||
},
|
||||
child: const Text(
|
||||
'Continue as Guest',
|
||||
style: TextStyle(
|
||||
color: _textMuted,
|
||||
fontSize: 13,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: _textMuted,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user