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).
72 lines
2.5 KiB
Dart
72 lines
2.5 KiB
Dart
// lib/core/auth/auth_guard.dart
|
|
import 'package:flutter/material.dart';
|
|
import '../../screens/login_screen.dart';
|
|
|
|
class AuthGuard {
|
|
static bool _isGuest = false;
|
|
|
|
static bool get isGuest => _isGuest;
|
|
static bool get isLoggedIn => !_isGuest;
|
|
|
|
static void setGuest(bool value) => _isGuest = value;
|
|
|
|
/// Call before any action that requires login.
|
|
/// Returns true if logged in (proceed). Returns false if guest (shows prompt).
|
|
static bool requireLogin(BuildContext context,
|
|
{String reason = 'This feature requires an account.'}) {
|
|
if (!_isGuest) return true;
|
|
_showLoginPrompt(context, reason);
|
|
return false;
|
|
}
|
|
|
|
static void _showLoginPrompt(BuildContext context, String reason) {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
),
|
|
builder: (ctx) => Padding(
|
|
padding: const EdgeInsets.all(24),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Icon(Icons.lock_outline, size: 48, color: Color(0xFF0B63D6)),
|
|
const SizedBox(height: 16),
|
|
Text(reason,
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(
|
|
fontSize: 16, fontWeight: FontWeight.w600)),
|
|
const SizedBox(height: 8),
|
|
const Text('Sign in or create an account to continue.',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(color: Colors.grey, fontSize: 14)),
|
|
const SizedBox(height: 24),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
height: 48,
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFF0B63D6),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12)),
|
|
),
|
|
onPressed: () {
|
|
Navigator.of(ctx).pop();
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
MaterialPageRoute(builder: (_) => const LoginScreen()),
|
|
(route) => false,
|
|
);
|
|
},
|
|
child: const Text('Sign In',
|
|
style: TextStyle(
|
|
color: Colors.white, fontWeight: FontWeight.w700)),
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|