From e0618ea3c444a361bffc1697fae8041551184c52 Mon Sep 17 00:00:00 2001 From: Patrick Alvin Alcala Date: Fri, 12 Dec 2025 16:39:12 +0800 Subject: [PATCH 1/4] Added bloc --- lib/blocs/user/functions/bloc_getuser.dart | 14 ++++ lib/blocs/user/functions/bloc_setuser.dart | 14 ++++ lib/blocs/user/user_bloc.dart | 14 ++++ lib/blocs/user/user_event.dart | 8 ++ lib/blocs/user/user_state.dart | 5 ++ pubspec.lock | 96 ++++++++-------------- pubspec.yaml | 2 +- 7 files changed, 88 insertions(+), 65 deletions(-) create mode 100644 lib/blocs/user/functions/bloc_getuser.dart create mode 100644 lib/blocs/user/functions/bloc_setuser.dart create mode 100644 lib/blocs/user/user_bloc.dart create mode 100644 lib/blocs/user/user_event.dart create mode 100644 lib/blocs/user/user_state.dart diff --git a/lib/blocs/user/functions/bloc_getuser.dart b/lib/blocs/user/functions/bloc_getuser.dart new file mode 100644 index 0000000..12e0a71 --- /dev/null +++ b/lib/blocs/user/functions/bloc_getuser.dart @@ -0,0 +1,14 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_bloc.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_event.dart'; + +Future blocGetUser(BuildContext context) async { + try { + final userBloc = context.read(); + userBloc.add(UserGetValue()); + return userBloc.state.value; + } catch (e) { + return ''; + } +} diff --git a/lib/blocs/user/functions/bloc_setuser.dart b/lib/blocs/user/functions/bloc_setuser.dart new file mode 100644 index 0000000..d433dd0 --- /dev/null +++ b/lib/blocs/user/functions/bloc_setuser.dart @@ -0,0 +1,14 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_bloc.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_event.dart'; + +Future blocSetUser(BuildContext context, String value) async { + try { + final userBloc = context.read(); + userBloc.add(UserSetValue(value)); + return true; + } catch (e) { + return false; + } +} diff --git a/lib/blocs/user/user_bloc.dart b/lib/blocs/user/user_bloc.dart new file mode 100644 index 0000000..d7c5526 --- /dev/null +++ b/lib/blocs/user/user_bloc.dart @@ -0,0 +1,14 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_event.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_state.dart'; + +class UserBloc extends Bloc { + UserBloc() : super(UserState('')) { + on((event, emit) { + emit(UserState(event.value)); + }); + on((event, emit) { + emit(state); + }); + } +} diff --git a/lib/blocs/user/user_event.dart b/lib/blocs/user/user_event.dart new file mode 100644 index 0000000..3c9b4be --- /dev/null +++ b/lib/blocs/user/user_event.dart @@ -0,0 +1,8 @@ +abstract class UserEvent {} + +class UserSetValue extends UserEvent { + final String value; + UserSetValue(this.value); +} + +class UserGetValue extends UserEvent {} diff --git a/lib/blocs/user/user_state.dart b/lib/blocs/user/user_state.dart new file mode 100644 index 0000000..6e75251 --- /dev/null +++ b/lib/blocs/user/user_state.dart @@ -0,0 +1,5 @@ +class UserState { + final String value; + + UserState(this.value); +} diff --git a/pubspec.lock b/pubspec.lock index 031a2f2..b0f3ddb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,30 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - adaptive_dialog: - dependency: "direct main" - description: - name: adaptive_dialog - sha256: "46e235feb99475d36a55fb6a424fe4e4aea1235c41089b847c4a20087582f029" - url: "https://pub.dev" - source: hosted - version: "2.6.0" - animations: - dependency: transitive - description: - name: animations - sha256: "18938cefd7dcc04e1ecac0db78973761a01e4bc2d6bfae0cfa596bfeac9e96ab" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - appkit_ui_element_colors: - dependency: transitive - description: - name: appkit_ui_element_colors - sha256: b88a7c35d440fa3ac75222d0e2b7e3259200e531e33b5d2468e358119f3481dc - url: "https://pub.dev" - source: hosted - version: "1.0.1" args: dependency: transitive description: @@ -41,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.13.0" + bloc: + dependency: transitive + description: + name: bloc + sha256: a2cebb899f91d36eeeaa55c7b20b5915db5a9df1b8fd4a3c9c825e22e474537d + url: "https://pub.dev" + source: hosted + version: "9.1.0" boolean_selector: dependency: transitive description: @@ -129,14 +113,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - dynamic_color: - dependency: transitive - description: - name: dynamic_color - sha256: "43a5a6679649a7731ab860334a5812f2067c2d9ce6452cf069c5e0c25336c17c" - url: "https://pub.dev" - source: hosted - version: "1.8.1" equatable: dependency: transitive description: @@ -166,6 +142,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: cf51747952201a455a1c840f8171d273be009b932c75093020f9af64f2123e38 + url: "https://pub.dev" + source: hosted + version: "9.1.1" flutter_dotenv: dependency: "direct main" description: @@ -216,14 +200,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.3.3" - gradient_borders: - dependency: transitive - description: - name: gradient_borders - sha256: "492bc88ab8d88a4117a7f00e525a669b65f19973bea7ee677f9d9de7603bf037" - url: "https://pub.dev" - source: hosted - version: "1.0.2" hashlib: dependency: "direct main" description: @@ -264,14 +240,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" - intersperse: - dependency: transitive - description: - name: intersperse - sha256: "2f8a905c96f6cbba978644a3d5b31b8d86ddc44917662df7d27a61f3df66a576" - url: "https://pub.dev" - source: hosted - version: "2.0.0" leak_tracker: dependency: transitive description: @@ -312,22 +280,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macos_ui: - dependency: transitive - description: - name: macos_ui - sha256: "09fb51d65b6a2d328ba5aa429ba0f7aabad5bc770193ea6e49da9f29bf95d835" - url: "https://pub.dev" - source: hosted - version: "2.2.2" - macos_window_utils: - dependency: transitive - description: - name: macos_window_utils - sha256: d4df3501fd32ac0d2d7590cb6a8e4758337d061c8fa0db816fdd636be63a8438 - url: "https://pub.dev" - source: hosted - version: "1.9.0" matcher: dependency: transitive description: @@ -368,6 +320,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.1.3" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" nm: dependency: transitive description: @@ -456,6 +416,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + provider: + dependency: transitive + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" + source: hosted + version: "6.1.5+1" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index d66982f..958ee4a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: flutter_dotenv: ^6.0.0 dio_smart_retry: ^7.0.1 hashlib: ^2.2.0 - adaptive_dialog: ^2.6.0 + flutter_bloc: ^9.1.1 dev_dependencies: flutter_test: From 130a8f33f0917717f86cc0537c4726bb678d36c5 Mon Sep 17 00:00:00 2001 From: Patrick Alvin Alcala Date: Fri, 12 Dec 2025 16:39:23 +0800 Subject: [PATCH 2/4] Used bloc on main --- lib/main.dart | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8370435..c93245d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:go_router/go_router.dart'; +import 'package:ocbo_esign_validator/blocs/user/user_bloc.dart'; import 'package:ocbo_esign_validator/pages/approval_page.dart'; import 'package:ocbo_esign_validator/pages/index_page.dart'; import 'package:ocbo_esign_validator/pages/login_page.dart'; @@ -28,10 +30,13 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp.router( - debugShowCheckedModeBanner: false, - theme: ThemeData(useMaterial3: true), - routerConfig: _router, + return MultiBlocProvider( + providers: [BlocProvider(create: (context) => UserBloc())], + child: MaterialApp.router( + debugShowCheckedModeBanner: false, + theme: ThemeData(useMaterial3: true), + routerConfig: _router, + ), ); } } From 1b86907d1b48a6abc895c0df79e7f4c804c9b2b6 Mon Sep 17 00:00:00 2001 From: Patrick Alvin Alcala Date: Fri, 12 Dec 2025 16:39:30 +0800 Subject: [PATCH 3/4] Added modal widget --- lib/functions/modal.dart | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/functions/modal.dart diff --git a/lib/functions/modal.dart b/lib/functions/modal.dart new file mode 100644 index 0000000..792f480 --- /dev/null +++ b/lib/functions/modal.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:ocbo_esign_validator/widgets/text_widget.dart'; + +void showModal(BuildContext context, String title, String message, bool error) { + showDialog( + context: context, + builder: (context) => Theme( + data: ThemeData( + dialogTheme: DialogThemeData( + backgroundColor: error + ? const Color.fromRGBO(72, 30, 31, 0.919) + : Color.fromRGBO(18, 44, 31, 0.919), // Check the value of `error` + ), + ), + child: AlertDialog( + title: TextWidget(text: title, color: Color.fromRGBO(244, 244, 244, 1), bold: true, size: 24), + content: SizedBox( + height: 48, + child: Column( + children: [ + const Gap(24), + TextWidget(text: message, color: Color.fromRGBO(244, 244, 244, 1), size: 16), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const TextWidget(text: 'OK', color: Colors.white, bold: true, size: 16), + ), + ], + ), + ), + ); +} From a60d6284ca9746abe586e70a9214a11de10d0483 Mon Sep 17 00:00:00 2001 From: Patrick Alvin Alcala Date: Fri, 12 Dec 2025 16:39:38 +0800 Subject: [PATCH 4/4] Updated pages --- lib/pages/approval_page.dart | 65 ++++++++++++++++++++++++++++++++++-- lib/pages/login_page.dart | 23 ++++++++++--- lib/pages/validate_page.dart | 24 +++++++++++-- 3 files changed, 103 insertions(+), 9 deletions(-) diff --git a/lib/pages/approval_page.dart b/lib/pages/approval_page.dart index 3361250..5ba85cc 100644 --- a/lib/pages/approval_page.dart +++ b/lib/pages/approval_page.dart @@ -1,10 +1,71 @@ import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:ocbo_esign_validator/blocs/user/functions/bloc_getuser.dart'; +import 'package:ocbo_esign_validator/widgets/image_widget.dart'; +import 'package:ocbo_esign_validator/widgets/text_widget.dart'; -class ApprovalPage extends StatelessWidget { +class ApprovalPage extends StatefulWidget { const ApprovalPage({super.key}); + @override + State createState() => _ApprovalPageState(); +} + +class _ApprovalPageState extends State { + late String blocUser = ''; + + Future _getUser() async { + final user = await blocGetUser(context); + return user; + } + + void _initUser() async { + blocUser = await _getUser(); + } + + @override + void initState() { + _initUser(); + super.initState(); + } + @override Widget build(BuildContext context) { - return Scaffold(); + return Scaffold( + resizeToAvoidBottomInset: false, + body: Container( + alignment: Alignment.center, + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color.fromRGBO(39, 26, 47, 1), + Color.fromRGBO(22, 33, 44, 1), + Color.fromRGBO(22, 33, 44, 1), + Color.fromRGBO(24, 45, 40, 1), + ], + ), + ), + child: Column( + children: [ + const Gap(76), + Row( + children: [ + const Gap(16), + const ImageWidget(imagePath: 'assets/logo.png', size: 32, measureByHeight: true), + const Gap(8), + TextWidget(text: blocUser, size: 16, bold: true), + const MaxGap(80), + Icon(Icons.menu, size: 20, color: Colors.white), + ], + ), + const Gap(32), + TextWidget(text: blocUser, size: 16, bold: true), + ], + ), + ), + ); } } diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index f6b4a84..0d481d3 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -3,8 +3,11 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:gap/gap.dart'; +import 'package:go_router/go_router.dart'; import 'package:hashlib/hashlib.dart'; +import 'package:ocbo_esign_validator/blocs/user/functions/bloc_setuser.dart'; import 'package:ocbo_esign_validator/functions/get_api.dart'; +import 'package:ocbo_esign_validator/functions/modal.dart'; import 'package:ocbo_esign_validator/widgets/box_widget.dart'; import 'package:ocbo_esign_validator/widgets/button_widget.dart'; import 'package:ocbo_esign_validator/widgets/image_widget.dart'; @@ -66,14 +69,26 @@ class _LoginPageState extends State { final employeeid = _approverId; final dbpassword = await _getPassword(employeeid); final hashPassword = await _securePassword(_passwordController.text); - if (dbpassword == hashPassword) { - log('yeah'); - } else { - log('no'); + + if (context.mounted) { + if (dbpassword == hashPassword) { + _setLogin(); + } else { + _showDialog(); + } } } } + void _setLogin() { + blocSetUser(context, _approver); + context.push('/approval'); + } + + void _showDialog() { + showModal(context, 'Error', 'Invalid password, try again.', true); + } + void _ignoreButton() {} @override diff --git a/lib/pages/validate_page.dart b/lib/pages/validate_page.dart index 47b5035..469a866 100644 --- a/lib/pages/validate_page.dart +++ b/lib/pages/validate_page.dart @@ -20,7 +20,7 @@ class BarcodeScannerScreen extends StatefulWidget { } class _BarcodeScannerScreenState extends State { - String barcodeResult = "Point the camera at a barcode"; + late String qrResult = ''; @override Widget build(BuildContext context) { @@ -54,7 +54,7 @@ class _BarcodeScannerScreenState extends State { ), child: TextWidget(text: 'Scan OCBO e-Sign QR Code', size: 14, bold: true), ), - Gap(50), + const Gap(50), SizedBox( height: 350, child: ClipRRect( @@ -65,13 +65,31 @@ class _BarcodeScannerScreenState extends State { final List barcodes = capture.barcodes; if (barcodes.isNotEmpty && barcodes.first.rawValue != null) { setState(() { - barcodeResult = barcodes.first.rawValue!; + qrResult = barcodes.first.rawValue!; }); } }, ), ), ), + const Gap(40), + Container( + padding: EdgeInsets.all(0), + width: 120, + height: 120, + decoration: BoxDecoration( + border: Border.all( + color: Color.fromRGBO(59, 169, 62, 1), + width: 2, + ), // Background color of the container + borderRadius: BorderRadius.circular(99), // Optional: rounded corners + ), + child: Icon(Icons.thumb_up, color: const Color.fromRGBO(59, 169, 62, 1), size: 80), + ), + const Gap(16), + const TextWidget(text: 'Verified', size: 20, bold: true, color: Color.fromRGBO(59, 169, 62, 1)), + const Gap(16), + TextWidget(text: qrResult, size: 20, bold: true), ], ), ),