diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ca28527..60578bf 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,7 +5,7 @@ + android:icon="@mipmap/launcher_icon"> init() async { + _prefs = await SharedPreferences.getInstance(); + username = _prefs?.getString(_keyUsername); + } + + /// Save username to persistent storage + static Future saveSession(String user) async { + username = user; + await _prefs?.setString(_keyUsername, user); + } + + /// Clear session from persistent storage + static Future logout() async { + username = null; + await _prefs?.remove(_keyUsername); + } + + static bool get isLoggedIn => username != null; +} diff --git a/lib/features/account/presentation/pages/account_page.dart b/lib/features/account/presentation/pages/account_page.dart index 1cf5668..e0dff02 100644 --- a/lib/features/account/presentation/pages/account_page.dart +++ b/lib/features/account/presentation/pages/account_page.dart @@ -1,16 +1,180 @@ import 'package:flutter/material.dart'; import 'package:monitoring_jamur/core/theme/app_theme.dart'; +import 'package:monitoring_jamur/core/session/user_session.dart'; +import 'package:monitoring_jamur/features/auth/presentation/pages/login_page.dart'; class AccountPage extends StatelessWidget { const AccountPage({super.key}); @override Widget build(BuildContext context) { - return const Scaffold( - body: Center( - child: Text( - 'Account Content Coming Soon', - style: TextStyle(color: AppTheme.textLight), + return Scaffold( + backgroundColor: AppTheme.backgroundBeige, + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Manajemen Akun', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + const SizedBox(height: 32), + // Main Consolidated Frame + Container( + width: double.infinity, + padding: const EdgeInsets.all(24.0), + decoration: BoxDecoration( + color: AppTheme.surfaceWhite, + borderRadius: BorderRadius.circular(32), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(10), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: Column( + children: [ + // Cool User Icon + _buildCoolUserIcon(), + const SizedBox(height: 24), + // Username Info + Text( + UserSession.username ?? 'Guest', + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + const Text( + 'Account Owner', + style: TextStyle( + fontSize: 14, + color: AppTheme.textLight, + ), + ), + const SizedBox(height: 24), + const Divider(height: 32, thickness: 1.0, color: AppTheme.backgroundBeige), + const SizedBox(height: 8), + // Menu Items + _buildMenuTile( + icon: Icons.settings_rounded, + title: 'Kelola Akun', + onTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Fitur Kelola Akun segera hadir')), + ); + }, + ), + const SizedBox(height: 12), + _buildMenuTile( + icon: Icons.logout_rounded, + title: 'Log out', + isDestructive: true, + onTap: () async { + await UserSession.logout(); + if (context.mounted) { + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => const LoginPage()), + (route) => false, + ); + } + }, + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildCoolUserIcon() { + return Container( + width: 110, + height: 110, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: const LinearGradient( + colors: [AppTheme.primaryGreen, Color(0xFF81C784)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + boxShadow: [ + BoxShadow( + color: AppTheme.primaryGreen.withAlpha(40), + blurRadius: 15, + spreadRadius: 2, + ), + ], + ), + child: Container( + margin: const EdgeInsets.all(4), + decoration: const BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + child: const Center( + child: Icon( + Icons.manage_accounts_rounded, + size: 56, + color: AppTheme.primaryGreen, + ), + ), + ), + ); + } + + Widget _buildMenuTile({ + required IconData icon, + required String title, + required VoidCallback onTap, + bool isDestructive = false, + }) { + final color = isDestructive ? Colors.red.shade700 : AppTheme.primaryGreen; + + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + decoration: BoxDecoration( + color: isDestructive ? Colors.red.withAlpha(10) : AppTheme.backgroundBeige.withAlpha(50), + borderRadius: BorderRadius.circular(16), + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: isDestructive ? Colors.red.withAlpha(20) : AppTheme.primaryGreen.withAlpha(20), + shape: BoxShape.circle, + ), + child: Icon(icon, color: color, size: 22), + ), + const SizedBox(width: 16), + Expanded( + child: Text( + title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: isDestructive ? color : AppTheme.textDark, + ), + ), + ), + Icon(Icons.chevron_right_rounded, color: AppTheme.textLight.withAlpha(100)), + ], ), ), ); diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index fdfa7f7..d01c8c2 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -3,6 +3,7 @@ import '../../data/user_repository.dart'; import 'register_page.dart'; import 'package:monitoring_jamur/core/theme/app_theme.dart'; import 'package:monitoring_jamur/features/home/presentation/pages/main_screen.dart'; +import 'package:monitoring_jamur/core/session/user_session.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @@ -33,10 +34,11 @@ class _LoginPageState extends State { setState(() => _isLoading = false); if (user != null) { + await UserSession.saveSession(_usernameController.text); if (mounted) { Navigator.pushAndRemoveUntil( context, - MaterialPageRoute(builder: (context) => MainScreen()), + MaterialPageRoute(builder: (context) => const MainScreen()), (route) => false, ); } @@ -56,10 +58,10 @@ class _LoginPageState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon( - Icons.nature_outlined, - size: 80, - color: AppTheme.primaryGreen, + Image.asset( + 'lib/assets/mushroom.png', + height: 120, + fit: BoxFit.contain, ), const SizedBox(height: 16), const Text( diff --git a/lib/features/history/presentation/pages/history_page.dart b/lib/features/history/presentation/pages/history_page.dart index 8a94019..a641bc0 100644 --- a/lib/features/history/presentation/pages/history_page.dart +++ b/lib/features/history/presentation/pages/history_page.dart @@ -6,11 +6,62 @@ class HistoryPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Scaffold( - body: Center( - child: Text( - 'History Content Coming Soon', - style: TextStyle(color: AppTheme.textLight), + return Scaffold( + backgroundColor: AppTheme.backgroundBeige, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Histori Monitoring', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + const SizedBox(height: 24), + Expanded( + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: AppTheme.surfaceWhite, + borderRadius: BorderRadius.circular(32), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(5), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.history_rounded, + size: 64, + color: AppTheme.backgroundBeige, + ), + SizedBox(height: 16), + Text( + 'tidak ada data', + style: TextStyle( + fontSize: 16, + color: AppTheme.textLight, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ), + ), + ], + ), ), ), ); diff --git a/lib/features/home/presentation/pages/dashboard_page.dart b/lib/features/home/presentation/pages/dashboard_page.dart index a9c4a6a..44ee598 100644 --- a/lib/features/home/presentation/pages/dashboard_page.dart +++ b/lib/features/home/presentation/pages/dashboard_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:monitoring_jamur/core/theme/app_theme.dart'; +import 'package:monitoring_jamur/features/home/presentation/pages/statistics_page.dart'; import 'dart:math' as math; class DashboardPage extends StatefulWidget { @@ -12,6 +13,12 @@ class DashboardPage extends StatefulWidget { class _DashboardPageState extends State { // Demo humidity value double _humidity = 85.0; + bool _isAutoMode = true; + bool _isPumpManual = false; + bool _isLightManual = false; + + bool get _pumpStatus => _isAutoMode ? (_humidity < 80) : _isPumpManual; + bool get _lightStatus => _isAutoMode ? (_humidity > 90) : _isLightManual; @override Widget build(BuildContext context) { @@ -74,6 +81,16 @@ class _DashboardPageState extends State { ], ), ), + const SizedBox(height: 32), + // Control Mode Selector + _buildModeSelector(), + const SizedBox(height: 24), + // Device Controls + _buildDeviceControls(), + const SizedBox(height: 32), + // Statistics Button + _buildStatisticsButton(context), + const SizedBox(height: 32), ], ), ), @@ -81,6 +98,188 @@ class _DashboardPageState extends State { ); } + Widget _buildModeSelector() { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(5), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () => setState(() => _isAutoMode = true), + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: BoxDecoration( + color: _isAutoMode ? AppTheme.primaryGreen : Colors.transparent, + borderRadius: BorderRadius.circular(16), + ), + alignment: Alignment.center, + child: Text( + 'Otomatis', + style: TextStyle( + fontWeight: FontWeight.bold, + color: _isAutoMode ? Colors.white : AppTheme.textLight, + ), + ), + ), + ), + ), + Expanded( + child: GestureDetector( + onTap: () => setState(() => _isAutoMode = false), + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: BoxDecoration( + color: !_isAutoMode ? AppTheme.primaryGreen : Colors.transparent, + borderRadius: BorderRadius.circular(16), + ), + alignment: Alignment.center, + child: Text( + 'Manual', + style: TextStyle( + fontWeight: FontWeight.bold, + color: !_isAutoMode ? Colors.white : AppTheme.textLight, + ), + ), + ), + ), + ), + ], + ), + ); + } + + Widget _buildDeviceControls() { + return Column( + children: [ + _buildDeviceTile( + title: 'Pompa Air', + isOn: _pumpStatus, + onChanged: _isAutoMode ? null : (val) => setState(() => _isPumpManual = val), + ), + const SizedBox(height: 16), + _buildDeviceTile( + title: 'Lampu Pemanas', + isOn: _lightStatus, + onChanged: _isAutoMode ? null : (val) => setState(() => _isLightManual = val), + ), + ], + ); + } + + Widget _buildDeviceTile({ + required String title, + required bool isOn, + required ValueChanged? onChanged, + }) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + decoration: BoxDecoration( + color: AppTheme.surfaceWhite, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(5), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: isOn ? AppTheme.primaryGreen.withAlpha(30) : Colors.grey.withAlpha(20), + shape: BoxShape.circle, + ), + child: Icon( + title.contains('Pompa') ? Icons.water_drop_rounded : Icons.lightbulb_rounded, + color: isOn ? AppTheme.primaryGreen : Colors.grey, + size: 28, + ), + ), + const SizedBox(width: 20), + Expanded( + child: Text( + title, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + ), + if (onChanged == null) + Text( + isOn ? 'MENYALA' : 'MATI', + style: TextStyle( + fontWeight: FontWeight.w900, + color: isOn ? AppTheme.primaryGreen : AppTheme.textLight, + ), + ) + else + Switch( + value: isOn, + onChanged: onChanged, + activeColor: AppTheme.primaryGreen, + ), + ], + ), + ); + } + + Widget _buildStatisticsButton(BuildContext context) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const StatisticsPage()), + ); + }, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 20), + decoration: BoxDecoration( + color: AppTheme.surfaceWhite, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: AppTheme.primaryGreen.withAlpha(20), + blurRadius: 15, + offset: const Offset(0, 8), + ), + ], + ), + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.bar_chart_rounded, color: AppTheme.primaryGreen, size: 28), + SizedBox(width: 12), + Text( + 'Lihat Statistik', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppTheme.primaryGreen, + ), + ), + ], + ), + ), + ); + } + Widget _buildStatusCard() { return Container( width: double.infinity, diff --git a/lib/features/home/presentation/pages/main_screen.dart b/lib/features/home/presentation/pages/main_screen.dart index beff3ec..b7f0b18 100644 --- a/lib/features/home/presentation/pages/main_screen.dart +++ b/lib/features/home/presentation/pages/main_screen.dart @@ -52,26 +52,52 @@ class _MainScreenState extends State { Widget _buildAnimatedBottomBar() { return Container( - margin: const EdgeInsets.fromLTRB(16, 0, 16, 24), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + margin: const EdgeInsets.fromLTRB(24, 0, 24, 24), + height: 70, decoration: BoxDecoration( color: AppTheme.surfaceWhite, - borderRadius: BorderRadius.circular(30), + borderRadius: BorderRadius.circular(35), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), - blurRadius: 20, - offset: const Offset(0, 10), + blurRadius: 25, + offset: const Offset(0, 12), ), ], ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _buildNavItem(0, Icons.dashboard_outlined, Icons.dashboard, 'Dashboard'), - _buildNavItem(1, Icons.history_outlined, Icons.history, 'History'), - _buildNavItem(2, Icons.person_outline, Icons.person, 'Account'), - ], + child: LayoutBuilder( + builder: (context, constraints) { + double totalWidth = constraints.maxWidth; + double itemWidth = totalWidth / 3; + + return Stack( + children: [ + // Animated Background Bubble + AnimatedPositioned( + duration: const Duration(milliseconds: 600), + curve: Curves.elasticOut, + left: _currentIndex * itemWidth + (itemWidth * 0.15), + top: 12, + child: Container( + width: itemWidth * 0.7, + height: 46, + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withOpacity(0.1), + borderRadius: BorderRadius.circular(23), + ), + ), + ), + // Navigation Items + Row( + children: [ + _buildNavItem(0, Icons.grid_view_outlined, Icons.grid_view_rounded, 'Home'), + _buildNavItem(1, Icons.history_rounded, Icons.history_rounded, 'History'), + _buildNavItem(2, Icons.person_outline_rounded, Icons.person_rounded, 'Account'), + ], + ), + ], + ); + }, ), ); } @@ -79,44 +105,38 @@ class _MainScreenState extends State { Widget _buildNavItem(int index, IconData outlineIcon, IconData filledIcon, String label) { bool isSelected = _currentIndex == index; - return GestureDetector( - onTap: () => _onItemTapped(index), - behavior: HitTestBehavior.opaque, - child: AnimatedContainer( - duration: const Duration(milliseconds: 300), - curve: Curves.easeOutBack, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - decoration: BoxDecoration( - color: isSelected ? AppTheme.primaryGreen.withOpacity(0.12) : Colors.transparent, - borderRadius: BorderRadius.circular(20), - ), - child: Row( + return Expanded( + child: GestureDetector( + onTap: () => _onItemTapped(index), + behavior: HitTestBehavior.opaque, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedScale( - scale: isSelected ? 1.15 : 1.0, + scale: isSelected ? 1.0 : 0.9, duration: const Duration(milliseconds: 300), curve: Curves.easeOutBack, - child: Icon( - isSelected ? filledIcon : outlineIcon, - color: isSelected ? AppTheme.primaryGreen : AppTheme.textLight, - size: 26, + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + child: Icon( + isSelected ? filledIcon : outlineIcon, + color: isSelected ? AppTheme.primaryGreen : AppTheme.textLight.withOpacity(0.6), + size: 26, + ), ), ), - if (isSelected) ...[ - const SizedBox(width: 8), - AnimatedOpacity( - opacity: isSelected ? 1.0 : 0.0, + if (isSelected) + AnimatedContainer( duration: const Duration(milliseconds: 300), child: Text( label, style: const TextStyle( - color: AppTheme.primaryGreen, + fontSize: 10, fontWeight: FontWeight.bold, - fontSize: 14, + color: AppTheme.primaryGreen, ), ), ), - ], ], ), ), diff --git a/lib/features/home/presentation/pages/statistics_page.dart b/lib/features/home/presentation/pages/statistics_page.dart new file mode 100644 index 0000000..067c808 --- /dev/null +++ b/lib/features/home/presentation/pages/statistics_page.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:monitoring_jamur/core/theme/app_theme.dart'; + +class StatisticsPage extends StatelessWidget { + const StatisticsPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppTheme.backgroundBeige, + appBar: AppBar( + title: const Text('Statistik Monitoring'), + backgroundColor: Colors.transparent, + elevation: 0, + foregroundColor: AppTheme.textDark, + centerTitle: true, + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSummaryRow(), + const SizedBox(height: 32), + _buildChartSection('Tren Kelembapan', [85, 82, 88, 84, 86, 85, 87], AppTheme.primaryGreen), + const SizedBox(height: 32), + _buildChartSection('Tren Suhu', [24, 25, 24, 26, 25, 24, 25], Colors.orange), + const SizedBox(height: 40), + _buildAnalysisCard(), + ], + ), + ), + ); + } + + Widget _buildSummaryRow() { + return Row( + children: [ + _buildStatCard('Rata-rata', '85%', Icons.water_drop_rounded, AppTheme.primaryGreen), + const SizedBox(width: 16), + _buildStatCard('Tertinggi', '89%', Icons.trending_up_rounded, Colors.blue), + ], + ); + } + + Widget _buildStatCard(String label, String value, IconData icon, Color color) { + return Expanded( + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppTheme.surfaceWhite, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(5), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(icon, color: color, size: 28), + const SizedBox(height: 12), + Text(value, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), + Text(label, style: const TextStyle(fontSize: 12, color: AppTheme.textLight)), + ], + ), + ), + ); + } + + Widget _buildChartSection(String title, List values, Color color) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: AppTheme.textDark), + ), + const SizedBox(height: 16), + Container( + height: 180, + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppTheme.surfaceWhite, + borderRadius: BorderRadius.circular(24), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: values.map((v) { + double height = (v / 100) * 120; + if (title.contains('Suhu')) height = (v / 40) * 120; // Scale for temperature + return Container( + width: 24, + height: height, + decoration: BoxDecoration( + color: color.withAlpha(50), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: color, width: 2), + ), + ); + }).toList(), + ), + ), + ], + ); + } + + Widget _buildAnalysisCard() { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withAlpha(20), + borderRadius: BorderRadius.circular(24), + border: Border.all(color: AppTheme.primaryGreen.withAlpha(50), width: 2), + ), + child: const Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(Icons.auto_awesome_rounded, color: AppTheme.primaryGreen), + SizedBox(width: 12), + Text( + 'Analisis Sistem', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: AppTheme.primaryGreen), + ), + ], + ), + SizedBox(height: 12), + Text( + 'Berdasarkan data 24 jam terakhir, kelembapan stabil di rentang ideal (80-90%). Pertumbuhan jamur terpantau optimal.', + style: TextStyle(fontSize: 14, color: AppTheme.textDark, height: 1.5), + ), + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 2e00def..16ed18e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,8 @@ import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:monitoring_jamur/core/constants/supabase_config.dart'; import 'package:monitoring_jamur/core/theme/app_theme.dart'; import 'package:monitoring_jamur/features/auth/presentation/pages/login_page.dart'; +import 'package:monitoring_jamur/features/home/presentation/pages/main_screen.dart'; +import 'package:monitoring_jamur/core/session/user_session.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -12,6 +14,8 @@ void main() async { anonKey: SupabaseConfig.anonKey, ); + await UserSession.init(); + runApp(const MyApp()); } @@ -24,7 +28,7 @@ class MyApp extends StatelessWidget { title: 'Mushroom Monitor', debugShowCheckedModeBanner: false, theme: AppTheme.lightTheme, - home: const LoginPage(), + home: UserSession.isLoggedIn ? const MainScreen() : const LoginPage(), ); } } diff --git a/pubspec.lock b/pubspec.lock index 6e4c749..4e8b1fd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -33,6 +33,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + archive: + dependency: transitive + description: + name: archive + sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff + url: "https://pub.dev" + source: hosted + version: "4.0.9" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -57,6 +73,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -142,6 +174,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -224,6 +264,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image: + dependency: transitive + description: + name: image + sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce + url: "https://pub.dev" + source: hosted + version: "4.8.0" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 + url: "https://pub.dev" + source: hosted + version: "4.11.0" jwt_decode: dependency: transitive description: @@ -376,6 +432,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" platform: dependency: transitive description: @@ -400,6 +464,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + posix: + dependency: transitive + description: + name: posix + sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" + url: "https://pub.dev" + source: hosted + version: "6.5.0" postgrest: dependency: transitive description: @@ -441,7 +513,7 @@ packages: source: hosted version: "0.28.0" shared_preferences: - dependency: transitive + dependency: "direct main" description: name: shared_preferences sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf @@ -693,6 +765,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 524c9a1..a5d7d05 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,6 +36,7 @@ dependencies: cupertino_icons: ^1.0.8 supabase_flutter: ^2.8.1 google_fonts: ^6.2.1 + shared_preferences: ^2.5.5 dev_dependencies: flutter_test: @@ -47,6 +48,7 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^6.0.0 + flutter_launcher_icons: ^0.13.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -90,3 +92,9 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/to/font-from-package + +flutter_launcher_icons: + android: "launcher_icon" + ios: true + image_path: "lib/assets/mushroom.png" + min_sdk_android: 21