From c0e892341b73923483d4ab236b70b6f525b1a018 Mon Sep 17 00:00:00 2001 From: Trina Bakshi Date: Fri, 30 May 2025 17:55:36 +0530 Subject: [PATCH] Acc_no_drop_down_functionality --- lib/app.dart | 6 +- lib/config/routes.dart | 2 + lib/features/auth/screens/mpin_screen.dart | 16 +- lib/features/auth/screens/mpin_setup.dart | 146 +++++++++++++++++ .../auth/screens/mpin_setup_confirm.dart | 155 ++++++++++++++++++ 5 files changed, 317 insertions(+), 8 deletions(-) create mode 100644 lib/features/auth/screens/mpin_setup.dart create mode 100644 lib/features/auth/screens/mpin_setup_confirm.dart diff --git a/lib/app.dart b/lib/app.dart index 4921487..d59bc23 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -53,7 +53,7 @@ class KMobile extends StatelessWidget { builder: (context, state) { // Handle different authentication states if (state is AuthInitial || state is AuthLoading) { - return const _SplashScreen(); + return const SplashScreen(); } if(state is ShowBiometricPermission){ @@ -73,8 +73,8 @@ class KMobile extends StatelessWidget { } // Simple splash screens component -class _SplashScreen extends StatelessWidget { - const _SplashScreen(); +class SplashScreen extends StatelessWidget { + const SplashScreen(); @override Widget build(BuildContext context) { diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 061e7f9..8a2bafa 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -31,6 +31,8 @@ class AppRoutes { // Route generator static Route generateRoute(RouteSettings settings) { switch (settings.name) { + case splash: + return MaterialPageRoute(builder: (_) => const SplashScreen()); case login: return MaterialPageRoute(builder: (_) => const LoginScreen()); diff --git a/lib/features/auth/screens/mpin_screen.dart b/lib/features/auth/screens/mpin_screen.dart index e681787..a31e2f2 100644 --- a/lib/features/auth/screens/mpin_screen.dart +++ b/lib/features/auth/screens/mpin_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:kmobile/features/auth/controllers/auth_cubit.dart'; +import 'package:kmobile/security/secure_storage.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; import '../../../app.dart'; @@ -64,15 +65,20 @@ class MPinScreenState extends State { return Padding( padding: const EdgeInsets.all(8.0), child: GestureDetector( - onTap: () { + onTap: () async { if (key == '<') { deleteDigit(); } else if (key == 'Enter') { if (mPin.length == 4) { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => const NavigationScaffold()), - ); + String storedMpin = await SecureStorage().read("mpin"); + if(!mounted) return; + if(storedMpin == mPin.join()) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const NavigationScaffold()), + ); + } } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Please enter 4 digits")), diff --git a/lib/features/auth/screens/mpin_setup.dart b/lib/features/auth/screens/mpin_setup.dart new file mode 100644 index 0000000..66964b6 --- /dev/null +++ b/lib/features/auth/screens/mpin_setup.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:kmobile/features/auth/controllers/auth_cubit.dart'; +import 'package:kmobile/features/auth/screens/mpin_setup_confirm.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; + +import '../../../app.dart'; + +class MPinSetupScreen extends StatefulWidget { + const MPinSetupScreen({super.key}); + + @override + MPinSetupScreenState createState() => MPinSetupScreenState(); +} + +class MPinSetupScreenState extends State { + List mPin = []; + + void addDigit(String digit) { + if (mPin.length < 4) { + setState(() { + mPin.add(digit); + }); + } + } + + void deleteDigit() { + if (mPin.isNotEmpty) { + setState(() { + mPin.removeLast(); + }); + } + } + + Widget buildMPinDots() { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(4, (index) { + return Container( + margin: const EdgeInsets.all(8), + width: 15, + height: 15, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: index < mPin.length ? Colors.black : Colors.grey[400], + ), + ); + }), + ); + } + + Widget buildNumberPad() { + List> keys = [ + ['1', '2', '3'], + ['4', '5', '6'], + ['7', '8', '9'], + ['Enter', '0', '<'] + ]; + + return Column( + children: keys.map((row) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: row.map((key) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () { + if (key == '<') { + deleteDigit(); + } else if (key == 'Enter') { + if (mPin.length == 4) { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => MPinSetupConfirmScreen(mPin: mPin,)), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("Please enter 4 digits")), + ); + } + } else if (key.isNotEmpty) { + addDigit(key); + } + }, + child: Container( + width: 70, + height: 70, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey[200], + ), + alignment: Alignment.center, + child: key == 'Enter' ? const Icon(Symbols.check) : Text( + key == '<' ? '⌫' : key, + style: TextStyle( + fontSize: 20, + fontWeight: key == 'Enter' ? + FontWeight.normal : FontWeight.normal, + color: key == 'Enter' ? Colors.blue : Colors.black, + ), + ), + ), + ), + ); + }).toList(), + ); + }).toList(), + ); + } + + @override + Widget build(BuildContext context) { + final cubit = context.read(); + + return Scaffold( + body: SafeArea( + child: Column( + children: [ + const Spacer(), + // Logo + const FlutterLogo(size: 100), + const SizedBox(height: 20), + const Text( + "Enter your mPIN", + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 20), + buildMPinDots(), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton(onPressed: () { + cubit.authenticateBiometric(); + }, child: const Text("Try another way")), + TextButton(onPressed: () {}, child: const Text("Register?")), + ], + ), + buildNumberPad(), + const Spacer(), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/auth/screens/mpin_setup_confirm.dart b/lib/features/auth/screens/mpin_setup_confirm.dart new file mode 100644 index 0000000..a6fab6f --- /dev/null +++ b/lib/features/auth/screens/mpin_setup_confirm.dart @@ -0,0 +1,155 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:kmobile/features/auth/controllers/auth_cubit.dart'; +import 'package:kmobile/security/secure_storage.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:collection/collection.dart'; + +import '../../../app.dart'; + +class MPinSetupConfirmScreen extends StatefulWidget { + final List mPin; + const MPinSetupConfirmScreen({super.key, required this.mPin}); + + @override + MPinSetupConfirmScreenState createState() => MPinSetupConfirmScreenState(); +} + +class MPinSetupConfirmScreenState extends State { + List mPin = []; + + void addDigit(String digit) { + if (mPin.length < 4) { + setState(() { + mPin.add(digit); + }); + } + } + + void deleteDigit() { + if (mPin.isNotEmpty) { + setState(() { + mPin.removeLast(); + }); + } + } + + Widget buildMPinDots() { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(4, (index) { + return Container( + margin: const EdgeInsets.all(8), + width: 15, + height: 15, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: index < mPin.length ? Colors.black : Colors.grey[400], + ), + ); + }), + ); + } + + Widget buildNumberPad() { + List> keys = [ + ['1', '2', '3'], + ['4', '5', '6'], + ['7', '8', '9'], + ['Enter', '0', '<'] + ]; + + return Column( + children: keys.map((row) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: row.map((key) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () async { + if (key == '<') { + deleteDigit(); + } else if (key == 'Enter') { + if (mPin.length == 4 && mPin.join() == widget.mPin.join()) { + + await SecureStorage().write("mpin", mPin.join()); + await SharedPreferences.getInstance() + .then((prefs) => prefs.setBool('mpin_set', true)); + if(!mounted) return; + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const NavigationScaffold()), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("Please enter 4 digits")), + ); + } + } else if (key.isNotEmpty) { + addDigit(key); + } + }, + child: Container( + width: 70, + height: 70, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey[200], + ), + alignment: Alignment.center, + child: key == 'Enter' ? const Icon(Symbols.check) : Text( + key == '<' ? '⌫' : key, + style: TextStyle( + fontSize: 20, + fontWeight: key == 'Enter' ? + FontWeight.normal : FontWeight.normal, + color: key == 'Enter' ? Colors.blue : Colors.black, + ), + ), + ), + ), + ); + }).toList(), + ); + }).toList(), + ); + } + + @override + Widget build(BuildContext context) { + final cubit = context.read(); + + return Scaffold( + body: SafeArea( + child: Column( + children: [ + const Spacer(), + // Logo + const FlutterLogo(size: 100), + const SizedBox(height: 20), + const Text( + "Enter your mPIN", + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 20), + buildMPinDots(), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton(onPressed: () { + cubit.authenticateBiometric(); + }, child: const Text("Try another way")), + TextButton(onPressed: () {}, child: const Text("Register?")), + ], + ), + buildNumberPad(), + const Spacer(), + ], + ), + ), + ); + } +} \ No newline at end of file