feat: Implement the home screen with new UI components and assets, and refine authentication screens and routing.

This commit is contained in:
pradeepkumar
2026-02-24 03:19:55 +05:30
parent 4f8ad7fe49
commit 0bc8852c17
31 changed files with 1540 additions and 24 deletions

View File

@@ -1,11 +1,12 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:real_estate_mobile/core/network/api_exceptions.dart';
import 'package:real_estate_mobile/core/storage/secure_storage.dart';
import 'package:real_estate_mobile/features/auth/data/auth_repository.dart';
import 'package:real_estate_mobile/features/auth/data/models/register_request.dart';
import 'package:real_estate_mobile/features/auth/data/models/user_model.dart';
// Auth state
enum AuthStatus { initial, loading, success, error }
enum AuthStatus { initial, loading, authenticated, error }
class AuthState {
final AuthStatus status;
@@ -49,7 +50,37 @@ class AuthState {
class AuthNotifier extends StateNotifier<AuthState> {
final AuthRepository _repository;
AuthNotifier(this._repository) : super(const AuthState());
AuthNotifier(this._repository) : super(const AuthState()) {
checkAuthStatus();
}
Future<void> checkAuthStatus() async {
final token = await SecureStorage.getAccessToken();
if (token == null) {
state = state.copyWith(status: AuthStatus.initial);
return;
}
state = state.copyWith(status: AuthStatus.loading);
try {
final user = await _repository.getMe();
state = state.copyWith(
status: AuthStatus.authenticated,
user: user,
);
} catch (_) {
// Token is invalid/expired — clear and show login
await SecureStorage.clearTokens();
state = state.copyWith(status: AuthStatus.initial);
}
}
Future<void> logout() async {
state = state.copyWith(status: AuthStatus.loading);
await _repository.logout();
state = const AuthState();
}
Future<void> login({
required String email,
@@ -76,7 +107,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
}
state = state.copyWith(
status: AuthStatus.success,
status: AuthStatus.authenticated,
user: result['user'] as UserModel,
);
} on ApiException catch (e) {
@@ -124,7 +155,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
);
state = state.copyWith(
status: AuthStatus.success,
status: AuthStatus.authenticated,
user: user,
registeredEmail: email,
);

View File

@@ -16,7 +16,6 @@ class LoginScreen extends ConsumerStatefulWidget {
}
class _LoginScreenState extends ConsumerState<LoginScreen> {
final _nameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
String _selectedRole = 'USER';
@@ -24,7 +23,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
_passwordController.dispose();
super.dispose();
@@ -63,6 +61,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
final authState = ref.watch(authProvider);
final isLoading = authState.status == AuthStatus.loading;
// Router redirect handles navigation on auth state change
return Scaffold(
body: Container(
width: double.infinity,
@@ -149,14 +149,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
const SizedBox(height: 16),
],
// Name field
AuthTextField(
hintText: 'Name',
controller: _nameController,
keyboardType: TextInputType.name,
),
const SizedBox(height: 16),
// Email field
AuthTextField(
hintText: 'Email',

View File

@@ -81,7 +81,7 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
child: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: authState.status == AuthStatus.success
child: authState.status == AuthStatus.authenticated
? _buildSuccessContent(authState)
: _buildFormContent(authState),
),