V1 - Personal Account and Budgeting Done

Personal Account and Budgeting
This commit is contained in:
2026-08-16 20:13:21 +05:30
commit 17c0526ed6
247 changed files with 19002 additions and 0 deletions

122
kifi-app/lib/main.dart Normal file
View File

@@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:local_auth/local_auth.dart';
import 'core/theme/app_theme.dart';
import 'core/theme/theme_provider.dart';
import 'features/auth/presentation/auth_screen.dart';
import 'features/dashboard/presentation/dashboard_screen.dart';
import 'features/onboarding/presentation/onboarding_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'core/network/dio_client.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
const ProviderScope(
child: KifiApp(),
),
);
}
class KifiApp extends ConsumerStatefulWidget {
const KifiApp({super.key});
@override
ConsumerState<KifiApp> createState() => _KifiAppState();
}
class _KifiAppState extends ConsumerState<KifiApp> {
bool _isLoading = true;
bool _isAuthenticated = false;
bool _hasSeenOnboarding = false;
final LocalAuthentication _localAuth = LocalAuthentication();
String? _startupError;
@override
void initState() {
super.initState();
_checkAuthStatus();
}
Future<bool> _authenticateWithBiometrics() async {
try {
final canCheckBiometrics = await _localAuth.canCheckBiometrics;
final isDeviceSupported = await _localAuth.isDeviceSupported();
if (!canCheckBiometrics && !isDeviceSupported) {
return true; // Pass if device doesn't support biometrics to avoid locking users out
}
return await _localAuth.authenticate(
localizedReason: 'Please authenticate to access Kifi',
biometricOnly: true,
persistAcrossBackgrounding: true,
);
} catch (e) {
return false; // Fail safe
}
}
Future<void> _checkAuthStatus() async {
try {
const storage = FlutterSecureStorage();
final token = await storage.read(key: 'jwt_token');
final prefs = await SharedPreferences.getInstance();
final hasSeenOnboarding = prefs.getBool('has_seen_onboarding') ?? false;
if (token != null && token.isNotEmpty) {
// Prompt for biometrics if returning user
final authSuccess = await _authenticateWithBiometrics();
if (!authSuccess) {
setState(() {
_isAuthenticated = false;
_hasSeenOnboarding = hasSeenOnboarding;
_isLoading = false;
});
return; // User failed biometrics, leave them on login screen
}
setState(() {
_isAuthenticated = true;
_hasSeenOnboarding = hasSeenOnboarding;
_isLoading = false;
});
} else {
setState(() {
_isAuthenticated = false;
_hasSeenOnboarding = hasSeenOnboarding;
_isLoading = false;
});
}
} catch (e, stacktrace) {
setState(() {
_startupError = e.toString();
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
final themeMode = ref.watch(themeProvider);
return MaterialApp(
navigatorKey: navigatorKey,
title: 'Kifi',
debugShowCheckedModeBanner: false,
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeMode,
home: _startupError != null
? Scaffold(body: Center(child: Padding(padding: const EdgeInsets.all(20), child: Text("Startup Error: $_startupError", style: const TextStyle(color: Colors.red)))))
: _isLoading
? const Scaffold(body: Center(child: CircularProgressIndicator()))
: (!_hasSeenOnboarding
? const OnboardingScreen()
: (_isAuthenticated ? const DashboardScreen() : const AuthScreen())),
);
}
}