From ada75b8f6a2957077bfa10d6e0df2a54c323b0f9 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Tue, 7 Feb 2023 10:39:31 +0200 Subject: [PATCH 01/19] Finishing half of the UI of the menu tab --- lib/main.dart | 2 +- lib/presentation/profile/profile_screen.dart | 4 +- lib/presentation/routes/app_routes.dart | 1 + lib/presentation/settings/menu_tab.dart | 282 +++++++++++++++++++ lib/presentation/themes/constants.dart | 20 ++ pubspec.lock | 209 ++++++++------ pubspec.yaml | 3 + 7 files changed, 439 insertions(+), 82 deletions(-) create mode 100644 lib/presentation/settings/menu_tab.dart diff --git a/lib/main.dart b/lib/main.dart index 90f5bafc..c2e64a11 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index 52fd7b0c..eede50a7 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -9,6 +9,7 @@ import 'package:share_plus/share_plus.dart'; import '../../application/user/profile/profile_bloc.dart'; import '../core/collaction_icons.dart'; import '../routes/app_routes.gr.dart'; +import '../settings/menu_tab.dart'; import '../shared_widgets/photo_selector.dart'; import '../shared_widgets/pill_button.dart'; import '../themes/constants.dart'; @@ -72,7 +73,8 @@ class _UserProfilePageState extends State { ), const SizedBox(height: 10), ElevatedButton( - onPressed: () => context.router.push(const SettingsRoute()), + // onPressed: () => context.router.push(const SettingsRoute()), + onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MenuTab())), style: ElevatedButton.styleFrom( foregroundColor: kPrimaryColor0, backgroundColor: Colors.white, diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index f852a68f..49d0ae37 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -74,6 +74,7 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'settings-layout', page: SettingsLayout), AutoRoute(path: 'contact-form', page: ContactFormPage), AutoRoute(path: 'webview', page: WebViewPage), + ], ) class $AppRouter {} diff --git a/lib/presentation/settings/menu_tab.dart b/lib/presentation/settings/menu_tab.dart new file mode 100644 index 00000000..f774b771 --- /dev/null +++ b/lib/presentation/settings/menu_tab.dart @@ -0,0 +1,282 @@ +import 'package:flutter/material.dart'; +import '../../presentation/themes/constants.dart'; + +class MenuTab extends StatefulWidget { + const MenuTab({Key? key}) : super(key: key); + + @override + State createState() => _MenuTabState(); +} + +class _MenuTabState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontFamily: "Rubik", + fontWeight: FontWeight.w700, + ), + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: "pictureUrl", + name: "Abdelrhman", + phoneNumber: "+970597501896", + ), + GestureDetector( + onTap: () { + debugPrint('Button tapped'); + }, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, shape: BoxShape.circle), + ), + ), + ], + ), + ), + ), + SizedBox( + height: 18, + ), + GestureDetector( + onTap: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.logout, + color: kErrorColor, + ), + SizedBox( + width: 2.5, + ), + Text( + "Log out", + style: TextStyle( + color: kErrorColor, + fontFamily: "Rubik", + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), + SizedBox(height: 38.5), + Text( + "Account", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + SizedBox( + height: 20, + ), + GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.account_circle, + color: kPrimaryColor300, + ), + SizedBox( + width: 18.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Account Information", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 275, + child: Text( + "View and update your account and contact information that is associated with your CollAction account.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ) + ], + ), + ), + SizedBox( + height: 30, + ), + Text( + "Feedback", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + SizedBox( + height: 20, + ), + GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.sms, + color: kPrimaryColor300, + ), + SizedBox( + width: 18.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact us", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 275, + child: Text( + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ), + ], + ), + ), + SizedBox(height: 30,), + Text( + "Legal information and policies", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + ], + ), + ), + ), + ); + } +} + +class AvatarAndInfo extends StatelessWidget { + final String pictureUrl; + + final String name; + + final String phoneNumber; + + const AvatarAndInfo( + {Key? key, + required this.pictureUrl, + required this.name, + required this.phoneNumber}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 65, + height: 65, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + ), + SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: nameTextStyle, + ), + Text( + phoneNumber, + style: phoneNumberTextStyle, + ), + ], + ) + ], + ); + } +} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index af0ecc4d..ea1101eb 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -24,6 +24,7 @@ const Color kPrimaryColor200 = Color(0xFF999999); const Color kPrimaryColor300 = Color(0xFF666666); const Color kPrimaryColor400 = Color(0xFF333333); const Color kPrimaryColor500 = Color(0xFF000000); +const Color kPrimaryColor600 = Color(0xFF2EB494); const TextStyle kCaption1 = TextStyle( fontSize: 12, @@ -41,3 +42,22 @@ const TextStyle kTitle1 = TextStyle( height: 34 / 28, fontWeight: FontWeight.w700, ); + +const TextStyle nameTextStyle = TextStyle( + fontSize: 17 , + fontWeight: FontWeight.w500 , + color: kPrimaryColor400 , +); + +const TextStyle phoneNumberTextStyle = TextStyle( + fontSize: 17, + fontWeight: FontWeight.w300, + color: kPrimaryColor300 , +); + + + +const BoxDecoration avatarInfoDecorationBox = BoxDecoration( + color: kAlmostTransparent , + borderRadius: BorderRadius.all(Radius.circular(20),) +); diff --git a/pubspec.lock b/pubspec.lock index 04868a93..0750b96f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" analyzer: dependency: transitive description: @@ -28,14 +35,14 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.3.2" + version: "3.3.6" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.1" + version: "2.3.2" async: dependency: transitive description: @@ -49,7 +56,7 @@ packages: name: auto_route url: "https://pub.dartlang.org" source: hosted - version: "5.0.2" + version: "5.0.4" auto_route_generator: dependency: "direct dev" description: @@ -119,7 +126,7 @@ packages: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "7.2.6" + version: "7.2.7" built_collection: dependency: transitive description: @@ -133,14 +140,14 @@ packages: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.4.1" + version: "8.4.3" cached_network_image: dependency: "direct main" description: name: cached_network_image url: "https://pub.dartlang.org" source: hosted - version: "3.2.2" + version: "3.2.3" cached_network_image_platform_interface: dependency: transitive description: @@ -162,13 +169,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.1" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" + cli_notify: + dependency: transitive + description: + name: cli_notify + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4" cli_util: dependency: transitive description: @@ -203,7 +224,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "4.3.0" + version: "4.4.0" collection: dependency: transitive description: @@ -211,6 +232,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + console: + dependency: transitive + description: + name: console + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" convert: dependency: transitive description: @@ -238,7 +266,7 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "1.3.2" + version: "1.6.2" cross_file: dependency: transitive description: @@ -259,7 +287,7 @@ packages: name: dart_jsonwebtoken url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.7.1" dart_pubspec_licenses: dependency: transitive description: @@ -281,6 +309,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.1" + date_format: + dependency: transitive + description: + name: date_format + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.7" device_frame: dependency: transitive description: @@ -302,6 +337,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + ed25519_edwards: + dependency: transitive + description: + name: ed25519_edwards + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1" email_validator: dependency: "direct main" description: @@ -357,7 +399,7 @@ packages: name: firebase_auth_mocks url: "https://pub.dartlang.org" source: hosted - version: "0.8.6" + version: "0.8.7" firebase_auth_platform_interface: dependency: transitive description: @@ -380,7 +422,7 @@ packages: source: hosted version: "1.24.0" firebase_core_platform_interface: - dependency: transitive + dependency: "direct overridden" description: name: firebase_core_platform_interface url: "https://pub.dartlang.org" @@ -506,6 +548,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.3" + fvm: + dependency: "direct main" + description: + name: fvm + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.1" get_it: dependency: "direct main" description: @@ -519,7 +568,7 @@ packages: name: glob url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" go_router: dependency: transitive description: @@ -533,7 +582,7 @@ packages: name: graphs url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.0" http: dependency: "direct main" description: @@ -561,42 +610,42 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.2.2" + version: "3.3.0" image_cropper: dependency: "direct main" description: name: image_cropper url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" image_cropper_for_web: dependency: transitive description: name: image_cropper_for_web url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.3" image_cropper_platform_interface: dependency: transitive description: name: image_cropper_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.0.2" + version: "3.0.3" image_picker: dependency: "direct main" description: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.8.6" + version: "0.8.6+1" image_picker_android: dependency: transitive description: name: image_picker_android url: "https://pub.dartlang.org" source: hosted - version: "0.8.5+3" + version: "0.8.5+5" image_picker_for_web: dependency: transitive description: @@ -610,7 +659,7 @@ packages: name: image_picker_ios url: "https://pub.dartlang.org" source: hosted - version: "0.8.6+1" + version: "0.8.6+6" image_picker_platform_interface: dependency: transitive description: @@ -631,14 +680,14 @@ packages: name: injectable url: "https://pub.dartlang.org" source: hosted - version: "1.5.3" + version: "1.5.4" injectable_generator: dependency: "direct dev" description: name: injectable_generator url: "https://pub.dartlang.org" source: hosted - version: "1.5.4" + version: "1.5.5" intl: dependency: "direct main" description: @@ -652,14 +701,14 @@ packages: name: io url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" ionicons: dependency: "direct main" description: name: ionicons url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "0.2.2" js: dependency: transitive description: @@ -680,7 +729,7 @@ packages: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "6.5.3" + version: "6.5.4" lint: dependency: "direct dev" description: @@ -701,7 +750,7 @@ packages: name: logging url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" matcher: dependency: transitive description: @@ -729,7 +778,7 @@ packages: name: mime url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.4" mocktail: dependency: "direct main" description: @@ -771,7 +820,7 @@ packages: name: package_info_plus url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" package_info_plus_platform_interface: dependency: transitive description: @@ -792,21 +841,21 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.20" - path_provider_ios: + version: "2.0.22" + path_provider_foundation: dependency: transitive description: - name: path_provider_ios + name: path_provider_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.1.1" path_provider_linux: dependency: transitive description: @@ -814,13 +863,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.6" path_provider_platform_interface: dependency: transitive description: @@ -848,7 +890,7 @@ packages: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "5.0.0" + version: "5.1.0" phone_number: dependency: "direct main" description: @@ -891,20 +933,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" + process_run: + dependency: transitive + description: + name: process_run + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.5+2" provider: dependency: transitive description: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.4" + version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" pubspec_parse: dependency: transitive description: @@ -925,56 +974,49 @@ packages: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.27.5" + version: "0.27.7" share_plus: dependency: "direct main" description: name: share_plus url: "https://pub.dartlang.org" source: hosted - version: "6.0.1" + version: "6.3.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.1.2" + version: "3.2.0" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.15" + version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.14" - shared_preferences_ios: + version: "2.0.15" + shared_preferences_foundation: dependency: transitive description: - name: shared_preferences_ios + name: shared_preferences_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" + version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: @@ -995,7 +1037,7 @@ packages: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" shelf: dependency: transitive description: @@ -1023,7 +1065,7 @@ packages: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.3" shimmer: dependency: "direct main" description: @@ -1070,7 +1112,7 @@ packages: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.10" + version: "0.10.11" source_span: dependency: transitive description: @@ -1084,14 +1126,14 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "2.1.0+1" + version: "2.2.4+1" sqflite_common: dependency: transitive description: name: sqflite_common url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.4.2+2" stack_trace: dependency: transitive description: @@ -1112,7 +1154,7 @@ packages: name: stream_transform url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.1.0" string_scanner: dependency: transitive description: @@ -1126,7 +1168,7 @@ packages: name: synchronized url: "https://pub.dartlang.org" source: hosted - version: "3.0.0+3" + version: "3.0.1" term_glyph: dependency: transitive description: @@ -1161,7 +1203,14 @@ packages: name: timing url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.1" + tint: + dependency: transitive + description: + name: tint + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" typed_data: dependency: transitive description: @@ -1175,35 +1224,35 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.6" + version: "6.1.8" url_launcher_android: dependency: transitive description: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.19" + version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios url: "https://pub.dartlang.org" source: hosted - version: "6.0.17" + version: "6.0.18" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: @@ -1217,21 +1266,21 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.3" uuid: dependency: transitive description: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "3.0.6" + version: "3.0.7" vector_math: dependency: transitive description: @@ -1245,7 +1294,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "8.3.0" + version: "9.4.0" watcher: dependency: transitive description: @@ -1259,7 +1308,7 @@ packages: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" webkit_inspection_protocol: dependency: transitive description: @@ -1329,14 +1378,14 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.1.3" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.2.0+2" + version: "0.2.0+3" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 93ad1741..993d1138 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: flutter_bloc: ^8.1.1 flutter_dotenv: ^5.0.2 freezed_annotation: ^2.2.0 + fvm: ^2.4.1 get_it: ^7.2.0 http: ^0.13.5 image: ^3.2.2 @@ -77,6 +78,8 @@ dev_dependencies: lint: ^1.10.0 widgetbook: ^2.4.1 widgetbook_generator: ^2.4.1 +dependency_overrides: + firebase_core_platform_interface: 4.5.1 flutter_icons: android: true From 1b02c3105ba48caac0e463acc801cac42cb64435 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:01:37 +0200 Subject: [PATCH 02/19] Finishing the Menu screen as a UI. --- assets/images/collaction.png | Bin 0 -> 4568 bytes lib/presentation/home/home_screen.dart | 5 + lib/presentation/menu/menu_screen.dart | 368 +++++++++++++++++++ lib/presentation/profile/profile_screen.dart | 4 +- lib/presentation/routes/app_routes.dart | 12 +- lib/presentation/settings/menu_tab.dart | 282 -------------- lib/presentation/themes/constants.dart | 5 + 7 files changed, 390 insertions(+), 286 deletions(-) create mode 100644 assets/images/collaction.png create mode 100644 lib/presentation/menu/menu_screen.dart delete mode 100644 lib/presentation/settings/menu_tab.dart diff --git a/assets/images/collaction.png b/assets/images/collaction.png new file mode 100644 index 0000000000000000000000000000000000000000..1f77c9b2d0729be8d76b412a9e36d2a337da889f GIT binary patch literal 4568 zcmV;}5hw16P)D5cHzGBe4{B#-oEW?lh%B-rl=dZg6qMx%Ryiz1z(*-ipg>tHAWQ4Lv*pj7C6l}?E#y1rJ9#hvy?3_% zn}7e)*EazqZW);rFBfizl;(cP{w`K7{3%k>4`J$AUngGem09Q@}Pyp+sI%j4&a3=%I&BV`^ni zI$9~-RwK?Z0tQCQ`a7{o;ljx`9kU%9vxgpfXfq-=&)zjw(k}%ezD0%UDd4icl%`i% zd?HdFIi8K*Ll5mlDm7!Okk$_8CG`lFDLKCvwS7+^b=9n`BcuAM(Q@G>w-5saTq-P~ z>68$2Wwbo38j|V3LD#k8{owN-r?wQltli4X>P8Q4h^2B;!AsgP@KCM>KI`$Y404k4E`0t2GQeUko!^(n=rnj)xtpG& z#g|z-LDIhDVPh~Uso!C3gTV7@1g`xy@EiB0_5i%_j--CwL^`c~j9#-%E~8#a?J3}T z$Ecsp{_J3u+HcmtUgKCC`#(`|<^A3de?+Pk1KSs;N*V*Br_?R(H?6UJ>yj*wm%7sqr-2)0tSDmVI4=w%gR@%?PiHRmd%|^zw6t$af?VvKL&(6 zPDMuvRo}&|D^!Dbg74Q*J2&-8v@$=#`i4PbV6RE=@YcE?ri=H2(0{{A$|63a{007h z%EP9H*#7He#_g1VjgBBmeUbVG5{^mZbORF=@OvI0rg11m&+-y-eCdgwh*k6pVm@tS zsQTX3ch#&9xctiVhamk~YLASUi%;QfF6t8&AWGf+AZz$MFDjp*ev#qfZBwH5eMsNn z;p31KRh{|CpdgzpZp=NOi^{YogR_~^9nt^?P==Wimd}kEZR$!9 zhofGKm-PpM3ma+YdI2)lJ?;m|Fq8i*^21!$@y#9W;EA~g}<=eQJZ zg~I0qh>k&ttH(pWY+Az)*&h^%^EZ&Fro60*vt>Gw`-Nj-_i z^8*SO1a%RO5lBg0jAPSm9A47C?y_r?&}6dXaguhuE8Su$HR##*f)hmGJQl%AD6qE1 z5^Nt2YF7vKhGVl0p2gAd_iCC(3HSIs9D#8HQvo|dE*CD{)D|I#qAJh}Vky9zoBDVG zN}XR*UzXG!tK@u$o9jmqS%JnxbV9&phmG40DP**RFf+j4FVi%W$|E$M7ogUYgnRmg z+rK{H{MTaX)2$p3tZ`T{IoiQjYnb3?t)qi^=ptD5|Xx$5ij6c!?QU7eD1wC6l?GgRV6^n-s9D-b-zoLfrr-5AEx5Ayta`{i)AHkP;P~rs+P8MaaBYa03HI@4b-A z?FJd=ENWB3jCu|mzuf}H<57E?IKP^;mN|} zgEr+{zHZf2`B{2TEdif*!MXp_q07#sQChNgHYMd4`y9gx7-Fe3op4DyttGHmIGG#X zS-`mn8TAzpJCl++YR5)|5ik@$E39G93m|WlXu6x)pkBOk(YGx!iW}jQndflDdixIZbpJDZGF+-wsN+kB==_uwY9zuHh3rxBRU{ zLivbo8L=3!bQ&EOa7KNd9>Y17q#Q`?5!}Fx z$<&smBx$^D+fD%o-m8rIJGcD|&SmEuL;Vf4M+6P&Ic+q8WWdTQBptfylz{nw+5so$ zk78rm;Pcp9t-e6*89!&mTabW-jIx4_%L39DQ+tO04lm%+h^rH((+JFz$QD+ilR0RQ z(fAA#q;z4y2h0?M3^mKPYpZ}I^^ernCRP`zJpu%=lG>WbP~XAK%G#RuM|*?XIzD24 zI&05D$byKoa7~2RM54Bx5HMDYXMOSvz?p&;dJ+I16wAWs)*e1@-4dlqohANBAtDOIN^woAa+X61d?MJp?*y^WwM zVL#KZL_kT(QyZ2jaMr$AbV9(^^jufE%{a8nXB{>!>}8AYtOTY#2K>UZVmwwvh3#wRj_zz+Ozt z>H!}12BErKVvo_E^1naGR?R8zh=65f3Qc24M-N!=LHz)dvdFRPj)3(y;+2t~(xBY} zH;|w1aS;x2HVgIf0xxM24x`|*IZC+EXQR#LEMPvPEv0s?pdbv1_A%a10*;G=d(gNx z_)S2-tKGuIQdj?DY`NY~19lVjZZr-?fhx4DJmBGDkbTLtL%{um zgE8LRI>==^Q6@8r(~&7;jVYQg8^?AtszT!@O=Fo5hdk$PBj8#8ncCarI#Pu$=}!>x zJ{B*{ckRe9JT|;ld`uUk<&k_N+r#2?%=l7WoO0*932)P4bT$O^3_~04!M;9scRvej z=8((RCWjpZef1yeyf! z7GQG?^&z~*v|O+y{Qas&y2*_C<=V(5L~-vuT(%4ad4|&i+$I74i`ul5)|5x{{&@FV zBmIVv1W`MP+A>^Ehmq>kx?Zfe+%AlO5%B*Sn(okNYf3ZbMv%FejqGsg5kw_Vl#98OeZ9JUdJ+-|rI*xI_*ZELb- z_mWl%80;>l=?uq>X?kIp(QfqcHz}!WY+rPZ12{bhy~mrz{5U}cDpsKfUPDIF4}k5vEDpNmWH1!0@bY_dt6Yn#N8r1x6(;T+AK(a z%fqK3;w}?3b}I$k4{dUq#&CTy)7b7BP=fgVq5;mqy~?&T7a#b)IKmKK$m@d^!&@(u zhK|v=fbka~W@h++7gqy3kBy6HtAK~c7HkCqIy%fIc3zAuD;hTo5gXO-rs?&mzk%)W zM%%@ltQGj6j;0WV>iCm_q+h5G|i!;UdzS{1KgU( z6{mX4b?j79K_0>(w{dD0hDMcFR=>p_+Y5YVCTdW zT<8z>zLWQT_=q4XhtXIzS}9;YpyYt|=izL;aKP%Z=G(@DdtUP+b*a?wu0qD>2nyE-P%DAmBm~>lk%wM7Dt8nO#NGY>J}d>bON%wTgz;ISbg&0xx(u%)Sltf)ZPG2;J{%bDmFhhCE!YNb+lCQT;0Fz>ZN9ZE9K}p80Uf8 zJNdNz5!ify`}iyBhlFQ4huYTw+OzvxyGptR$a2|SXXQy<0aps^fTz*%<{oG47B { if (!kReleaseMode) ...[ DemoScreenRouter(), ], + MenuScreenRouter() ], bottomNavigationBuilder: (_, tabsRouter) => bottomNavbar(tabsRouter), ); @@ -72,6 +73,10 @@ class HomePageState extends State { label: '', ), ], + BottomNavigationBarItem( + icon: Icon(Icons.menu_outlined), + label: '', + ), ], currentIndex: tabsRouter.activeIndex, onTap: tabsRouter.setActiveIndex, diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart new file mode 100644 index 00000000..bca3b4e9 --- /dev/null +++ b/lib/presentation/menu/menu_screen.dart @@ -0,0 +1,368 @@ +import 'package:flutter/material.dart'; +import '../themes/constants.dart'; +import '../core/collaction_icons.dart'; + +class MenuPage extends StatefulWidget { + const MenuPage({Key? key}) : super(key: key); + + @override + State createState() => _MenuTabState(); +} + +class _MenuTabState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontFamily: "Rubik", + fontWeight: FontWeight.w700, + ), + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: "pictureUrl", + name: "Abdelrhman", + phoneNumber: "+970597501896", + ), + GestureDetector( + onTap: () { + debugPrint('Button tapped'); + }, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle), + ), + ), + ], + ), + ), + ), + SizedBox(height: 18,), + GestureDetector( + onTap: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.logout, + color: kErrorColor, + ), + SizedBox( + width: 2.5, + ), + Text( + "Log out", + style: TextStyle( + color: kErrorColor, + fontFamily: "Rubik", + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), + ], + ), + ), + _buildSubTitle( + subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only(left: 22.25), + child: GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.account_circle, + color: kPrimaryColor300, + size: 19.5, + ), + SizedBox( + width: 12.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Account Information", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 306, + child: Text( + "View and update your account and contact information that is associated with your CollAction account.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ) + ], + ), + ), + ), + _buildSubTitle( + subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only( + left: 22.5, + ), + child: GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + CollactionIcons.message, + color: kPrimaryColor300, + size: 15, + ), + SizedBox( + width: 16.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact us", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 305, + child: Text( + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ), + ], + ), + ), + ), + _buildSubTitle( + subTitle: "Legal information and policies", + paddingBottom: 24, + paddingTop: 30), + LegalInfoAndPoliciesWidget( + onTap: () {}, + iconWidget: CollactionIcons.lock, + label: "Privacy Policy"), + LegalInfoAndPoliciesWidget( + onTap: () {}, + iconWidget: CollactionIcons.file, + label: "Terms & conditions"), + LegalInfoAndPoliciesWidget( + onTap: () {}, + iconWidget: CollactionIcons.opensource, + label: "Privacy Policy"), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Image( + image: AssetImage("assets/images/collaction.png"), + width: 120, + height: 20.36, + ), + SizedBox(height: 4,), + Text('Build 443' ,style: appInfo,), + Text('Version 1.0.1',style: appInfo), + Text('Stichting CollAction',style: appInfo) + ], + ), + ], + ) + ], + ), + ), + ), + ); + } + + Widget _buildSubTitle( + {required String subTitle, + double paddingTop = 0.0, + double paddingBottom = 0.0}) { + return Padding( + padding: + EdgeInsets.only(left: 20, top: paddingTop, bottom: paddingBottom), + child: Text( + subTitle, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + ); + } +} + +class AvatarAndInfo extends StatelessWidget { + final String pictureUrl; + final String name; + final String phoneNumber; + + const AvatarAndInfo( + {Key? key, + required this.pictureUrl, + required this.name, + required this.phoneNumber}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 65, + height: 65, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + ), + SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: nameTextStyle, + ), + Text( + phoneNumber, + style: phoneNumberTextStyle, + ), + ], + ) + ], + ); + } +} + +class LegalInfoAndPoliciesWidget extends StatefulWidget { + final Function onTap; + final IconData iconWidget; + final String label; + + const LegalInfoAndPoliciesWidget( + {Key? key, + required this.onTap, + required this.iconWidget, + required this.label}) + : super(key: key); + + @override + State createState() => + _LegalInfoAndPoliciesWidgetState(); +} + +class _LegalInfoAndPoliciesWidgetState + extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 20, bottom: 27.6), + child: InkWell( + onTap: widget.onTap(), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + widget.iconWidget, + size: 20, + ), + SizedBox( + width: 14, + ), + Text( + widget.label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index eede50a7..52fd7b0c 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -9,7 +9,6 @@ import 'package:share_plus/share_plus.dart'; import '../../application/user/profile/profile_bloc.dart'; import '../core/collaction_icons.dart'; import '../routes/app_routes.gr.dart'; -import '../settings/menu_tab.dart'; import '../shared_widgets/photo_selector.dart'; import '../shared_widgets/pill_button.dart'; import '../themes/constants.dart'; @@ -73,8 +72,7 @@ class _UserProfilePageState extends State { ), const SizedBox(height: 10), ElevatedButton( - // onPressed: () => context.router.push(const SettingsRoute()), - onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MenuTab())), + onPressed: () => context.router.push(const SettingsRoute()), style: ElevatedButton.styleFrom( foregroundColor: kPrimaryColor0, backgroundColor: Colors.white, diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index 49d0ae37..2fa3ab7a 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -14,6 +14,7 @@ import '../demo/components_demo/components_demo_screen.dart'; import '../demo/demo_screen.dart'; import '../home/home_screen.dart'; import '../licenses/licenses_page.dart'; +import '../menu/menu_screen.dart'; import '../onboarding/onboarding_screen.dart'; import '../settings/settings_layout.dart'; import '../settings/settings_screen.dart'; @@ -64,6 +65,16 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'comments', page: CrowdActionCommentsPage), ], ), + AutoRoute( + path: 'menu', + name: 'MenuScreenRouter', + page: EmptyRouterPage, + children: [ + AutoRoute( + path: '' , page: MenuPage + ) + ], + ), ], ), AutoRoute(path: 'onboarding', page: OnboardingPage), @@ -74,7 +85,6 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'settings-layout', page: SettingsLayout), AutoRoute(path: 'contact-form', page: ContactFormPage), AutoRoute(path: 'webview', page: WebViewPage), - ], ) class $AppRouter {} diff --git a/lib/presentation/settings/menu_tab.dart b/lib/presentation/settings/menu_tab.dart deleted file mode 100644 index f774b771..00000000 --- a/lib/presentation/settings/menu_tab.dart +++ /dev/null @@ -1,282 +0,0 @@ -import 'package:flutter/material.dart'; -import '../../presentation/themes/constants.dart'; - -class MenuTab extends StatefulWidget { - const MenuTab({Key? key}) : super(key: key); - - @override - State createState() => _MenuTabState(); -} - -class _MenuTabState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: Padding( - padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - "Menu", - style: TextStyle( - fontSize: 28, - fontFamily: "Rubik", - fontWeight: FontWeight.w700, - ), - ), - IconButton( - onPressed: () {}, - icon: Icon( - Icons.search, - color: kPrimaryColor600, - size: 21.08, - ), - ), - ], - ), - SizedBox( - height: 30, - ), - Container( - height: 85, - decoration: avatarInfoDecorationBox, - child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AvatarAndInfo( - pictureUrl: "pictureUrl", - name: "Abdelrhman", - phoneNumber: "+970597501896", - ), - GestureDetector( - onTap: () { - debugPrint('Button tapped'); - }, - child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), - ), - decoration: BoxDecoration( - color: Colors.white, shape: BoxShape.circle), - ), - ), - ], - ), - ), - ), - SizedBox( - height: 18, - ), - GestureDetector( - onTap: () {}, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.logout, - color: kErrorColor, - ), - SizedBox( - width: 2.5, - ), - Text( - "Log out", - style: TextStyle( - color: kErrorColor, - fontFamily: "Rubik", - fontSize: 15, - fontWeight: FontWeight.w700, - ), - ) - ], - ), - ), - SizedBox(height: 38.5), - Text( - "Account", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - SizedBox( - height: 20, - ), - GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.account_circle, - color: kPrimaryColor300, - ), - SizedBox( - width: 18.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Account Information", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 275, - child: Text( - "View and update your account and contact information that is associated with your CollAction account.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ) - ], - ), - ), - SizedBox( - height: 30, - ), - Text( - "Feedback", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - SizedBox( - height: 20, - ), - GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.sms, - color: kPrimaryColor300, - ), - SizedBox( - width: 18.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Contact us", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 275, - child: Text( - "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ), - ], - ), - ), - SizedBox(height: 30,), - Text( - "Legal information and policies", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - ], - ), - ), - ), - ); - } -} - -class AvatarAndInfo extends StatelessWidget { - final String pictureUrl; - - final String name; - - final String phoneNumber; - - const AvatarAndInfo( - {Key? key, - required this.pictureUrl, - required this.name, - required this.phoneNumber}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 65, - height: 65, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.blue, - ), - ), - SizedBox( - width: 10, - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: nameTextStyle, - ), - Text( - phoneNumber, - style: phoneNumberTextStyle, - ), - ], - ) - ], - ); - } -} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index ea1101eb..a5c1c5e5 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -55,6 +55,11 @@ const TextStyle phoneNumberTextStyle = TextStyle( color: kPrimaryColor300 , ); +const TextStyle appInfo = TextStyle( +fontSize: 17, +fontWeight: FontWeight.w300, + color: kPrimaryColor200 , +); const BoxDecoration avatarInfoDecorationBox = BoxDecoration( From a176209bf457c49d5536c6627beb3e23dda346c5 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sun, 12 Feb 2023 18:28:18 +0200 Subject: [PATCH 03/19] Finishing the menu tab, and removing the settings screen. --- lib/presentation/home/home_screen.dart | 4 +- lib/presentation/menu/menu_screen.dart | 523 ++++++++---------- .../menu/widgets/avatar_info.dart | 83 +++ .../widgets/build_information_tile.dart | 2 +- .../widgets/legal_info_policy_widget.dart | 56 ++ lib/presentation/profile/profile_screen.dart | 27 - lib/presentation/routes/app_routes.dart | 4 - .../settings/settings_layout.dart | 46 -- .../settings/settings_screen.dart | 131 ----- .../settings/widgets/settings_list_tile.dart | 44 -- .../widgets/share_collaction_list_tile.dart | 85 --- lib/presentation/themes/constants.dart | 6 - 12 files changed, 372 insertions(+), 639 deletions(-) create mode 100644 lib/presentation/menu/widgets/avatar_info.dart rename lib/presentation/{settings => menu}/widgets/build_information_tile.dart (95%) create mode 100644 lib/presentation/menu/widgets/legal_info_policy_widget.dart delete mode 100644 lib/presentation/settings/settings_layout.dart delete mode 100644 lib/presentation/settings/settings_screen.dart delete mode 100644 lib/presentation/settings/widgets/settings_list_tile.dart delete mode 100644 lib/presentation/settings/widgets/share_collaction_list_tile.dart diff --git a/lib/presentation/home/home_screen.dart b/lib/presentation/home/home_screen.dart index 917ad2ea..69e01b7f 100644 --- a/lib/presentation/home/home_screen.dart +++ b/lib/presentation/home/home_screen.dart @@ -56,7 +56,7 @@ class HomePageState extends State { unselectedItemColor: kDisabledButtonColor, type: BottomNavigationBarType.fixed, elevation: 0, - items: const [ + items: [ BottomNavigationBarItem( icon: Icon(CollactionIcons.collaction), label: '', @@ -74,7 +74,7 @@ class HomePageState extends State { ), ], BottomNavigationBarItem( - icon: Icon(Icons.menu_outlined), + icon: Icon(Icons.grid_view,), label: '', ), ], diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index bca3b4e9..6b42ea13 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -1,3 +1,15 @@ +import 'package:auto_route/auto_route.dart'; +import 'widgets/build_information_tile.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../application/auth/auth_bloc.dart'; +import '../../application/settings/build_information/build_information_bloc.dart'; +import '../../application/user/profile/profile_bloc.dart'; +import '../../infrastructure/core/injection.dart'; +import '../routes/app_routes.gr.dart'; +import '../utils/launch_url.dart'; +import 'widgets/avatar_info.dart'; +import 'widgets/legal_info_policy_widget.dart'; import 'package:flutter/material.dart'; import '../themes/constants.dart'; import '../core/collaction_icons.dart'; @@ -15,236 +27,258 @@ class _MenuTabState extends State { return Scaffold( body: SafeArea( child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + child: BlocProvider.value( + value: BlocProvider.of(context), + child: BlocBuilder( + builder: (context, state) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: + const EdgeInsets.only(left: 20, top: 10, right: 22.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Menu", - style: TextStyle( - fontSize: 28, - fontFamily: "Rubik", - fontWeight: FontWeight.w700, - ), - ), - IconButton( - onPressed: () {}, - icon: Icon( - Icons.search, - color: kPrimaryColor600, - size: 21.08, - ), - ), - ], - ), - SizedBox( - height: 30, - ), - Container( - height: 85, - decoration: avatarInfoDecorationBox, - child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), - child: Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - AvatarAndInfo( - pictureUrl: "pictureUrl", - name: "Abdelrhman", - phoneNumber: "+970597501896", + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontFamily: "Rubik", + fontWeight: FontWeight.w700, + ), ), - GestureDetector( - onTap: () { - debugPrint('Button tapped'); - }, - child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), - ), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, ), ), ], ), - ), + SizedBox( + height: 30, + ), + Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: state.userProfile?.profile.avatar, + name: state.userProfile?.profile.firstName, + ), + GestureDetector( + onTap: () { + }, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle), + ), + ), + ], + ), + ), + ), + SizedBox( + height: 18, + ), + GestureDetector( + onTap: () async { + BlocProvider.of(context) + .add(const AuthEvent.signedOut()); + BlocProvider.of(context) + .add(GetUserProfile()); + await context.router.pop(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.logout, + color: kErrorColor, + ), + SizedBox( + width: 2.5, + ), + Text( + "Log out", + style: TextStyle( + color: kErrorColor, + fontFamily: "Rubik", + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), + ], ), - SizedBox(height: 18,), - GestureDetector( + ), + _buildSubTitle( + subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only(left: 22.25), + child: GestureDetector( onTap: () {}, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon( - Icons.logout, - color: kErrorColor, + Icons.account_circle, + color: kPrimaryColor300, + size: 19.5, ), SizedBox( - width: 2.5, + width: 12.25, ), - Text( - "Log out", - style: TextStyle( - color: kErrorColor, - fontFamily: "Rubik", - fontSize: 15, - fontWeight: FontWeight.w700, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Account Information", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 306, + child: Text( + "View and update your account and contact information that is associated with your CollAction account.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], ) ], ), ), - ], - ), - ), - _buildSubTitle( - subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), - Padding( - padding: const EdgeInsets.only(left: 22.25), - child: GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.account_circle, - color: kPrimaryColor300, - size: 19.5, - ), - SizedBox( - width: 12.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Account Information", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 306, - child: Text( - "View and update your account and contact information that is associated with your CollAction account.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ) - ], ), - ), - ), - _buildSubTitle( - subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), - Padding( - padding: const EdgeInsets.only( - left: 22.5, - ), - child: GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - CollactionIcons.message, - color: kPrimaryColor300, - size: 15, - ), - SizedBox( - width: 16.25, - ), - Column( + _buildSubTitle( + subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only( + left: 22.5, + ), + child: GestureDetector( + onTap: () {}, + child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Contact us", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), + Icon( + CollactionIcons.message, + color: kPrimaryColor300, + size: 15, ), SizedBox( - height: 5, + width: 16.25, ), - SizedBox( - width: 305, - child: Text( - "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact us", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 305, + child: Text( + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], ), ], ), - ], + ), ), - ), - ), - _buildSubTitle( - subTitle: "Legal information and policies", - paddingBottom: 24, - paddingTop: 30), - LegalInfoAndPoliciesWidget( - onTap: () {}, - iconWidget: CollactionIcons.lock, - label: "Privacy Policy"), - LegalInfoAndPoliciesWidget( - onTap: () {}, - iconWidget: CollactionIcons.file, - label: "Terms & conditions"), - LegalInfoAndPoliciesWidget( - onTap: () {}, - iconWidget: CollactionIcons.opensource, - label: "Privacy Policy"), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( + _buildSubTitle( + subTitle: "Legal information and policies", + paddingBottom: 24, + paddingTop: 30), + LegalInfoAndPoliciesWidget( + onTap: () async { + launchUrl( + 'https://www.collaction.org/privacy', + useWebView: true, + context: context, + ); + }, + iconWidget: CollactionIcons.lock, + label: "Privacy Policy"), + LegalInfoAndPoliciesWidget( + onTap: () => launchUrl( + 'https://www.collaction.org/terms', + useWebView: true, + context: context, + ), + iconWidget: CollactionIcons.file, + label: "Terms & conditions"), + LegalInfoAndPoliciesWidget( + onTap: () => context.router.push(const LicensesRoute()), + iconWidget: CollactionIcons.opensource, + label: "Open-source libraries"), + Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Image( - image: AssetImage("assets/images/collaction.png"), - width: 120, - height: 20.36, + BlocBuilder( + bloc: getIt() + ..add(const BuildInformationEvent.fetch()), + builder: (context, state) { + return state.when( + loading: () => const SizedBox(), + fetched: (buildInfo) => + BuildInformationTile(information: buildInfo), + ); + }, ), - SizedBox(height: 4,), - Text('Build 443' ,style: appInfo,), - Text('Version 1.0.1',style: appInfo), - Text('Stichting CollAction',style: appInfo) + ], - ), + ) ], - ) - ], + ), + ), ), ), ), @@ -269,100 +303,3 @@ class _MenuTabState extends State { ); } } - -class AvatarAndInfo extends StatelessWidget { - final String pictureUrl; - final String name; - final String phoneNumber; - - const AvatarAndInfo( - {Key? key, - required this.pictureUrl, - required this.name, - required this.phoneNumber}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 65, - height: 65, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.blue, - ), - ), - SizedBox( - width: 10, - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: nameTextStyle, - ), - Text( - phoneNumber, - style: phoneNumberTextStyle, - ), - ], - ) - ], - ); - } -} - -class LegalInfoAndPoliciesWidget extends StatefulWidget { - final Function onTap; - final IconData iconWidget; - final String label; - - const LegalInfoAndPoliciesWidget( - {Key? key, - required this.onTap, - required this.iconWidget, - required this.label}) - : super(key: key); - - @override - State createState() => - _LegalInfoAndPoliciesWidgetState(); -} - -class _LegalInfoAndPoliciesWidgetState - extends State { - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 20, bottom: 27.6), - child: InkWell( - onTap: widget.onTap(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - widget.iconWidget, - size: 20, - ), - SizedBox( - width: 14, - ), - Text( - widget.label, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300, - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/presentation/menu/widgets/avatar_info.dart b/lib/presentation/menu/widgets/avatar_info.dart new file mode 100644 index 00000000..4c128270 --- /dev/null +++ b/lib/presentation/menu/widgets/avatar_info.dart @@ -0,0 +1,83 @@ + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +import '../../../domain/user/i_user_repository.dart'; +import '../../../domain/user/user.dart'; +import '../../../infrastructure/core/injection.dart'; +import '../../profile/widget/profile_picture.dart'; +import '../../themes/constants.dart'; + +class AvatarAndInfo extends StatefulWidget { + final String? pictureUrl; + final String? name; + + const AvatarAndInfo( + {Key? key, + required this.pictureUrl, + required this.name, + }) + : super(key: key); + + @override + State createState() => _AvatarAndInfoState(); +} + +class _AvatarAndInfoState extends State { + late final IUserRepository _userRepository; + File? _image; + @override + void initState() { + super.initState(); + _userRepository = getIt(); + } + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // ProfilePicture( + // maxRadius: 40, + // profileImage: + // '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}', + // ), + ProfilePicture( + image: _image, + profileImage: widget.pictureUrl != + null + ? '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}' + : null, + maxRadius: 50, + ), + SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.name ?? "", + style: nameTextStyle, + ), + StreamBuilder(builder: (context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + final number = snapshot.data!.phoneNumber ?? 'no phone number'; + return Text( + number, + style: phoneNumberTextStyle, + ); + } else { + return const Text('...'); + } + + },stream: _userRepository.observeUser() + ,), + ], + ) + ], + ); + } +} diff --git a/lib/presentation/settings/widgets/build_information_tile.dart b/lib/presentation/menu/widgets/build_information_tile.dart similarity index 95% rename from lib/presentation/settings/widgets/build_information_tile.dart rename to lib/presentation/menu/widgets/build_information_tile.dart index 1092d7e6..2d2c575e 100644 --- a/lib/presentation/settings/widgets/build_information_tile.dart +++ b/lib/presentation/menu/widgets/build_information_tile.dart @@ -15,7 +15,7 @@ class BuildInformationTile extends StatelessWidget { const SizedBox(height: 50), const SizedBox( width: 56, - child: Image(image: AssetImage('assets/images/build_info.png')), + child: Image(image: AssetImage('assets/images/collaction.png')), ), const SizedBox(height: 5), Text( diff --git a/lib/presentation/menu/widgets/legal_info_policy_widget.dart b/lib/presentation/menu/widgets/legal_info_policy_widget.dart new file mode 100644 index 00000000..c5ed05a7 --- /dev/null +++ b/lib/presentation/menu/widgets/legal_info_policy_widget.dart @@ -0,0 +1,56 @@ + +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; + +class LegalInfoAndPoliciesWidget extends StatefulWidget { + final onTap; + final IconData iconWidget; + final String label; + + const LegalInfoAndPoliciesWidget( + {Key? key, + required this.onTap, + required this.iconWidget, + required this.label}) + : super(key: key); + + @override + State createState() => + _LegalInfoAndPoliciesWidgetState(); +} + +class _LegalInfoAndPoliciesWidgetState + extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 20, bottom: 27.6), + child: InkWell( + onTap:(){ + widget.onTap(); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + widget.iconWidget, + size: 20, + ), + SizedBox( + width: 14, + ), + Text( + widget.label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index 52fd7b0c..5aea2993 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -71,33 +71,6 @@ class _UserProfilePageState extends State { ), ), const SizedBox(height: 10), - ElevatedButton( - onPressed: () => context.router.push(const SettingsRoute()), - style: ElevatedButton.styleFrom( - foregroundColor: kPrimaryColor0, - backgroundColor: Colors.white, - shape: const CircleBorder(), - tapTargetSize: MaterialTapTargetSize.padded, - ).merge( - ButtonStyle( - elevation: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.pressed)) { - return 5; - } - return 4; - }, - ), - ), - ), - child: const Padding( - padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 4), - child: Icon( - CollactionIcons.settings, - color: kPrimaryColor300, - ), - ), - ), ], ), body: SafeArea( diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index 2fa3ab7a..a5b7f294 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -16,8 +16,6 @@ import '../home/home_screen.dart'; import '../licenses/licenses_page.dart'; import '../menu/menu_screen.dart'; import '../onboarding/onboarding_screen.dart'; -import '../settings/settings_layout.dart'; -import '../settings/settings_screen.dart'; import '../shared_widgets/web_view_page.dart'; @MaterialAutoRouter( @@ -80,9 +78,7 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'onboarding', page: OnboardingPage), AutoRoute(path: 'auth', page: AuthPage), AutoRoute(path: 'verified', page: VerifiedPage), - AutoRoute(path: 'settings-page', page: SettingsPage), AutoRoute(path: 'licenses-page', page: LicensesPage), - AutoRoute(path: 'settings-layout', page: SettingsLayout), AutoRoute(path: 'contact-form', page: ContactFormPage), AutoRoute(path: 'webview', page: WebViewPage), ], diff --git a/lib/presentation/settings/settings_layout.dart b/lib/presentation/settings/settings_layout.dart deleted file mode 100644 index 56dbdbc1..00000000 --- a/lib/presentation/settings/settings_layout.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; - -import '../themes/constants.dart'; - -class SettingsLayout extends StatelessWidget { - const SettingsLayout({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: kSecondaryColor, - leading: RawMaterialButton( - elevation: 5, - onPressed: () => context.router.pop(), - child: const CircleAvatar( - backgroundColor: kSecondaryColor, - child: Icon( - Icons.arrow_back_ios_new_outlined, - color: kPrimaryColor300, - ), - ), - ), - actions: [ - ElevatedButton( - style: ButtonStyle( - padding: MaterialStateProperty.all(const EdgeInsets.all(8)), - backgroundColor: MaterialStateProperty.all(kSecondaryColor), - elevation: MaterialStateProperty.all(2), - ), - onPressed: () => context.router.pop(), - child: const CircleAvatar( - backgroundColor: kSecondaryColor, - child: Icon( - Icons.close_outlined, - color: kPrimaryColor300, - ), - ), - ) - ], - ), - ); - } -} diff --git a/lib/presentation/settings/settings_screen.dart b/lib/presentation/settings/settings_screen.dart deleted file mode 100644 index 1689e386..00000000 --- a/lib/presentation/settings/settings_screen.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import '/application/settings/build_information/build_information_bloc.dart'; -import '../../../presentation/utils/launch_url.dart'; -import '../../application/auth/auth_bloc.dart'; -import '../../application/user/profile/profile_bloc.dart'; -import '../../infrastructure/core/injection.dart'; -import '../core/collaction_icons.dart'; -import '../routes/app_routes.gr.dart'; -import '../shared_widgets/custom_app_bars/custom_appbar.dart'; -import '../themes/constants.dart'; -import 'widgets/build_information_tile.dart'; -import 'widgets/settings_list_tile.dart'; -import 'widgets/share_collaction_list_tile.dart'; - -class SettingsPage extends StatelessWidget { - const SettingsPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: const CustomAppBar(closable: true), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - children: [ - const ShareCollactionListTile(), - const SizedBox(height: 15), - SettingsListTile( - title: 'Contact us', - icon: CollactionIcons.message, - trailingIcon: CollactionIcons.arrow_right, - onTap: () => - context.router.push(const ContactFormRoute()), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Onboarding', - icon: CollactionIcons.rocket, - trailingIcon: CollactionIcons.arrow_right, - onTap: () => - context.router.push(const OnboardingRoute()), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Open source libraries', - icon: CollactionIcons.opensource, - trailingIcon: CollactionIcons.arrow_right, - onTap: () => - context.router.push(const LicensesRoute()), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Terms of use', - icon: CollactionIcons.lock, - trailingIcon: CollactionIcons.external_link, - onTap: () => launchUrl( - 'https://www.collaction.org/terms', - useWebView: true, - context: context, - ), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Privacy policy', - icon: CollactionIcons.file, - trailingIcon: CollactionIcons.external_link, - onTap: () => launchUrl( - 'https://www.collaction.org/privacy', - useWebView: true, - context: context, - ), - ), - BlocBuilder( - bloc: BlocProvider.of(context), - builder: (context, ProfileState state) => state - .userProfile == - null - ? const SizedBox() - : Column( - children: [ - const SizedBox(height: 15), - SettingsListTile( - title: 'Log out', - icon: CollactionIcons.logout, - iconColor: kErrorColor, - onTap: () async { - BlocProvider.of(context) - .add(const AuthEvent.signedOut()); - BlocProvider.of(context) - .add(GetUserProfile()); - await context.router.pop(); - }, - ), - ], - ), - ), - BlocBuilder( - bloc: getIt() - ..add(const BuildInformationEvent.fetch()), - builder: (context, state) { - return state.when( - loading: () => const SizedBox(), - fetched: (buildInfo) => - BuildInformationTile(information: buildInfo), - ); - }, - ), - ], - ), - ], - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/presentation/settings/widgets/settings_list_tile.dart b/lib/presentation/settings/widgets/settings_list_tile.dart deleted file mode 100644 index 4f9e1307..00000000 --- a/lib/presentation/settings/widgets/settings_list_tile.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; -import '../../themes/constants.dart'; - -class SettingsListTile extends StatelessWidget { - final String title; - final IconData icon; - final Color iconColor; - final Function() onTap; - final IconData? trailingIcon; - - const SettingsListTile({ - super.key, - required this.title, - required this.icon, - required this.onTap, - this.iconColor = kPrimaryColor300, - this.trailingIcon, - }); - - @override - Widget build(BuildContext context) { - return ListTile( - onTap: onTap, - contentPadding: const EdgeInsets.symmetric( - vertical: 15, - horizontal: 20, - ), - tileColor: kAlmostTransparent, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - leading: CircleAvatar( - radius: 32.5, - backgroundColor: kSecondaryColor, - child: Icon( - icon, - color: iconColor, - ), - ), - title: Text(title), - trailing: trailingIcon != null ? Icon(trailingIcon) : null, - ); - } -} diff --git a/lib/presentation/settings/widgets/share_collaction_list_tile.dart b/lib/presentation/settings/widgets/share_collaction_list_tile.dart deleted file mode 100644 index 3d3ef6ad..00000000 --- a/lib/presentation/settings/widgets/share_collaction_list_tile.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:share_plus/share_plus.dart'; - -import '../../core/collaction_icons.dart'; -import '../../themes/constants.dart'; -import '../../utils/strings.dart'; - -class ShareCollactionListTile extends StatefulWidget { - const ShareCollactionListTile({ - super.key, - String? shareText, - String? shareEmailSubject, - }) : _shareText = shareText, - _shareEmailSubject = shareEmailSubject; - - final String? _shareText; - final String? _shareEmailSubject; - - @override - State createState() => - ShareCollactionListTileState(); -} - -class ShareCollactionListTileState extends State { - late bool _isClicked; - - void onFocusChange(bool focused) { - setState(() { - _isClicked = focused == false; - }); - } - - Future _clickCallback() async { - setState(() { - _isClicked = true; - }); - - Share.share( - widget._shareText ?? defaultShareText, - subject: widget._shareEmailSubject ?? defaultShareEmailSubject, - ); - await Future.delayed(const Duration(seconds: 1)); - - setState(() { - _isClicked = false; - }); - } - - @override - void initState() { - super.initState(); - _isClicked = false; - } - - @override - Widget build(BuildContext context) { - return Focus( - onFocusChange: onFocusChange, - child: ListTile( - enabled: !_isClicked, - onTap: _clickCallback, - contentPadding: const EdgeInsets.symmetric( - vertical: 15, - horizontal: 20, - ), - tileColor: kAlmostTransparent, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - leading: const CircleAvatar( - radius: 32.5, - backgroundColor: kSecondaryColor, - child: Icon( - CollactionIcons.share, - color: kPrimaryColor300, - ), - ), - title: const Text( - 'Share CollAction', - ), - trailing: const Icon(CollactionIcons.arrow_right), - ), - ); - } -} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index a5c1c5e5..91bf5ac3 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -25,7 +25,6 @@ const Color kPrimaryColor300 = Color(0xFF666666); const Color kPrimaryColor400 = Color(0xFF333333); const Color kPrimaryColor500 = Color(0xFF000000); const Color kPrimaryColor600 = Color(0xFF2EB494); - const TextStyle kCaption1 = TextStyle( fontSize: 12, height: 16 / 12, @@ -55,11 +54,6 @@ const TextStyle phoneNumberTextStyle = TextStyle( color: kPrimaryColor300 , ); -const TextStyle appInfo = TextStyle( -fontSize: 17, -fontWeight: FontWeight.w300, - color: kPrimaryColor200 , -); const BoxDecoration avatarInfoDecorationBox = BoxDecoration( From b77f84cd7195ee14a82be226dc047a020a7dbf5d Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Tue, 14 Feb 2023 19:47:54 +0200 Subject: [PATCH 04/19] Solving the the inconsistencies. --- assets/images/build_info.png | Bin 14107 -> 0 bytes lib/infrastructure/core/injection.dart | 1 + lib/main.dart | 2 +- lib/presentation/menu/menu_screen.dart | 91 ++++-------------- .../menu/widgets/avatar_info.dart | 40 ++++---- lib/presentation/menu/widgets/header_bar.dart | 32 ++++++ .../widgets/legal_info_policy_widget.dart | 13 +-- .../menu/widgets/user_info_and_avatar.dart | 55 +++++++++++ lib/presentation/themes/constants.dart | 17 ++-- pubspec.lock | 77 ++++++++------- pubspec.yaml | 5 +- 11 files changed, 180 insertions(+), 153 deletions(-) delete mode 100644 assets/images/build_info.png create mode 100644 lib/presentation/menu/widgets/header_bar.dart create mode 100644 lib/presentation/menu/widgets/user_info_and_avatar.dart diff --git a/assets/images/build_info.png b/assets/images/build_info.png deleted file mode 100644 index c362d5b49cfa7e1fc8a18b98557b749a66cb13b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14107 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 bMiqbv`2$U}ob=x>8<>oQf_Sy4QPBSZ`FR&q diff --git a/lib/infrastructure/core/injection.dart b/lib/infrastructure/core/injection.dart index 98ad4f10..535b983b 100644 --- a/lib/infrastructure/core/injection.dart +++ b/lib/infrastructure/core/injection.dart @@ -8,4 +8,5 @@ final GetIt getIt = GetIt.instance; @injectableInit void configureInjection() { getIt.init(); + } diff --git a/lib/main.dart b/lib/main.dart index c2e64a11..90f5bafc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index 6b42ea13..61320857 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -9,19 +9,16 @@ import '../../infrastructure/core/injection.dart'; import '../routes/app_routes.gr.dart'; import '../utils/launch_url.dart'; import 'widgets/avatar_info.dart'; +import 'widgets/header_bar.dart'; import 'widgets/legal_info_policy_widget.dart'; import 'package:flutter/material.dart'; import '../themes/constants.dart'; import '../core/collaction_icons.dart'; +import 'widgets/user_info_and_avatar.dart'; -class MenuPage extends StatefulWidget { +class MenuPage extends StatelessWidget { const MenuPage({Key? key}) : super(key: key); - @override - State createState() => _MenuTabState(); -} - -class _MenuTabState extends State { @override Widget build(BuildContext context) { return Scaffold( @@ -39,69 +36,14 @@ class _MenuTabState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - "Menu", - style: TextStyle( - fontSize: 28, - fontFamily: "Rubik", - fontWeight: FontWeight.w700, - ), - ), - IconButton( - onPressed: () {}, - icon: Icon( - Icons.search, - color: kPrimaryColor600, - size: 21.08, - ), - ), - ], + HeaderBar(), + UserInfoAndAvatar( + pictureUrl: state.userProfile?.profile.avatar, + name: state.userProfile?.profile.firstName, ), SizedBox( height: 30, ), - Container( - height: 85, - decoration: avatarInfoDecorationBox, - child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AvatarAndInfo( - pictureUrl: state.userProfile?.profile.avatar, - name: state.userProfile?.profile.firstName, - ), - GestureDetector( - onTap: () { - }, - child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), - ), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle), - ), - ), - ], - ), - ), - ), SizedBox( height: 18, ), @@ -127,7 +69,6 @@ class _MenuTabState extends State { "Log out", style: TextStyle( color: kErrorColor, - fontFamily: "Rubik", fontSize: 15, fontWeight: FontWeight.w700, ), @@ -139,7 +80,10 @@ class _MenuTabState extends State { ), ), _buildSubTitle( - subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), + subTitle: "Account", + paddingTop: 38.5, + paddingBottom: 20, + ), Padding( padding: const EdgeInsets.only(left: 22.25), child: GestureDetector( @@ -261,8 +205,7 @@ class _MenuTabState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - BlocBuilder( + BlocBuilder( bloc: getIt() ..add(const BuildInformationEvent.fetch()), builder: (context, state) { @@ -273,7 +216,6 @@ class _MenuTabState extends State { ); }, ), - ], ) ], @@ -285,10 +227,11 @@ class _MenuTabState extends State { ); } - Widget _buildSubTitle( - {required String subTitle, - double paddingTop = 0.0, - double paddingBottom = 0.0}) { + Widget _buildSubTitle({ + required String subTitle, + double paddingTop = 0.0, + double paddingBottom = 0.0, + }) { return Padding( padding: EdgeInsets.only(left: 20, top: paddingTop, bottom: paddingBottom), diff --git a/lib/presentation/menu/widgets/avatar_info.dart b/lib/presentation/menu/widgets/avatar_info.dart index 4c128270..e93319eb 100644 --- a/lib/presentation/menu/widgets/avatar_info.dart +++ b/lib/presentation/menu/widgets/avatar_info.dart @@ -1,4 +1,3 @@ - import 'dart:io'; import 'package:flutter/material.dart'; @@ -14,12 +13,11 @@ class AvatarAndInfo extends StatefulWidget { final String? pictureUrl; final String? name; - const AvatarAndInfo( - {Key? key, - required this.pictureUrl, - required this.name, - }) - : super(key: key); + const AvatarAndInfo({ + Key? key, + required this.pictureUrl, + required this.name, + }) : super(key: key); @override State createState() => _AvatarAndInfoState(); @@ -28,25 +26,22 @@ class AvatarAndInfo extends StatefulWidget { class _AvatarAndInfoState extends State { late final IUserRepository _userRepository; File? _image; + late String number; + @override void initState() { super.initState(); _userRepository = getIt(); } + @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // ProfilePicture( - // maxRadius: 40, - // profileImage: - // '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}', - // ), ProfilePicture( image: _image, - profileImage: widget.pictureUrl != - null + profileImage: widget.pictureUrl != null ? '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}' : null, maxRadius: 50, @@ -62,19 +57,18 @@ class _AvatarAndInfoState extends State { widget.name ?? "", style: nameTextStyle, ), - StreamBuilder(builder: (context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - final number = snapshot.data!.phoneNumber ?? 'no phone number'; + StreamBuilder( + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + number = snapshot.data!.phoneNumber ?? 'no phone number'; + } return Text( number, style: phoneNumberTextStyle, ); - } else { - return const Text('...'); - } - - },stream: _userRepository.observeUser() - ,), + }, + stream: _userRepository.observeUser(), + ), ], ) ], diff --git a/lib/presentation/menu/widgets/header_bar.dart b/lib/presentation/menu/widgets/header_bar.dart new file mode 100644 index 00000000..f6a0bdd1 --- /dev/null +++ b/lib/presentation/menu/widgets/header_bar.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; + +class HeaderBar extends StatelessWidget { + const HeaderBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.w700, + ), + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/menu/widgets/legal_info_policy_widget.dart b/lib/presentation/menu/widgets/legal_info_policy_widget.dart index c5ed05a7..9cb21908 100644 --- a/lib/presentation/menu/widgets/legal_info_policy_widget.dart +++ b/lib/presentation/menu/widgets/legal_info_policy_widget.dart @@ -1,18 +1,17 @@ - import 'package:flutter/material.dart'; import '../../themes/constants.dart'; class LegalInfoAndPoliciesWidget extends StatefulWidget { - final onTap; + final Function onTap; final IconData iconWidget; final String label; const LegalInfoAndPoliciesWidget( {Key? key, - required this.onTap, - required this.iconWidget, - required this.label}) + required this.onTap, + required this.iconWidget, + required this.label}) : super(key: key); @override @@ -27,9 +26,7 @@ class _LegalInfoAndPoliciesWidgetState return Padding( padding: const EdgeInsets.only(left: 20, bottom: 27.6), child: InkWell( - onTap:(){ - widget.onTap(); - }, + onTap: () => widget.onTap(), child: Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/presentation/menu/widgets/user_info_and_avatar.dart b/lib/presentation/menu/widgets/user_info_and_avatar.dart new file mode 100644 index 00000000..eeb1ddf5 --- /dev/null +++ b/lib/presentation/menu/widgets/user_info_and_avatar.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; +import 'avatar_info.dart'; + +class UserInfoAndAvatar extends StatelessWidget { + final String? pictureUrl; + + final String? name; + + const UserInfoAndAvatar({Key? key, this.pictureUrl, this.name}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: pictureUrl, + name: name, + ), + GestureDetector( + onTap: () {}, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index 91bf5ac3..656fae5c 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -25,6 +25,7 @@ const Color kPrimaryColor300 = Color(0xFF666666); const Color kPrimaryColor400 = Color(0xFF333333); const Color kPrimaryColor500 = Color(0xFF000000); const Color kPrimaryColor600 = Color(0xFF2EB494); + const TextStyle kCaption1 = TextStyle( fontSize: 12, height: 16 / 12, @@ -43,20 +44,20 @@ const TextStyle kTitle1 = TextStyle( ); const TextStyle nameTextStyle = TextStyle( - fontSize: 17 , - fontWeight: FontWeight.w500 , - color: kPrimaryColor400 , + fontSize: 17, + fontWeight: FontWeight.w500, + color: kPrimaryColor400, ); const TextStyle phoneNumberTextStyle = TextStyle( fontSize: 17, fontWeight: FontWeight.w300, - color: kPrimaryColor300 , + color: kPrimaryColor300, ); - - const BoxDecoration avatarInfoDecorationBox = BoxDecoration( - color: kAlmostTransparent , - borderRadius: BorderRadius.all(Radius.circular(20),) + color: kAlmostTransparent, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), ); diff --git a/pubspec.lock b/pubspec.lock index 04868a93..169ea84c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -14,7 +14,7 @@ packages: name: _flutterfire_internals url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.13" analyzer: dependency: transitive description: @@ -183,20 +183,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" - cloud_firestore_platform_interface: - dependency: transitive - description: - name: cloud_firestore_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "5.7.7" - cloud_firestore_web: - dependency: transitive - description: - name: cloud_firestore_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.10" code_builder: dependency: transitive description: @@ -350,63 +336,63 @@ packages: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "3.11.2" + version: "4.2.2" firebase_auth_mocks: dependency: "direct dev" description: name: firebase_auth_mocks url: "https://pub.dartlang.org" source: hosted - version: "0.8.6" + version: "0.10.3" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "6.10.1" + version: "6.11.8" firebase_auth_web: dependency: transitive description: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "4.6.1" + version: "5.2.2" firebase_core: dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "1.24.0" + version: "2.5.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.5.1" + version: "4.5.3" firebase_core_web: dependency: transitive description: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "1.7.3" + version: "2.1.1" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics url: "https://pub.dartlang.org" source: hosted - version: "2.9.0" + version: "3.0.12" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.3.0" + version: "3.3.12" fixnum: dependency: transitive description: @@ -453,7 +439,7 @@ packages: name: flutter_launcher_icons url: "https://pub.dartlang.org" source: hosted - version: "0.10.0" + version: "0.11.0" flutter_lints: dependency: "direct dev" description: @@ -631,21 +617,21 @@ packages: name: injectable url: "https://pub.dartlang.org" source: hosted - version: "1.5.3" + version: "2.1.0" injectable_generator: dependency: "direct dev" description: name: injectable_generator url: "https://pub.dartlang.org" source: hosted - version: "1.5.4" + version: "2.1.4" intl: dependency: "direct main" description: name: intl url: "https://pub.dartlang.org" source: hosted - version: "0.17.0" + version: "0.18.0" io: dependency: transitive description: @@ -687,7 +673,7 @@ packages: name: lint url: "https://pub.dartlang.org" source: hosted - version: "1.10.0" + version: "2.0.1" lints: dependency: transitive description: @@ -730,6 +716,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + mock_exceptions: + dependency: transitive + description: + name: mock_exceptions + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.2" mocktail: dependency: "direct main" description: @@ -912,13 +905,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.1" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" rive: dependency: "direct main" description: name: rive url: "https://pub.dartlang.org" source: hosted - version: "0.9.1" + version: "0.10.1" + rive_common: + dependency: transitive + description: + name: rive_common + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2" rxdart: dependency: "direct main" description: @@ -1273,28 +1280,28 @@ packages: name: webview_flutter url: "https://pub.dartlang.org" source: hosted - version: "3.0.4" + version: "4.0.2" webview_flutter_android: dependency: transitive description: name: webview_flutter_android url: "https://pub.dartlang.org" source: hosted - version: "2.10.4" + version: "3.2.4" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.9.5" + version: "2.0.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview url: "https://pub.dartlang.org" source: hosted - version: "2.9.5" + version: "3.0.5" widgetbook: dependency: "direct dev" description: @@ -1352,5 +1359,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.18.2 <3.0.0" + dart: ">=2.18.6 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index afdedda6..eeaba32b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,7 +39,6 @@ dependencies: flutter_bloc: ^8.1.1 flutter_dotenv: ^5.0.2 freezed_annotation: ^2.2.0 - fvm: ^2.4.1 get_it: ^7.2.0 http: ^0.13.5 image: ^3.2.2 @@ -78,8 +77,6 @@ dev_dependencies: lint: ^2.0.1 widgetbook: ^2.4.1 widgetbook_generator: ^2.4.1 -dependency_overrides: - firebase_core_platform_interface: 4.5.1 flutter_icons: android: true @@ -113,4 +110,4 @@ flutter: - asset: assets/fonts/Rubik/Rubik-Medium.ttf weight: 400 - asset: assets/fonts/Rubik/Rubik-Light.ttf - weight: 300 + weight: 300 \ No newline at end of file From 7ddabec577fe61577a001b0982368a5c92563d3d Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Tue, 14 Feb 2023 19:50:38 +0200 Subject: [PATCH 05/19] Solving the the inconsistencies. --- lib/infrastructure/core/injection.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/infrastructure/core/injection.dart b/lib/infrastructure/core/injection.dart index 535b983b..98ad4f10 100644 --- a/lib/infrastructure/core/injection.dart +++ b/lib/infrastructure/core/injection.dart @@ -8,5 +8,4 @@ final GetIt getIt = GetIt.instance; @injectableInit void configureInjection() { getIt.init(); - } From cf9b0b0256c06b59a639a8f916464963ee81363d Mon Sep 17 00:00:00 2001 From: Mathias Mogensencd collaction_website Date: Sat, 4 Mar 2023 19:48:24 +0100 Subject: [PATCH 06/19] fix: add manual logging to auth repo --- .../auth/firebase_auth_repository.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/infrastructure/auth/firebase_auth_repository.dart b/lib/infrastructure/auth/firebase_auth_repository.dart index 0ec66fc7..42283e39 100644 --- a/lib/infrastructure/auth/firebase_auth_repository.dart +++ b/lib/infrastructure/auth/firebase_auth_repository.dart @@ -54,6 +54,13 @@ class FirebaseAuthRepository implements IAuthRepository, Disposable { result.add(right(AuthSuccess.codeSent(credential: credential))); }, verificationFailed: (firebase_auth.FirebaseAuthException error) { + FirebaseCrashlyticsLogger.warn( + error, + null, + message: + '[FirebaseAuthRepository] verifyPhoneNumber().verificationFailed', + ); + result.add(left(error.toFailure())); result.close(); }, @@ -166,6 +173,12 @@ class FirebaseAuthRepository implements IAuthRepository, Disposable { result.add(right(AuthSuccess.codeSent(credential: credential))); }, verificationFailed: (firebase_auth.FirebaseAuthException error) { + FirebaseCrashlyticsLogger.warn( + error, + null, + message: '[FirebaseAuthRepository] resendOTP().verificationFailed', + ); + result.add(left(error.toFailure())); result.close(); }, From 8d903e32ec65428f121a59f6931721f04959e96b Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sat, 4 Mar 2023 21:09:30 +0200 Subject: [PATCH 07/19] Deleting settings folder at the testing part --- .env.example | 5 - lib/application/auth/auth_bloc.dart | 2 + lib/presentation/demo/demo_screen.dart | 1 + lib/presentation/home/home_screen.dart | 6 +- lib/presentation/routes/app_routes.dart | 6 +- .../build_information_tile_test.dart | 2 +- .../settings/settings_layout_test.dart | 45 --- .../settings/settings_layout_test.ext.dart | 15 - .../settings/settings_list_tile_test.dart | 28 -- .../settings/settings_screen_test.dart | 262 ------------------ .../settings/settings_screen_test.ext.dart | 25 -- .../share_collaction_list_tile_test.dart | 40 --- 12 files changed, 9 insertions(+), 428 deletions(-) delete mode 100644 .env.example rename test/presentation/{settings => menu}/build_information_tile_test.dart (93%) delete mode 100644 test/presentation/settings/settings_layout_test.dart delete mode 100644 test/presentation/settings/settings_layout_test.ext.dart delete mode 100644 test/presentation/settings/settings_list_tile_test.dart delete mode 100644 test/presentation/settings/settings_screen_test.dart delete mode 100644 test/presentation/settings/settings_screen_test.ext.dart delete mode 100644 test/presentation/settings/share_collaction_list_tile_test.dart diff --git a/.env.example b/.env.example deleted file mode 100644 index 4bf673e2..00000000 --- a/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -ENV = development - -# Full base URL including protocol (http or https), host and optionally the port and the base api path without trailing forward slash -BASE_API_ENDPOINT_URL = -BASE_STATIC_ENDPOINT_URL = diff --git a/lib/application/auth/auth_bloc.dart b/lib/application/auth/auth_bloc.dart index 973fd1bf..67a74711 100644 --- a/lib/application/auth/auth_bloc.dart +++ b/lib/application/auth/auth_bloc.dart @@ -14,7 +14,9 @@ import '../../domain/user/i_user_repository.dart'; import '../../domain/user/user.dart'; part 'auth_bloc.freezed.dart'; + part 'auth_event.dart'; + part 'auth_state.dart'; @injectable diff --git a/lib/presentation/demo/demo_screen.dart b/lib/presentation/demo/demo_screen.dart index 26412a7f..9188a681 100644 --- a/lib/presentation/demo/demo_screen.dart +++ b/lib/presentation/demo/demo_screen.dart @@ -9,6 +9,7 @@ import 'components_demo/current_user_status_text.dart'; class DemoPage extends StatelessWidget { DemoPage({super.key}); + final settingsRepository = getIt(); final _pageScrollController = ScrollController(); diff --git a/lib/presentation/home/home_screen.dart b/lib/presentation/home/home_screen.dart index 69e01b7f..ba4cdac5 100644 --- a/lib/presentation/home/home_screen.dart +++ b/lib/presentation/home/home_screen.dart @@ -56,7 +56,7 @@ class HomePageState extends State { unselectedItemColor: kDisabledButtonColor, type: BottomNavigationBarType.fixed, elevation: 0, - items: [ + items: [ BottomNavigationBarItem( icon: Icon(CollactionIcons.collaction), label: '', @@ -74,7 +74,9 @@ class HomePageState extends State { ), ], BottomNavigationBarItem( - icon: Icon(Icons.grid_view,), + icon: Icon( + Icons.grid_view, + ), label: '', ), ], diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index a5b7f294..e07554de 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -67,11 +67,7 @@ import '../shared_widgets/web_view_page.dart'; path: 'menu', name: 'MenuScreenRouter', page: EmptyRouterPage, - children: [ - AutoRoute( - path: '' , page: MenuPage - ) - ], + children: [AutoRoute(path: '', page: MenuPage)], ), ], ), diff --git a/test/presentation/settings/build_information_tile_test.dart b/test/presentation/menu/build_information_tile_test.dart similarity index 93% rename from test/presentation/settings/build_information_tile_test.dart rename to test/presentation/menu/build_information_tile_test.dart index b9d4b315..38b45191 100644 --- a/test/presentation/settings/build_information_tile_test.dart +++ b/test/presentation/menu/build_information_tile_test.dart @@ -1,5 +1,5 @@ import 'package:collaction_app/domain/settings/build_information.dart'; -import 'package:collaction_app/presentation/settings/widgets/build_information_tile.dart'; +import 'package:collaction_app/presentation/menu/widgets/build_information_tile.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../test_helper.dart'; diff --git a/test/presentation/settings/settings_layout_test.dart b/test/presentation/settings/settings_layout_test.dart deleted file mode 100644 index bdf4dfe0..00000000 --- a/test/presentation/settings/settings_layout_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:collaction_app/presentation/settings/settings_layout.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mocktail/mocktail.dart'; - -import '../router.mocks.dart'; - -part 'settings_layout_test.ext.dart'; - -void main() { - late StackRouter stackRouter; - - setUpAll(() { - stackRouter = RouteHelpers.setUpRouterStubs(); - }); - - group('SettingsLayout tests:', () { - testWidgets('can render', (WidgetTester tester) async { - await tester.pumpSettingsLayout(stackRouter); - await tester.pumpAndSettle(); - - expect(find.byType(SettingsLayout), findsOneWidget); - }); - - testWidgets('back ElevatedButton works', (WidgetTester tester) async { - await tester.pumpSettingsLayout(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.byType(ElevatedButton)); - final capturedPops = verify(() => stackRouter.pop()).callCount; - - expect(capturedPops, 1); - }); - - testWidgets('back RawMaterialButton works', (WidgetTester tester) async { - await tester.pumpSettingsLayout(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.byType(RawMaterialButton)); - final capturedPops = verify(() => stackRouter.pop()); - expect(capturedPops.callCount, 1); - }); - }); -} diff --git a/test/presentation/settings/settings_layout_test.ext.dart b/test/presentation/settings/settings_layout_test.ext.dart deleted file mode 100644 index 3998c210..00000000 --- a/test/presentation/settings/settings_layout_test.ext.dart +++ /dev/null @@ -1,15 +0,0 @@ -part of 'settings_layout_test.dart'; - -extension WidgetX on WidgetTester { - Future pumpSettingsLayout([ - StackRouter? stackRouter, - ]) async { - await pumpWidget( - MaterialApp( - home: Scaffold( - body: SettingsLayout(), - ), - ).withRouterScope(stackRouter), - ); - } -} diff --git a/test/presentation/settings/settings_list_tile_test.dart b/test/presentation/settings/settings_list_tile_test.dart deleted file mode 100644 index 0a5db946..00000000 --- a/test/presentation/settings/settings_list_tile_test.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:collaction_app/presentation/settings/widgets/settings_list_tile.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../../test_helper.dart'; - -void main() { - group('SettingsListTile tests', () { - testWidgets('onTap', (WidgetTester tester) async { - int counter = 0; - - await buildAndPump( - tester: tester, - widget: SettingsListTile( - title: 'title', - icon: Icons.abc, - onTap: () => counter++, - ), - ); - - await tester.pumpAndSettle(); - - expect(counter, 0); - await tester.tap(find.byType(SettingsListTile)); - expect(counter, 1); - }); - }); -} diff --git a/test/presentation/settings/settings_screen_test.dart b/test/presentation/settings/settings_screen_test.dart deleted file mode 100644 index 6e87405a..00000000 --- a/test/presentation/settings/settings_screen_test.dart +++ /dev/null @@ -1,262 +0,0 @@ -import 'dart:io'; - -import 'package:auto_route/auto_route.dart'; -import 'package:collaction_app/application/auth/auth_bloc.dart'; -import 'package:collaction_app/application/settings/build_information/build_information_bloc.dart'; -import 'package:collaction_app/application/user/profile/profile_bloc.dart'; -import 'package:collaction_app/domain/settings/build_information.dart'; -import 'package:collaction_app/infrastructure/core/injection.dart'; -import 'package:collaction_app/presentation/routes/app_routes.gr.dart'; -import 'package:collaction_app/presentation/settings/settings_screen.dart'; -import 'package:collaction_app/presentation/settings/widgets/build_information_tile.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:get_it/get_it.dart'; -import 'package:mocktail/mocktail.dart'; - -import '../../application/auth/auth_bloc.mocks.dart'; -import '../../application/settings/build_information_bloc.mocks.dart'; -import '../../application/user/profile/profile_bloc.mocks.dart'; -import '../../utils/user.fixtures.dart'; -import '../router.mocks.dart'; - -part 'settings_screen_test.ext.dart'; - -void main() { - late StackRouter stackRouter; - late AuthBloc authBloc; - late ProfileBloc profileBloc; - late BuildInformationBloc buildInformationBloc; - - final channels = [ - MethodChannel( - Platform.isLinux - ? 'plugins.flutter.io/url_launcher_linux' - : Platform.isWindows - ? 'plugins.flutter.io/url_launcher_windows' - : 'plugins.flutter.io/url_launcher_macos', - ), - MethodChannel('plugins.flutter.io/url_launcher') - ]; - - setUp(() async { - for (final channel in channels) { - channel.setMockMethodCallHandler((MethodCall methodCall) async { - return methodCall.method == 'canLaunch' ? true : null; - }); - } - }); - - tearDown(() { - for (final channel in channels) { - channel.setMockMethodCallHandler(null); - } - }); - - setUpAll(() { - stackRouter = RouteHelpers.setUpRouterStubs(); - - // Auth Bloc - authBloc = MockAuthBloc(); - when(() => authBloc.state).thenAnswer((_) => AuthState.initial()); - GetIt.I.registerSingleton(authBloc); - - // Profile Bloc - profileBloc = MockProfileBloc(); - when(() => profileBloc.state).thenAnswer((_) => ProfileState.initial()); - GetIt.I.registerSingleton(profileBloc); - registerFallbackValue(GetUserProfile()); - - // Build Information Bloc - buildInformationBloc = MockBuildInformationBloc(); - when(() => buildInformationBloc.state).thenAnswer( - (_) => BuildInformationState.fetched( - BuildInformation( - buildNumber: 'tBuildNumber', - version: 'tVersion', - ), - ), - ); - GetIt.I.registerSingleton(buildInformationBloc); - }); - - tearDownAll(() { - GetIt.I.unregister(); - GetIt.I.unregister(); - GetIt.I.unregister(); - }); - - group('SettingsPage tests:', () { - testWidgets('can render', (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect(find.byType(SettingsPage), findsOneWidget); - }); - - testWidgets('onTap, "Contact Us" button routes to ContactForm', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.text('Contact us')); - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - }); - - testWidgets('onTap, "Onboarding" button routes to Onboarding', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.text('Onboarding')); - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - }); - - testWidgets('onTap, "Open source libraries" button routes to Licenses', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.text('Open source libraries')); - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - }); - - testWidgets('onTap, "Terms of use" button opens terms webpage', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.runAsync(() async { - await tester.tap(find.text('Terms of use')); - await tester.pumpAndSettle(); - }); - - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - - final route = capturedRoutes.first as WebViewRoute; - expect(route.args?.url, 'https://www.collaction.org/terms'); - }); - - testWidgets('onTap, "Privacy policy" button opens privacy webpage', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.runAsync(() async { - await tester.scrollUntilVisible( - find.text( - 'Privacy policy', - skipOffstage: false, - ), - 15, - ); - await tester.tap(find.text('Privacy policy')); - await tester.pumpAndSettle(); - }); - - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - - final route = capturedRoutes.first as WebViewRoute; - expect(route.args?.url, 'https://www.collaction.org/privacy'); - }); - - testWidgets('"Log out" button not available when not logged in', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect( - find.text( - 'Log out', - skipOffstage: false, - ), - findsNothing, - ); - }); - - testWidgets('onTap, "Log out" button starts logout event', - (WidgetTester tester) async { - when(() => profileBloc.state) - .thenAnswer((_) => ProfileState(userProfile: testUserProfile)); - - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.scrollUntilVisible( - find.text( - 'Log out', - skipOffstage: false, - ), - 15, - ); - await tester.tap(find.text('Log out')); - - final capturedPops = verify(() => stackRouter.pop()); - expect(capturedPops.callCount, 1); - - verify(() => authBloc.add(AuthEvent.signedOut())); - - final profileEvents = verify(() => profileBloc.add(any())); - expect(profileEvents.callCount, 1); - }); - - testWidgets('BuildInformationTile renders when fetched', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect( - find.byType( - BuildInformationTile, - skipOffstage: false, - ), - findsOneWidget, - ); - }); - - testWidgets('BuildInformationTile does not render when loading', - (WidgetTester tester) async { - when(() => buildInformationBloc.state).thenAnswer( - (_) => BuildInformationState.loading(), - ); - - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect( - find.byType( - BuildInformationTile, - skipOffstage: false, - ), - findsNothing, - ); - }); - }); -} diff --git a/test/presentation/settings/settings_screen_test.ext.dart b/test/presentation/settings/settings_screen_test.ext.dart deleted file mode 100644 index ff0d65bf..00000000 --- a/test/presentation/settings/settings_screen_test.ext.dart +++ /dev/null @@ -1,25 +0,0 @@ -part of 'settings_screen_test.dart'; - -extension WidgetX on WidgetTester { - Future pumpSettingsPage([ - StackRouter? stackRouter, - ]) async { - await pumpWidget( - MaterialApp( - home: Scaffold( - body: MultiBlocProvider( - providers: [ - BlocProvider( - create: (_) => getIt(), - ), - BlocProvider( - create: (_) => getIt(), - ), - ], - child: SettingsPage(), - ), - ), - ).withRouterScope(stackRouter), - ); - } -} diff --git a/test/presentation/settings/share_collaction_list_tile_test.dart b/test/presentation/settings/share_collaction_list_tile_test.dart deleted file mode 100644 index 8febe882..00000000 --- a/test/presentation/settings/share_collaction_list_tile_test.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:collaction_app/presentation/settings/widgets/share_collaction_list_tile.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../../test_helper.dart'; - -void main() { - group('ShareCollActionListTile tests', () { - testWidgets('can render', (WidgetTester tester) async { - await buildAndPump(tester: tester, widget: ShareCollactionListTile()); - await tester.pumpAndSettle(); - - expect(find.byType(ShareCollactionListTile), findsOneWidget); - }); - - testWidgets('state', (WidgetTester tester) async { - await buildAndPump(tester: tester, widget: ShareCollactionListTile()); - await tester.pumpAndSettle(); - - expect(find.byType(ShareCollactionListTile), findsOneWidget); - - await tester.tap(find.byType(ShareCollactionListTile)); - await tester.pumpAndSettle(const Duration(seconds: 1)); - }); - - testWidgets('onFocusChange', (WidgetTester tester) async { - final ShareCollactionListTile shareCollactionButton = - ShareCollactionListTile(); - - await buildAndPump(tester: tester, widget: shareCollactionButton); - await tester.pumpAndSettle(); - - final state = tester.state( - find.byType(ShareCollactionListTile), - ); - - state.onFocusChange(true); - state.onFocusChange(false); - }); - }); -} From fa2d65089abff8fc36563596cf3ddd827b76bd20 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sat, 4 Mar 2023 22:26:30 +0200 Subject: [PATCH 08/19] Deleting settings folder at the testing part --- pubspec.lock | 208 +++++++++++++++++++++++++-------------------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 169ea84c..dc655a1d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -14,7 +14,14 @@ packages: name: _flutterfire_internals url: "https://pub.dartlang.org" source: hosted - version: "1.0.13" + version: "1.0.16" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" analyzer: dependency: transitive description: @@ -28,14 +35,14 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.3.2" + version: "3.3.6" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.1" + version: "2.4.0" async: dependency: transitive description: @@ -49,7 +56,7 @@ packages: name: auto_route url: "https://pub.dartlang.org" source: hosted - version: "5.0.2" + version: "5.0.4" auto_route_generator: dependency: "direct dev" description: @@ -63,14 +70,14 @@ packages: name: bloc url: "https://pub.dartlang.org" source: hosted - version: "8.1.0" + version: "8.1.1" bloc_test: dependency: "direct dev" description: name: bloc_test url: "https://pub.dartlang.org" source: hosted - version: "9.1.0" + version: "9.1.1" boolean_selector: dependency: transitive description: @@ -98,7 +105,7 @@ packages: name: build_daemon url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" build_resolvers: dependency: transitive description: @@ -119,7 +126,7 @@ packages: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "7.2.6" + version: "7.2.7" built_collection: dependency: transitive description: @@ -133,14 +140,14 @@ packages: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.4.1" + version: "8.4.4" cached_network_image: dependency: "direct main" description: name: cached_network_image url: "https://pub.dartlang.org" source: hosted - version: "3.2.2" + version: "3.2.3" cached_network_image_platform_interface: dependency: transitive description: @@ -168,7 +175,7 @@ packages: name: checked_yaml url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" cli_util: dependency: transitive description: @@ -189,7 +196,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "4.3.0" + version: "4.4.0" collection: dependency: transitive description: @@ -224,14 +231,14 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "1.3.2" + version: "1.6.3" cross_file: dependency: transitive description: name: cross_file url: "https://pub.dartlang.org" source: hosted - version: "0.3.3+2" + version: "0.3.3+4" crypto: dependency: transitive description: @@ -245,7 +252,7 @@ packages: name: dart_jsonwebtoken url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.7.1" dart_pubspec_licenses: dependency: transitive description: @@ -288,6 +295,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + ed25519_edwards: + dependency: transitive + description: + name: ed25519_edwards + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1" email_validator: dependency: "direct main" description: @@ -350,7 +364,7 @@ packages: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "6.11.8" + version: "6.11.11" firebase_auth_web: dependency: transitive description: @@ -364,7 +378,7 @@ packages: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.7.0" firebase_core_platform_interface: dependency: transitive description: @@ -378,21 +392,21 @@ packages: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.2.1" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics url: "https://pub.dartlang.org" source: hosted - version: "3.0.12" + version: "3.0.15" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.3.12" + version: "3.3.15" fixnum: dependency: transitive description: @@ -411,7 +425,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "8.1.1" + version: "8.1.2" flutter_blurhash: dependency: transitive description: @@ -460,7 +474,7 @@ packages: name: flutter_plugin_android_lifecycle url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -505,7 +519,7 @@ packages: name: glob url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" go_router: dependency: transitive description: @@ -519,7 +533,7 @@ packages: name: graphs url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.0" http: dependency: "direct main" description: @@ -547,63 +561,63 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.2.2" + version: "3.3.0" image_cropper: dependency: "direct main" description: name: image_cropper url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" image_cropper_for_web: dependency: transitive description: name: image_cropper_for_web url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.3" image_cropper_platform_interface: dependency: transitive description: name: image_cropper_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.0.2" + version: "3.0.3" image_picker: dependency: "direct main" description: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.8.6" + version: "0.8.6+4" image_picker_android: dependency: transitive description: name: image_picker_android url: "https://pub.dartlang.org" source: hosted - version: "0.8.5+3" + version: "0.8.5+9" image_picker_for_web: dependency: transitive description: name: image_picker_for_web url: "https://pub.dartlang.org" source: hosted - version: "2.1.10" + version: "2.1.11" image_picker_ios: dependency: transitive description: name: image_picker_ios url: "https://pub.dartlang.org" source: hosted - version: "0.8.6+1" + version: "0.8.7" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.6.2" + version: "2.6.3" infinite_scroll_pagination: dependency: "direct main" description: @@ -638,14 +652,14 @@ packages: name: io url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" ionicons: dependency: "direct main" description: name: ionicons url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "0.2.2" js: dependency: transitive description: @@ -666,7 +680,7 @@ packages: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "6.5.3" + version: "6.5.4" lint: dependency: "direct dev" description: @@ -687,7 +701,7 @@ packages: name: logging url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" matcher: dependency: transitive description: @@ -715,7 +729,7 @@ packages: name: mime url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.4" mock_exceptions: dependency: transitive description: @@ -743,7 +757,7 @@ packages: name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" octo_image: dependency: transitive description: @@ -764,7 +778,7 @@ packages: name: package_info_plus url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.3" package_info_plus_platform_interface: dependency: transitive description: @@ -785,49 +799,42 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.13" path_provider_android: dependency: transitive description: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.20" - path_provider_ios: + version: "2.0.23" + path_provider_foundation: dependency: transitive description: - name: path_provider_ios + name: path_provider_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.1.2" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.6" + version: "2.1.9" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" pedantic: dependency: transitive description: @@ -841,7 +848,7 @@ packages: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "5.0.0" + version: "5.1.0" phone_number: dependency: "direct main" description: @@ -862,7 +869,7 @@ packages: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" pointycastle: dependency: transitive description: @@ -890,14 +897,14 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.4" + version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" pubspec_parse: dependency: transitive description: @@ -918,7 +925,7 @@ packages: name: rive url: "https://pub.dartlang.org" source: hosted - version: "0.10.1" + version: "0.10.2" rive_common: dependency: transitive description: @@ -932,77 +939,70 @@ packages: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.27.5" + version: "0.27.7" share_plus: dependency: "direct main" description: name: share_plus url: "https://pub.dartlang.org" source: hosted - version: "6.0.1" + version: "6.3.1" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.1.2" + version: "3.2.0" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.15" + version: "2.0.18" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.14" - shared_preferences_ios: + version: "2.0.16" + shared_preferences_foundation: dependency: transitive description: - name: shared_preferences_ios + name: shared_preferences_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" + version: "2.1.4" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.0.5" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.4" shelf: dependency: transitive description: @@ -1030,7 +1030,7 @@ packages: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.3" shimmer: dependency: "direct main" description: @@ -1049,7 +1049,7 @@ packages: name: sliver_tools url: "https://pub.dartlang.org" source: hosted - version: "0.2.8" + version: "0.2.9" source_gen: dependency: transitive description: @@ -1077,7 +1077,7 @@ packages: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.10" + version: "0.10.12" source_span: dependency: transitive description: @@ -1091,14 +1091,14 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "2.1.0+1" + version: "2.2.5" sqflite_common: dependency: transitive description: name: sqflite_common url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.4.2+2" stack_trace: dependency: transitive description: @@ -1119,7 +1119,7 @@ packages: name: stream_transform url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.1.0" string_scanner: dependency: transitive description: @@ -1133,7 +1133,7 @@ packages: name: synchronized url: "https://pub.dartlang.org" source: hosted - version: "3.0.0+3" + version: "3.0.1" term_glyph: dependency: transitive description: @@ -1168,7 +1168,7 @@ packages: name: timing url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.1" typed_data: dependency: transitive description: @@ -1182,63 +1182,63 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.6" + version: "6.1.10" url_launcher_android: dependency: transitive description: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.19" + version: "6.0.24" url_launcher_ios: dependency: transitive description: name: url_launcher_ios url: "https://pub.dartlang.org" source: hosted - version: "6.0.17" + version: "6.1.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.3" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.3" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.15" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.4" uuid: dependency: transitive description: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "3.0.6" + version: "3.0.7" vector_math: dependency: transitive description: @@ -1252,7 +1252,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "8.3.0" + version: "9.4.0" watcher: dependency: transitive description: @@ -1266,7 +1266,7 @@ packages: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" webkit_inspection_protocol: dependency: transitive description: @@ -1280,28 +1280,28 @@ packages: name: webview_flutter url: "https://pub.dartlang.org" source: hosted - version: "4.0.2" + version: "4.0.6" webview_flutter_android: dependency: transitive description: name: webview_flutter_android url: "https://pub.dartlang.org" source: hosted - version: "3.2.4" + version: "3.3.2" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview url: "https://pub.dartlang.org" source: hosted - version: "3.0.5" + version: "3.2.0" widgetbook: dependency: "direct dev" description: @@ -1336,14 +1336,14 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.1.3" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.2.0+2" + version: "1.0.0" xml: dependency: transitive description: From 023d67eaef5b6040395cf03006731ed01cc28727 Mon Sep 17 00:00:00 2001 From: Mathias Mogensencd collaction_website Date: Sun, 5 Mar 2023 00:15:16 +0100 Subject: [PATCH 09/19] chore: upgrade gradle build tools and dependencies --- android/build.gradle | 6 +++--- android/gradle/wrapper/gradle-wrapper.properties | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 2a330ec6..6b74e344 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,10 +6,10 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + classpath 'com.android.tools.build:gradle:7.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.10' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' + classpath 'com.google.gms:google-services:4.3.15' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.4' } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 939efa29..cb24abda 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip From 2aa649c974ecfdc78a79f806204d8edb5b006597 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Tue, 7 Feb 2023 10:39:31 +0200 Subject: [PATCH 10/19] Finishing half of the UI of the menu tab --- lib/main.dart | 2 +- lib/presentation/profile/profile_screen.dart | 4 +- lib/presentation/routes/app_routes.dart | 4 + lib/presentation/settings/menu_tab.dart | 282 +++++++++++++++++++ lib/presentation/themes/constants.dart | 20 ++ pubspec.lock | 204 +++++++++----- pubspec.yaml | 3 + 7 files changed, 443 insertions(+), 76 deletions(-) create mode 100644 lib/presentation/settings/menu_tab.dart diff --git a/lib/main.dart b/lib/main.dart index 90f5bafc..c2e64a11 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index ea260b62..79ff3764 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -9,6 +9,7 @@ import 'package:share_plus/share_plus.dart'; import '../../application/user/profile/profile_bloc.dart'; import '../core/collaction_icons.dart'; import '../routes/app_routes.gr.dart'; +import '../settings/menu_tab.dart'; import '../shared_widgets/photo_selector.dart'; import '../shared_widgets/pill_button.dart'; import '../themes/constants.dart'; @@ -72,7 +73,8 @@ class _UserProfilePageState extends State { ), const SizedBox(height: 10), ElevatedButton( - onPressed: () => context.router.push(const SettingsRoute()), + // onPressed: () => context.router.push(const SettingsRoute()), + onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MenuTab())), style: ElevatedButton.styleFrom( foregroundColor: kPrimaryColor0, backgroundColor: Colors.white, diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index 4bfe0835..5dd33fba 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -75,7 +75,11 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'settings-layout', page: SettingsLayout), AutoRoute(path: 'contact-form', page: ContactFormPage), AutoRoute(path: 'webview', page: WebViewPage), +<<<<<<< HEAD AutoRoute(path: 'unauthenticated', page: UnauthenticatedPage) +======= + +>>>>>>> ada75b8 (Finishing half of the UI of the menu tab) ], ) class $AppRouter {} diff --git a/lib/presentation/settings/menu_tab.dart b/lib/presentation/settings/menu_tab.dart new file mode 100644 index 00000000..f774b771 --- /dev/null +++ b/lib/presentation/settings/menu_tab.dart @@ -0,0 +1,282 @@ +import 'package:flutter/material.dart'; +import '../../presentation/themes/constants.dart'; + +class MenuTab extends StatefulWidget { + const MenuTab({Key? key}) : super(key: key); + + @override + State createState() => _MenuTabState(); +} + +class _MenuTabState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontFamily: "Rubik", + fontWeight: FontWeight.w700, + ), + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: "pictureUrl", + name: "Abdelrhman", + phoneNumber: "+970597501896", + ), + GestureDetector( + onTap: () { + debugPrint('Button tapped'); + }, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, shape: BoxShape.circle), + ), + ), + ], + ), + ), + ), + SizedBox( + height: 18, + ), + GestureDetector( + onTap: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.logout, + color: kErrorColor, + ), + SizedBox( + width: 2.5, + ), + Text( + "Log out", + style: TextStyle( + color: kErrorColor, + fontFamily: "Rubik", + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), + SizedBox(height: 38.5), + Text( + "Account", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + SizedBox( + height: 20, + ), + GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.account_circle, + color: kPrimaryColor300, + ), + SizedBox( + width: 18.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Account Information", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 275, + child: Text( + "View and update your account and contact information that is associated with your CollAction account.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ) + ], + ), + ), + SizedBox( + height: 30, + ), + Text( + "Feedback", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + SizedBox( + height: 20, + ), + GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.sms, + color: kPrimaryColor300, + ), + SizedBox( + width: 18.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact us", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 275, + child: Text( + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ), + ], + ), + ), + SizedBox(height: 30,), + Text( + "Legal information and policies", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + ], + ), + ), + ), + ); + } +} + +class AvatarAndInfo extends StatelessWidget { + final String pictureUrl; + + final String name; + + final String phoneNumber; + + const AvatarAndInfo( + {Key? key, + required this.pictureUrl, + required this.name, + required this.phoneNumber}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 65, + height: 65, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + ), + SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: nameTextStyle, + ), + Text( + phoneNumber, + style: phoneNumberTextStyle, + ), + ], + ) + ], + ); + } +} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index af0ecc4d..ea1101eb 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -24,6 +24,7 @@ const Color kPrimaryColor200 = Color(0xFF999999); const Color kPrimaryColor300 = Color(0xFF666666); const Color kPrimaryColor400 = Color(0xFF333333); const Color kPrimaryColor500 = Color(0xFF000000); +const Color kPrimaryColor600 = Color(0xFF2EB494); const TextStyle kCaption1 = TextStyle( fontSize: 12, @@ -41,3 +42,22 @@ const TextStyle kTitle1 = TextStyle( height: 34 / 28, fontWeight: FontWeight.w700, ); + +const TextStyle nameTextStyle = TextStyle( + fontSize: 17 , + fontWeight: FontWeight.w500 , + color: kPrimaryColor400 , +); + +const TextStyle phoneNumberTextStyle = TextStyle( + fontSize: 17, + fontWeight: FontWeight.w300, + color: kPrimaryColor300 , +); + + + +const BoxDecoration avatarInfoDecorationBox = BoxDecoration( + color: kAlmostTransparent , + borderRadius: BorderRadius.all(Radius.circular(20),) +); diff --git a/pubspec.lock b/pubspec.lock index 1767e4ce..a566c260 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "64fcb0dbca4386356386c085142fa6e79c00a3326ceaa778a2d25f5d9ba61441" + sha256: cb3a948a1eebbf8efd987c43f95418269930e912a88bc7b6a5a7658423133635 url: "https://pub.dev" source: hosted - version: "1.0.16" + version: "1.0.17" adaptive_number: dependency: transitive description: @@ -133,10 +133,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "93f05c041932674be039b0a2323d6cf57e5f2bbf884a3c0382f9e53fc45ebace" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.3" build_runner_core: dependency: transitive description: @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: "31b7c748fd4b9adf8d25d72a4c4a59ef119f12876cf414f94f8af5131d5fa2b0" url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.4.4" cached_network_image: dependency: "direct main" description: @@ -193,6 +193,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" + source: hosted + version: "1.3.1" checked_yaml: dependency: transitive description: @@ -201,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + cli_notify: + dependency: transitive + description: + name: cli_notify + sha256: "778987d49794f07a25d34369a158600e325b6d0f2671f361a81143511db569f5" + url: "https://pub.dev" + source: hosted + version: "0.0.4" cli_util: dependency: transitive description: @@ -233,6 +249,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + console: + dependency: transitive + description: + name: console + sha256: e04e7824384c5b39389acdd6dc7d33f3efe6b232f6f16d7626f194f6a01ad69a + url: "https://pub.dev" + source: hosted + version: "4.1.0" convert: dependency: transitive description: @@ -313,6 +337,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.1" + date_format: + dependency: transitive + description: + name: date_format + sha256: "8e5154ca363411847220c8cbc43afcf69c08e8debe40ba09d57710c25711760c" + url: "https://pub.dev" + source: hosted + version: "2.0.7" device_frame: dependency: transitive description: @@ -413,10 +445,10 @@ packages: dependency: transitive description: name: firebase_auth_platform_interface - sha256: c645fec50b0391aa878288f58fa4fe9762c271380c457aedf5c7c9b718604f68 + sha256: "98e4a414db0e083a2cb8a24735bb57ef3a1ee40a1407a93513391b24ad6ffd5d" url: "https://pub.dev" source: hosted - version: "6.11.11" + version: "6.11.12" firebase_auth_web: dependency: transitive description: @@ -429,50 +461,50 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: fe30ac230f12f8836bb97e6e09197340d3c584526825b1746ea362a82e1e43f7 + sha256: "1c121a478af23755b0b93fd4aa70d3bd32a587dd51ef0a3979091ac0d2317d32" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.7.1" firebase_core_platform_interface: - dependency: transitive + dependency: "direct overridden" description: name: firebase_core_platform_interface - sha256: "5615b30c36f55b2777d0533771deda7e5730e769e5d3cb7fda79e9bed86cfa55" + sha256: b51257a8b4388565cd66062d727d3e60067b5f5cc3390eb0ecd20b8f97741bdb url: "https://pub.dev" source: hosted - version: "4.5.3" + version: "4.5.1" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "291fbcace608aca6c860652e1358ef89752be8cc3ef227f8bbcd1e62775b833a" + sha256: "0c1cf1f1022d2245ac117443bb95207952ca770281524d2908e323bc063fb8ff" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics - sha256: "816bbb920316c8fe257b460b8856b01e274e867a729961bf7a3be6322cdf13e1" + sha256: d4190479611f42a34a04630d9188f30b592b65013d0f19c408d5249998429864 url: "https://pub.dev" source: hosted - version: "3.0.15" + version: "3.0.16" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: "120e47b9bac3654848d1bdc60b8027f3574b53ee0b81b1a2e5e76ddaa58f6645" + sha256: "667955b348b7729ed3d987956021a97fcdd05957df7c27b2d855e6b3f70e9521" url: "https://pub.dev" source: hosted - version: "3.3.15" + version: "3.3.16" fixnum: dependency: transitive description: name: fixnum - sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -538,10 +570,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" + sha256: c224ac897bed083dabf11f238dd11a239809b446740be0c2044608c50029ffdf url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -572,10 +604,18 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "4f4a162323c86ffc1245765cfe138872b8f069deb42f7dbb36115fa27f31469b" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.2.0" + fvm: + dependency: "direct main" + description: + name: fvm + sha256: "5b6f5ee02e779c555e5e2a782bbdca794bcc738daf2aad3ef8e399721c3ec85d" + url: "https://pub.dev" + source: hosted + version: "2.4.1" get_it: dependency: "direct main" description: @@ -668,34 +708,34 @@ packages: dependency: "direct main" description: name: image_picker - sha256: "22207768556b82d55ec70166824350fee32298732d5efa4d6e756f848f51f66a" + sha256: "64b21d9f0e065f9ab0e4dde458076226c97382cc0c6949144cb874c62bf8e9f8" url: "https://pub.dev" source: hosted - version: "0.8.6+3" + version: "0.8.7" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: "68d067baf7f6e401b1124ee83dd6967e67847314250fd68012aab34a69beb344" + sha256: "1f5a4b38eb742422d89c1a01d9db6077c3c9496f551bc9da74649e338a2b5101" url: "https://pub.dev" source: hosted - version: "0.8.5+7" + version: "0.8.6" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "66fc6e3877bbde82c33d122f3588777c3784ac5bd7d1cdd79213ef7aecb85b34" + sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c" url: "https://pub.dev" source: hosted - version: "2.1.11" + version: "2.1.12" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: "39aa70b5f1e5e7c94585b9738632d5fdb764a5655e40cd9e7b95fbd2fc50c519" + sha256: "50e882fe0a06bf0c8f7f5bce78d30975f279213293afc9471dc35f05617c50ff" url: "https://pub.dev" source: hosted - version: "0.8.6+9" + version: "0.8.7+1" image_picker_platform_interface: dependency: transitive description: @@ -860,10 +900,10 @@ packages: dependency: transitive description: name: node_preamble - sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" octo_image: dependency: transitive description: @@ -916,26 +956,26 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" + sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" url: "https://pub.dev" source: hosted - version: "2.0.23" + version: "2.0.24" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 + sha256: "026b97a6c29da75181a37aae2eba9227f5fe13cb2838c6b975ce209328b8ab4e" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" url: "https://pub.dev" source: hosted - version: "2.1.9" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: @@ -948,10 +988,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" pedantic: dependency: transitive description: @@ -1016,6 +1056,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.4" + process_run: + dependency: transitive + description: + name: process_run + sha256: "1142d7f4f0c3f36393a1319406efcf481def2b6d862b2bf600c8ae8fa74d5bd8" + url: "https://pub.dev" + source: hosted + version: "0.12.5+2" provider: dependency: transitive description: @@ -1100,26 +1148,26 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4 + sha256: ad423a80fe7b4e48b50d6111b3ea1027af0e959e49d485712e134863d9c1c521 url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.17" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259" + sha256: "1e755f8583229f185cfca61b1d80fb2344c9d660e1c69ede5450d8f478fa5310" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa + sha256: "3a59ed10890a8409ad0faad7bb2957dab4b92b8fbe553257b05d30ed8af2c707" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shared_preferences_platform_interface: dependency: transitive description: @@ -1132,18 +1180,18 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7" + sha256: "0dc2633f215a3d4aa3184c9b2c5766f4711e4e5a6b256e62aafee41f89f1bfb8" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.6" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d + sha256: "71bcd669bb9cdb6b39f22c4a7728b6d49e934f6cba73157ffa5a54f1eed67436" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shelf: dependency: transitive description: @@ -1333,6 +1381,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tint: + dependency: transitive + description: + name: tint + sha256: "9652d9a589f4536d5e392cf790263d120474f15da3cf1bee7f1fdb31b4de5f46" + url: "https://pub.dev" + source: hosted + version: "2.0.1" typed_data: dependency: transitive description: @@ -1353,34 +1409,34 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732" + sha256: "845530e5e05db5500c1a4c1446785d60cbd8f9bd45e21e7dd643a3273bb4bbd1" url: "https://pub.dev" source: hosted - version: "6.0.24" + version: "6.0.25" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5 + sha256: "7ab1e5b646623d6a2537aa59d5d039f90eebef75a7c25e105f6f75de1f7750c3" url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 + sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06" + sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" url_launcher_platform_interface: dependency: transitive description: @@ -1393,18 +1449,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" + sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" + sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" uuid: dependency: transitive description: @@ -1457,18 +1513,18 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "9ba213434f13e760ea0f175fbc4d6bb6aeafd7dfc6c7d973f15d3e47a5d6686e" + sha256: b6cd42db3ced5411f3d01599906156885b18e4188f7065a8a351eb84bee347e0 url: "https://pub.dev" source: hosted - version: "4.0.5" + version: "4.0.6" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "48c8cfb023168473c0a3a4c21ffea6c23a32cc7156701c39f618b303c6a3c96e" + sha256: c849dcb6bf7367f696869006fb9575c15bdc6a1d624ae13f12de5a147a740b12 url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.4.2" webview_flutter_platform_interface: dependency: transitive description: @@ -1481,10 +1537,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "283a38c2a2544768033864c698e0133aa9eee0f2c800f494b538a3d1044f7ecb" + sha256: ab12479f7a0cf112b9420c36aaf206a1ca47cd60cd42de74a4be2e97a697587b url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.2.1" widgetbook: dependency: "direct dev" description: @@ -1537,10 +1593,10 @@ packages: dependency: transitive description: name: xml - sha256: ac0e3f4bf00ba2708c33fbabbbe766300e509f8c82dbd4ab6525039813f7e2fb + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.2" yaml: dependency: transitive description: @@ -1550,5 +1606,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.18.6 <3.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index f9bced27..023288c7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: flutter_bloc: ^8.1.1 flutter_dotenv: ^5.0.2 freezed_annotation: ^2.2.0 + fvm: ^2.4.1 get_it: ^7.2.0 http: ^0.13.5 image: ^3.2.2 @@ -67,6 +68,8 @@ dev_dependencies: lint: ^2.0.1 widgetbook: ^2.4.1 widgetbook_generator: ^2.4.1 +dependency_overrides: + firebase_core_platform_interface: 4.5.1 flutter_icons: android: true From 28149542d6a92cfd3b9769bc5fe41dbde2a72a78 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:01:37 +0200 Subject: [PATCH 11/19] Finishing the Menu screen as a UI. --- assets/images/collaction.png | Bin 0 -> 4568 bytes lib/presentation/home/home_screen.dart | 5 + lib/presentation/menu/menu_screen.dart | 368 +++++++++++++++++++ lib/presentation/profile/profile_screen.dart | 4 +- lib/presentation/routes/app_routes.dart | 13 +- lib/presentation/settings/menu_tab.dart | 282 -------------- lib/presentation/themes/constants.dart | 5 + 7 files changed, 387 insertions(+), 290 deletions(-) create mode 100644 assets/images/collaction.png create mode 100644 lib/presentation/menu/menu_screen.dart delete mode 100644 lib/presentation/settings/menu_tab.dart diff --git a/assets/images/collaction.png b/assets/images/collaction.png new file mode 100644 index 0000000000000000000000000000000000000000..1f77c9b2d0729be8d76b412a9e36d2a337da889f GIT binary patch literal 4568 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 bottomNavbar(tabsRouter), ); @@ -47,6 +48,10 @@ class HomePage extends StatelessWidget { label: '', ), ], + BottomNavigationBarItem( + icon: Icon(Icons.menu_outlined), + label: '', + ), ], currentIndex: tabsRouter.activeIndex, onTap: tabsRouter.setActiveIndex, diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart new file mode 100644 index 00000000..bca3b4e9 --- /dev/null +++ b/lib/presentation/menu/menu_screen.dart @@ -0,0 +1,368 @@ +import 'package:flutter/material.dart'; +import '../themes/constants.dart'; +import '../core/collaction_icons.dart'; + +class MenuPage extends StatefulWidget { + const MenuPage({Key? key}) : super(key: key); + + @override + State createState() => _MenuTabState(); +} + +class _MenuTabState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontFamily: "Rubik", + fontWeight: FontWeight.w700, + ), + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: "pictureUrl", + name: "Abdelrhman", + phoneNumber: "+970597501896", + ), + GestureDetector( + onTap: () { + debugPrint('Button tapped'); + }, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle), + ), + ), + ], + ), + ), + ), + SizedBox(height: 18,), + GestureDetector( + onTap: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.logout, + color: kErrorColor, + ), + SizedBox( + width: 2.5, + ), + Text( + "Log out", + style: TextStyle( + color: kErrorColor, + fontFamily: "Rubik", + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), + ], + ), + ), + _buildSubTitle( + subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only(left: 22.25), + child: GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.account_circle, + color: kPrimaryColor300, + size: 19.5, + ), + SizedBox( + width: 12.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Account Information", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 306, + child: Text( + "View and update your account and contact information that is associated with your CollAction account.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ) + ], + ), + ), + ), + _buildSubTitle( + subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only( + left: 22.5, + ), + child: GestureDetector( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + CollactionIcons.message, + color: kPrimaryColor300, + size: 15, + ), + SizedBox( + width: 16.25, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact us", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 305, + child: Text( + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], + ), + ], + ), + ), + ), + _buildSubTitle( + subTitle: "Legal information and policies", + paddingBottom: 24, + paddingTop: 30), + LegalInfoAndPoliciesWidget( + onTap: () {}, + iconWidget: CollactionIcons.lock, + label: "Privacy Policy"), + LegalInfoAndPoliciesWidget( + onTap: () {}, + iconWidget: CollactionIcons.file, + label: "Terms & conditions"), + LegalInfoAndPoliciesWidget( + onTap: () {}, + iconWidget: CollactionIcons.opensource, + label: "Privacy Policy"), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Image( + image: AssetImage("assets/images/collaction.png"), + width: 120, + height: 20.36, + ), + SizedBox(height: 4,), + Text('Build 443' ,style: appInfo,), + Text('Version 1.0.1',style: appInfo), + Text('Stichting CollAction',style: appInfo) + ], + ), + ], + ) + ], + ), + ), + ), + ); + } + + Widget _buildSubTitle( + {required String subTitle, + double paddingTop = 0.0, + double paddingBottom = 0.0}) { + return Padding( + padding: + EdgeInsets.only(left: 20, top: paddingTop, bottom: paddingBottom), + child: Text( + subTitle, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + ); + } +} + +class AvatarAndInfo extends StatelessWidget { + final String pictureUrl; + final String name; + final String phoneNumber; + + const AvatarAndInfo( + {Key? key, + required this.pictureUrl, + required this.name, + required this.phoneNumber}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 65, + height: 65, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + ), + SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: nameTextStyle, + ), + Text( + phoneNumber, + style: phoneNumberTextStyle, + ), + ], + ) + ], + ); + } +} + +class LegalInfoAndPoliciesWidget extends StatefulWidget { + final Function onTap; + final IconData iconWidget; + final String label; + + const LegalInfoAndPoliciesWidget( + {Key? key, + required this.onTap, + required this.iconWidget, + required this.label}) + : super(key: key); + + @override + State createState() => + _LegalInfoAndPoliciesWidgetState(); +} + +class _LegalInfoAndPoliciesWidgetState + extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 20, bottom: 27.6), + child: InkWell( + onTap: widget.onTap(), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + widget.iconWidget, + size: 20, + ), + SizedBox( + width: 14, + ), + Text( + widget.label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index 79ff3764..ea260b62 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -9,7 +9,6 @@ import 'package:share_plus/share_plus.dart'; import '../../application/user/profile/profile_bloc.dart'; import '../core/collaction_icons.dart'; import '../routes/app_routes.gr.dart'; -import '../settings/menu_tab.dart'; import '../shared_widgets/photo_selector.dart'; import '../shared_widgets/pill_button.dart'; import '../themes/constants.dart'; @@ -73,8 +72,7 @@ class _UserProfilePageState extends State { ), const SizedBox(height: 10), ElevatedButton( - // onPressed: () => context.router.push(const SettingsRoute()), - onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MenuTab())), + onPressed: () => context.router.push(const SettingsRoute()), style: ElevatedButton.styleFrom( foregroundColor: kPrimaryColor0, backgroundColor: Colors.white, diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index 5dd33fba..4a6c507f 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -15,6 +15,7 @@ import '../demo/components_demo/components_demo_screen.dart'; import '../demo/demo_screen.dart'; import '../home/home_screen.dart'; import '../licenses/licenses_page.dart'; +import '../menu/menu_screen.dart'; import '../onboarding/onboarding_screen.dart'; import '../settings/settings_layout.dart'; import '../settings/settings_screen.dart'; @@ -65,6 +66,12 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'comments', page: CrowdActionCommentsPage), ], ), + AutoRoute( + path: 'menu', + name: 'MenuScreenRouter', + page: EmptyRouterPage, + children: [AutoRoute(path: '', page: MenuPage)], + ), ], ), AutoRoute(path: 'onboarding', page: OnboardingPage), @@ -75,11 +82,7 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'settings-layout', page: SettingsLayout), AutoRoute(path: 'contact-form', page: ContactFormPage), AutoRoute(path: 'webview', page: WebViewPage), -<<<<<<< HEAD - AutoRoute(path: 'unauthenticated', page: UnauthenticatedPage) -======= - ->>>>>>> ada75b8 (Finishing half of the UI of the menu tab) + AutoRoute(path: 'unauthenticated', page: UnauthenticatedPage), ], ) class $AppRouter {} diff --git a/lib/presentation/settings/menu_tab.dart b/lib/presentation/settings/menu_tab.dart deleted file mode 100644 index f774b771..00000000 --- a/lib/presentation/settings/menu_tab.dart +++ /dev/null @@ -1,282 +0,0 @@ -import 'package:flutter/material.dart'; -import '../../presentation/themes/constants.dart'; - -class MenuTab extends StatefulWidget { - const MenuTab({Key? key}) : super(key: key); - - @override - State createState() => _MenuTabState(); -} - -class _MenuTabState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: Padding( - padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - "Menu", - style: TextStyle( - fontSize: 28, - fontFamily: "Rubik", - fontWeight: FontWeight.w700, - ), - ), - IconButton( - onPressed: () {}, - icon: Icon( - Icons.search, - color: kPrimaryColor600, - size: 21.08, - ), - ), - ], - ), - SizedBox( - height: 30, - ), - Container( - height: 85, - decoration: avatarInfoDecorationBox, - child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AvatarAndInfo( - pictureUrl: "pictureUrl", - name: "Abdelrhman", - phoneNumber: "+970597501896", - ), - GestureDetector( - onTap: () { - debugPrint('Button tapped'); - }, - child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), - ), - decoration: BoxDecoration( - color: Colors.white, shape: BoxShape.circle), - ), - ), - ], - ), - ), - ), - SizedBox( - height: 18, - ), - GestureDetector( - onTap: () {}, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.logout, - color: kErrorColor, - ), - SizedBox( - width: 2.5, - ), - Text( - "Log out", - style: TextStyle( - color: kErrorColor, - fontFamily: "Rubik", - fontSize: 15, - fontWeight: FontWeight.w700, - ), - ) - ], - ), - ), - SizedBox(height: 38.5), - Text( - "Account", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - SizedBox( - height: 20, - ), - GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.account_circle, - color: kPrimaryColor300, - ), - SizedBox( - width: 18.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Account Information", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 275, - child: Text( - "View and update your account and contact information that is associated with your CollAction account.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ) - ], - ), - ), - SizedBox( - height: 30, - ), - Text( - "Feedback", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - SizedBox( - height: 20, - ), - GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.sms, - color: kPrimaryColor300, - ), - SizedBox( - width: 18.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Contact us", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 275, - child: Text( - "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ), - ], - ), - ), - SizedBox(height: 30,), - Text( - "Legal information and policies", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - ], - ), - ), - ), - ); - } -} - -class AvatarAndInfo extends StatelessWidget { - final String pictureUrl; - - final String name; - - final String phoneNumber; - - const AvatarAndInfo( - {Key? key, - required this.pictureUrl, - required this.name, - required this.phoneNumber}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 65, - height: 65, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.blue, - ), - ), - SizedBox( - width: 10, - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: nameTextStyle, - ), - Text( - phoneNumber, - style: phoneNumberTextStyle, - ), - ], - ) - ], - ); - } -} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index ea1101eb..a5c1c5e5 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -55,6 +55,11 @@ const TextStyle phoneNumberTextStyle = TextStyle( color: kPrimaryColor300 , ); +const TextStyle appInfo = TextStyle( +fontSize: 17, +fontWeight: FontWeight.w300, + color: kPrimaryColor200 , +); const BoxDecoration avatarInfoDecorationBox = BoxDecoration( From 51705a23ca62c1f7445322670e69422ba7b610fc Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sun, 12 Feb 2023 18:28:18 +0200 Subject: [PATCH 12/19] Finishing the menu tab, and removing the settings screen. --- lib/presentation/home/home_screen.dart | 4 +- lib/presentation/menu/menu_screen.dart | 523 ++++++++---------- .../menu/widgets/avatar_info.dart | 83 +++ .../widgets/build_information_tile.dart | 2 +- .../widgets/legal_info_policy_widget.dart | 56 ++ lib/presentation/profile/profile_screen.dart | 27 - lib/presentation/routes/app_routes.dart | 4 - .../settings/settings_layout.dart | 46 -- .../settings/settings_screen.dart | 131 ----- .../settings/widgets/settings_list_tile.dart | 44 -- .../widgets/share_collaction_list_tile.dart | 85 --- lib/presentation/themes/constants.dart | 6 - 12 files changed, 372 insertions(+), 639 deletions(-) create mode 100644 lib/presentation/menu/widgets/avatar_info.dart rename lib/presentation/{settings => menu}/widgets/build_information_tile.dart (95%) create mode 100644 lib/presentation/menu/widgets/legal_info_policy_widget.dart delete mode 100644 lib/presentation/settings/settings_layout.dart delete mode 100644 lib/presentation/settings/settings_screen.dart delete mode 100644 lib/presentation/settings/widgets/settings_list_tile.dart delete mode 100644 lib/presentation/settings/widgets/share_collaction_list_tile.dart diff --git a/lib/presentation/home/home_screen.dart b/lib/presentation/home/home_screen.dart index aa0d4c52..4cc0cf81 100644 --- a/lib/presentation/home/home_screen.dart +++ b/lib/presentation/home/home_screen.dart @@ -31,7 +31,7 @@ class HomePage extends StatelessWidget { unselectedItemColor: kDisabledButtonColor, type: BottomNavigationBarType.fixed, elevation: 0, - items: const [ + items: [ BottomNavigationBarItem( icon: Icon(CollactionIcons.collaction), label: '', @@ -49,7 +49,7 @@ class HomePage extends StatelessWidget { ), ], BottomNavigationBarItem( - icon: Icon(Icons.menu_outlined), + icon: Icon(Icons.grid_view,), label: '', ), ], diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index bca3b4e9..6b42ea13 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -1,3 +1,15 @@ +import 'package:auto_route/auto_route.dart'; +import 'widgets/build_information_tile.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../application/auth/auth_bloc.dart'; +import '../../application/settings/build_information/build_information_bloc.dart'; +import '../../application/user/profile/profile_bloc.dart'; +import '../../infrastructure/core/injection.dart'; +import '../routes/app_routes.gr.dart'; +import '../utils/launch_url.dart'; +import 'widgets/avatar_info.dart'; +import 'widgets/legal_info_policy_widget.dart'; import 'package:flutter/material.dart'; import '../themes/constants.dart'; import '../core/collaction_icons.dart'; @@ -15,236 +27,258 @@ class _MenuTabState extends State { return Scaffold( body: SafeArea( child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20, top: 10, right: 22.5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + child: BlocProvider.value( + value: BlocProvider.of(context), + child: BlocBuilder( + builder: (context, state) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: + const EdgeInsets.only(left: 20, top: 10, right: 22.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Menu", - style: TextStyle( - fontSize: 28, - fontFamily: "Rubik", - fontWeight: FontWeight.w700, - ), - ), - IconButton( - onPressed: () {}, - icon: Icon( - Icons.search, - color: kPrimaryColor600, - size: 21.08, - ), - ), - ], - ), - SizedBox( - height: 30, - ), - Container( - height: 85, - decoration: avatarInfoDecorationBox, - child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), - child: Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - AvatarAndInfo( - pictureUrl: "pictureUrl", - name: "Abdelrhman", - phoneNumber: "+970597501896", + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontFamily: "Rubik", + fontWeight: FontWeight.w700, + ), ), - GestureDetector( - onTap: () { - debugPrint('Button tapped'); - }, - child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), - ), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, ), ), ], ), - ), + SizedBox( + height: 30, + ), + Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: state.userProfile?.profile.avatar, + name: state.userProfile?.profile.firstName, + ), + GestureDetector( + onTap: () { + }, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle), + ), + ), + ], + ), + ), + ), + SizedBox( + height: 18, + ), + GestureDetector( + onTap: () async { + BlocProvider.of(context) + .add(const AuthEvent.signedOut()); + BlocProvider.of(context) + .add(GetUserProfile()); + await context.router.pop(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.logout, + color: kErrorColor, + ), + SizedBox( + width: 2.5, + ), + Text( + "Log out", + style: TextStyle( + color: kErrorColor, + fontFamily: "Rubik", + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), + ], ), - SizedBox(height: 18,), - GestureDetector( + ), + _buildSubTitle( + subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only(left: 22.25), + child: GestureDetector( onTap: () {}, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon( - Icons.logout, - color: kErrorColor, + Icons.account_circle, + color: kPrimaryColor300, + size: 19.5, ), SizedBox( - width: 2.5, + width: 12.25, ), - Text( - "Log out", - style: TextStyle( - color: kErrorColor, - fontFamily: "Rubik", - fontSize: 15, - fontWeight: FontWeight.w700, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Account Information", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 306, + child: Text( + "View and update your account and contact information that is associated with your CollAction account.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], ) ], ), ), - ], - ), - ), - _buildSubTitle( - subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), - Padding( - padding: const EdgeInsets.only(left: 22.25), - child: GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.account_circle, - color: kPrimaryColor300, - size: 19.5, - ), - SizedBox( - width: 12.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Account Information", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 306, - child: Text( - "View and update your account and contact information that is associated with your CollAction account.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ) - ], ), - ), - ), - _buildSubTitle( - subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), - Padding( - padding: const EdgeInsets.only( - left: 22.5, - ), - child: GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - CollactionIcons.message, - color: kPrimaryColor300, - size: 15, - ), - SizedBox( - width: 16.25, - ), - Column( + _buildSubTitle( + subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), + Padding( + padding: const EdgeInsets.only( + left: 22.5, + ), + child: GestureDetector( + onTap: () {}, + child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Contact us", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), + Icon( + CollactionIcons.message, + color: kPrimaryColor300, + size: 15, ), SizedBox( - height: 5, + width: 16.25, ), - SizedBox( - width: 305, - child: Text( - "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact us", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300), + ), + SizedBox( + height: 5, + ), + SizedBox( + width: 305, + child: Text( + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400), + ), + ), + ], ), ], ), - ], + ), ), - ), - ), - _buildSubTitle( - subTitle: "Legal information and policies", - paddingBottom: 24, - paddingTop: 30), - LegalInfoAndPoliciesWidget( - onTap: () {}, - iconWidget: CollactionIcons.lock, - label: "Privacy Policy"), - LegalInfoAndPoliciesWidget( - onTap: () {}, - iconWidget: CollactionIcons.file, - label: "Terms & conditions"), - LegalInfoAndPoliciesWidget( - onTap: () {}, - iconWidget: CollactionIcons.opensource, - label: "Privacy Policy"), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( + _buildSubTitle( + subTitle: "Legal information and policies", + paddingBottom: 24, + paddingTop: 30), + LegalInfoAndPoliciesWidget( + onTap: () async { + launchUrl( + 'https://www.collaction.org/privacy', + useWebView: true, + context: context, + ); + }, + iconWidget: CollactionIcons.lock, + label: "Privacy Policy"), + LegalInfoAndPoliciesWidget( + onTap: () => launchUrl( + 'https://www.collaction.org/terms', + useWebView: true, + context: context, + ), + iconWidget: CollactionIcons.file, + label: "Terms & conditions"), + LegalInfoAndPoliciesWidget( + onTap: () => context.router.push(const LicensesRoute()), + iconWidget: CollactionIcons.opensource, + label: "Open-source libraries"), + Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Image( - image: AssetImage("assets/images/collaction.png"), - width: 120, - height: 20.36, + BlocBuilder( + bloc: getIt() + ..add(const BuildInformationEvent.fetch()), + builder: (context, state) { + return state.when( + loading: () => const SizedBox(), + fetched: (buildInfo) => + BuildInformationTile(information: buildInfo), + ); + }, ), - SizedBox(height: 4,), - Text('Build 443' ,style: appInfo,), - Text('Version 1.0.1',style: appInfo), - Text('Stichting CollAction',style: appInfo) + ], - ), + ) ], - ) - ], + ), + ), ), ), ), @@ -269,100 +303,3 @@ class _MenuTabState extends State { ); } } - -class AvatarAndInfo extends StatelessWidget { - final String pictureUrl; - final String name; - final String phoneNumber; - - const AvatarAndInfo( - {Key? key, - required this.pictureUrl, - required this.name, - required this.phoneNumber}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 65, - height: 65, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.blue, - ), - ), - SizedBox( - width: 10, - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: nameTextStyle, - ), - Text( - phoneNumber, - style: phoneNumberTextStyle, - ), - ], - ) - ], - ); - } -} - -class LegalInfoAndPoliciesWidget extends StatefulWidget { - final Function onTap; - final IconData iconWidget; - final String label; - - const LegalInfoAndPoliciesWidget( - {Key? key, - required this.onTap, - required this.iconWidget, - required this.label}) - : super(key: key); - - @override - State createState() => - _LegalInfoAndPoliciesWidgetState(); -} - -class _LegalInfoAndPoliciesWidgetState - extends State { - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 20, bottom: 27.6), - child: InkWell( - onTap: widget.onTap(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - widget.iconWidget, - size: 20, - ), - SizedBox( - width: 14, - ), - Text( - widget.label, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300, - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/presentation/menu/widgets/avatar_info.dart b/lib/presentation/menu/widgets/avatar_info.dart new file mode 100644 index 00000000..4c128270 --- /dev/null +++ b/lib/presentation/menu/widgets/avatar_info.dart @@ -0,0 +1,83 @@ + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +import '../../../domain/user/i_user_repository.dart'; +import '../../../domain/user/user.dart'; +import '../../../infrastructure/core/injection.dart'; +import '../../profile/widget/profile_picture.dart'; +import '../../themes/constants.dart'; + +class AvatarAndInfo extends StatefulWidget { + final String? pictureUrl; + final String? name; + + const AvatarAndInfo( + {Key? key, + required this.pictureUrl, + required this.name, + }) + : super(key: key); + + @override + State createState() => _AvatarAndInfoState(); +} + +class _AvatarAndInfoState extends State { + late final IUserRepository _userRepository; + File? _image; + @override + void initState() { + super.initState(); + _userRepository = getIt(); + } + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // ProfilePicture( + // maxRadius: 40, + // profileImage: + // '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}', + // ), + ProfilePicture( + image: _image, + profileImage: widget.pictureUrl != + null + ? '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}' + : null, + maxRadius: 50, + ), + SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.name ?? "", + style: nameTextStyle, + ), + StreamBuilder(builder: (context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + final number = snapshot.data!.phoneNumber ?? 'no phone number'; + return Text( + number, + style: phoneNumberTextStyle, + ); + } else { + return const Text('...'); + } + + },stream: _userRepository.observeUser() + ,), + ], + ) + ], + ); + } +} diff --git a/lib/presentation/settings/widgets/build_information_tile.dart b/lib/presentation/menu/widgets/build_information_tile.dart similarity index 95% rename from lib/presentation/settings/widgets/build_information_tile.dart rename to lib/presentation/menu/widgets/build_information_tile.dart index 1092d7e6..2d2c575e 100644 --- a/lib/presentation/settings/widgets/build_information_tile.dart +++ b/lib/presentation/menu/widgets/build_information_tile.dart @@ -15,7 +15,7 @@ class BuildInformationTile extends StatelessWidget { const SizedBox(height: 50), const SizedBox( width: 56, - child: Image(image: AssetImage('assets/images/build_info.png')), + child: Image(image: AssetImage('assets/images/collaction.png')), ), const SizedBox(height: 5), Text( diff --git a/lib/presentation/menu/widgets/legal_info_policy_widget.dart b/lib/presentation/menu/widgets/legal_info_policy_widget.dart new file mode 100644 index 00000000..c5ed05a7 --- /dev/null +++ b/lib/presentation/menu/widgets/legal_info_policy_widget.dart @@ -0,0 +1,56 @@ + +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; + +class LegalInfoAndPoliciesWidget extends StatefulWidget { + final onTap; + final IconData iconWidget; + final String label; + + const LegalInfoAndPoliciesWidget( + {Key? key, + required this.onTap, + required this.iconWidget, + required this.label}) + : super(key: key); + + @override + State createState() => + _LegalInfoAndPoliciesWidgetState(); +} + +class _LegalInfoAndPoliciesWidgetState + extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 20, bottom: 27.6), + child: InkWell( + onTap:(){ + widget.onTap(); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + widget.iconWidget, + size: 20, + ), + SizedBox( + width: 14, + ), + Text( + widget.label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: kPrimaryColor300, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index ea260b62..8f9ee041 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -71,33 +71,6 @@ class _UserProfilePageState extends State { ), ), const SizedBox(height: 10), - ElevatedButton( - onPressed: () => context.router.push(const SettingsRoute()), - style: ElevatedButton.styleFrom( - foregroundColor: kPrimaryColor0, - backgroundColor: Colors.white, - shape: const CircleBorder(), - tapTargetSize: MaterialTapTargetSize.padded, - ).merge( - ButtonStyle( - elevation: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.pressed)) { - return 5; - } - return 4; - }, - ), - ), - ), - child: const Padding( - padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 4), - child: Icon( - CollactionIcons.settings, - color: kPrimaryColor300, - ), - ), - ), ], ), body: SafeArea( diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index 4a6c507f..f5373caa 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -17,8 +17,6 @@ import '../home/home_screen.dart'; import '../licenses/licenses_page.dart'; import '../menu/menu_screen.dart'; import '../onboarding/onboarding_screen.dart'; -import '../settings/settings_layout.dart'; -import '../settings/settings_screen.dart'; import '../shared_widgets/web_view_page.dart'; @MaterialAutoRouter( @@ -77,9 +75,7 @@ import '../shared_widgets/web_view_page.dart'; AutoRoute(path: 'onboarding', page: OnboardingPage), AutoRoute(path: 'auth', page: AuthPage), AutoRoute(path: 'verified', page: VerifiedPage), - AutoRoute(path: 'settings-page', page: SettingsPage), AutoRoute(path: 'licenses-page', page: LicensesPage), - AutoRoute(path: 'settings-layout', page: SettingsLayout), AutoRoute(path: 'contact-form', page: ContactFormPage), AutoRoute(path: 'webview', page: WebViewPage), AutoRoute(path: 'unauthenticated', page: UnauthenticatedPage), diff --git a/lib/presentation/settings/settings_layout.dart b/lib/presentation/settings/settings_layout.dart deleted file mode 100644 index 56dbdbc1..00000000 --- a/lib/presentation/settings/settings_layout.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; - -import '../themes/constants.dart'; - -class SettingsLayout extends StatelessWidget { - const SettingsLayout({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: kSecondaryColor, - leading: RawMaterialButton( - elevation: 5, - onPressed: () => context.router.pop(), - child: const CircleAvatar( - backgroundColor: kSecondaryColor, - child: Icon( - Icons.arrow_back_ios_new_outlined, - color: kPrimaryColor300, - ), - ), - ), - actions: [ - ElevatedButton( - style: ButtonStyle( - padding: MaterialStateProperty.all(const EdgeInsets.all(8)), - backgroundColor: MaterialStateProperty.all(kSecondaryColor), - elevation: MaterialStateProperty.all(2), - ), - onPressed: () => context.router.pop(), - child: const CircleAvatar( - backgroundColor: kSecondaryColor, - child: Icon( - Icons.close_outlined, - color: kPrimaryColor300, - ), - ), - ) - ], - ), - ); - } -} diff --git a/lib/presentation/settings/settings_screen.dart b/lib/presentation/settings/settings_screen.dart deleted file mode 100644 index 1689e386..00000000 --- a/lib/presentation/settings/settings_screen.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import '/application/settings/build_information/build_information_bloc.dart'; -import '../../../presentation/utils/launch_url.dart'; -import '../../application/auth/auth_bloc.dart'; -import '../../application/user/profile/profile_bloc.dart'; -import '../../infrastructure/core/injection.dart'; -import '../core/collaction_icons.dart'; -import '../routes/app_routes.gr.dart'; -import '../shared_widgets/custom_app_bars/custom_appbar.dart'; -import '../themes/constants.dart'; -import 'widgets/build_information_tile.dart'; -import 'widgets/settings_list_tile.dart'; -import 'widgets/share_collaction_list_tile.dart'; - -class SettingsPage extends StatelessWidget { - const SettingsPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: const CustomAppBar(closable: true), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - children: [ - const ShareCollactionListTile(), - const SizedBox(height: 15), - SettingsListTile( - title: 'Contact us', - icon: CollactionIcons.message, - trailingIcon: CollactionIcons.arrow_right, - onTap: () => - context.router.push(const ContactFormRoute()), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Onboarding', - icon: CollactionIcons.rocket, - trailingIcon: CollactionIcons.arrow_right, - onTap: () => - context.router.push(const OnboardingRoute()), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Open source libraries', - icon: CollactionIcons.opensource, - trailingIcon: CollactionIcons.arrow_right, - onTap: () => - context.router.push(const LicensesRoute()), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Terms of use', - icon: CollactionIcons.lock, - trailingIcon: CollactionIcons.external_link, - onTap: () => launchUrl( - 'https://www.collaction.org/terms', - useWebView: true, - context: context, - ), - ), - const SizedBox(height: 15), - SettingsListTile( - title: 'Privacy policy', - icon: CollactionIcons.file, - trailingIcon: CollactionIcons.external_link, - onTap: () => launchUrl( - 'https://www.collaction.org/privacy', - useWebView: true, - context: context, - ), - ), - BlocBuilder( - bloc: BlocProvider.of(context), - builder: (context, ProfileState state) => state - .userProfile == - null - ? const SizedBox() - : Column( - children: [ - const SizedBox(height: 15), - SettingsListTile( - title: 'Log out', - icon: CollactionIcons.logout, - iconColor: kErrorColor, - onTap: () async { - BlocProvider.of(context) - .add(const AuthEvent.signedOut()); - BlocProvider.of(context) - .add(GetUserProfile()); - await context.router.pop(); - }, - ), - ], - ), - ), - BlocBuilder( - bloc: getIt() - ..add(const BuildInformationEvent.fetch()), - builder: (context, state) { - return state.when( - loading: () => const SizedBox(), - fetched: (buildInfo) => - BuildInformationTile(information: buildInfo), - ); - }, - ), - ], - ), - ], - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/presentation/settings/widgets/settings_list_tile.dart b/lib/presentation/settings/widgets/settings_list_tile.dart deleted file mode 100644 index 4f9e1307..00000000 --- a/lib/presentation/settings/widgets/settings_list_tile.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; -import '../../themes/constants.dart'; - -class SettingsListTile extends StatelessWidget { - final String title; - final IconData icon; - final Color iconColor; - final Function() onTap; - final IconData? trailingIcon; - - const SettingsListTile({ - super.key, - required this.title, - required this.icon, - required this.onTap, - this.iconColor = kPrimaryColor300, - this.trailingIcon, - }); - - @override - Widget build(BuildContext context) { - return ListTile( - onTap: onTap, - contentPadding: const EdgeInsets.symmetric( - vertical: 15, - horizontal: 20, - ), - tileColor: kAlmostTransparent, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - leading: CircleAvatar( - radius: 32.5, - backgroundColor: kSecondaryColor, - child: Icon( - icon, - color: iconColor, - ), - ), - title: Text(title), - trailing: trailingIcon != null ? Icon(trailingIcon) : null, - ); - } -} diff --git a/lib/presentation/settings/widgets/share_collaction_list_tile.dart b/lib/presentation/settings/widgets/share_collaction_list_tile.dart deleted file mode 100644 index 3d3ef6ad..00000000 --- a/lib/presentation/settings/widgets/share_collaction_list_tile.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:share_plus/share_plus.dart'; - -import '../../core/collaction_icons.dart'; -import '../../themes/constants.dart'; -import '../../utils/strings.dart'; - -class ShareCollactionListTile extends StatefulWidget { - const ShareCollactionListTile({ - super.key, - String? shareText, - String? shareEmailSubject, - }) : _shareText = shareText, - _shareEmailSubject = shareEmailSubject; - - final String? _shareText; - final String? _shareEmailSubject; - - @override - State createState() => - ShareCollactionListTileState(); -} - -class ShareCollactionListTileState extends State { - late bool _isClicked; - - void onFocusChange(bool focused) { - setState(() { - _isClicked = focused == false; - }); - } - - Future _clickCallback() async { - setState(() { - _isClicked = true; - }); - - Share.share( - widget._shareText ?? defaultShareText, - subject: widget._shareEmailSubject ?? defaultShareEmailSubject, - ); - await Future.delayed(const Duration(seconds: 1)); - - setState(() { - _isClicked = false; - }); - } - - @override - void initState() { - super.initState(); - _isClicked = false; - } - - @override - Widget build(BuildContext context) { - return Focus( - onFocusChange: onFocusChange, - child: ListTile( - enabled: !_isClicked, - onTap: _clickCallback, - contentPadding: const EdgeInsets.symmetric( - vertical: 15, - horizontal: 20, - ), - tileColor: kAlmostTransparent, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - leading: const CircleAvatar( - radius: 32.5, - backgroundColor: kSecondaryColor, - child: Icon( - CollactionIcons.share, - color: kPrimaryColor300, - ), - ), - title: const Text( - 'Share CollAction', - ), - trailing: const Icon(CollactionIcons.arrow_right), - ), - ); - } -} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index a5c1c5e5..91bf5ac3 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -25,7 +25,6 @@ const Color kPrimaryColor300 = Color(0xFF666666); const Color kPrimaryColor400 = Color(0xFF333333); const Color kPrimaryColor500 = Color(0xFF000000); const Color kPrimaryColor600 = Color(0xFF2EB494); - const TextStyle kCaption1 = TextStyle( fontSize: 12, height: 16 / 12, @@ -55,11 +54,6 @@ const TextStyle phoneNumberTextStyle = TextStyle( color: kPrimaryColor300 , ); -const TextStyle appInfo = TextStyle( -fontSize: 17, -fontWeight: FontWeight.w300, - color: kPrimaryColor200 , -); const BoxDecoration avatarInfoDecorationBox = BoxDecoration( From 6e8121f3c7a12e6d06f17989de0d0ffc90eabe41 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Tue, 14 Feb 2023 19:47:54 +0200 Subject: [PATCH 13/19] Solving the the inconsistencies. --- assets/images/build_info.png | Bin 14107 -> 0 bytes lib/infrastructure/core/injection.dart | 1 + lib/main.dart | 2 +- lib/presentation/menu/menu_screen.dart | 91 ++++-------------- .../menu/widgets/avatar_info.dart | 40 ++++---- lib/presentation/menu/widgets/header_bar.dart | 32 ++++++ .../widgets/legal_info_policy_widget.dart | 13 +-- .../menu/widgets/user_info_and_avatar.dart | 55 +++++++++++ lib/presentation/themes/constants.dart | 17 ++-- pubspec.lock | 62 +----------- pubspec.yaml | 5 +- 11 files changed, 141 insertions(+), 177 deletions(-) delete mode 100644 assets/images/build_info.png create mode 100644 lib/presentation/menu/widgets/header_bar.dart create mode 100644 lib/presentation/menu/widgets/user_info_and_avatar.dart diff --git a/assets/images/build_info.png b/assets/images/build_info.png deleted file mode 100644 index c362d5b49cfa7e1fc8a18b98557b749a66cb13b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14107 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 bMiqbv`2$U}ob=x>8<>oQf_Sy4QPBSZ`FR&q diff --git a/lib/infrastructure/core/injection.dart b/lib/infrastructure/core/injection.dart index 98ad4f10..535b983b 100644 --- a/lib/infrastructure/core/injection.dart +++ b/lib/infrastructure/core/injection.dart @@ -8,4 +8,5 @@ final GetIt getIt = GetIt.instance; @injectableInit void configureInjection() { getIt.init(); + } diff --git a/lib/main.dart b/lib/main.dart index c2e64a11..90f5bafc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index 6b42ea13..61320857 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -9,19 +9,16 @@ import '../../infrastructure/core/injection.dart'; import '../routes/app_routes.gr.dart'; import '../utils/launch_url.dart'; import 'widgets/avatar_info.dart'; +import 'widgets/header_bar.dart'; import 'widgets/legal_info_policy_widget.dart'; import 'package:flutter/material.dart'; import '../themes/constants.dart'; import '../core/collaction_icons.dart'; +import 'widgets/user_info_and_avatar.dart'; -class MenuPage extends StatefulWidget { +class MenuPage extends StatelessWidget { const MenuPage({Key? key}) : super(key: key); - @override - State createState() => _MenuTabState(); -} - -class _MenuTabState extends State { @override Widget build(BuildContext context) { return Scaffold( @@ -39,69 +36,14 @@ class _MenuTabState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - "Menu", - style: TextStyle( - fontSize: 28, - fontFamily: "Rubik", - fontWeight: FontWeight.w700, - ), - ), - IconButton( - onPressed: () {}, - icon: Icon( - Icons.search, - color: kPrimaryColor600, - size: 21.08, - ), - ), - ], + HeaderBar(), + UserInfoAndAvatar( + pictureUrl: state.userProfile?.profile.avatar, + name: state.userProfile?.profile.firstName, ), SizedBox( height: 30, ), - Container( - height: 85, - decoration: avatarInfoDecorationBox, - child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AvatarAndInfo( - pictureUrl: state.userProfile?.profile.avatar, - name: state.userProfile?.profile.firstName, - ), - GestureDetector( - onTap: () { - }, - child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), - ), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle), - ), - ), - ], - ), - ), - ), SizedBox( height: 18, ), @@ -127,7 +69,6 @@ class _MenuTabState extends State { "Log out", style: TextStyle( color: kErrorColor, - fontFamily: "Rubik", fontSize: 15, fontWeight: FontWeight.w700, ), @@ -139,7 +80,10 @@ class _MenuTabState extends State { ), ), _buildSubTitle( - subTitle: "Account", paddingTop: 38.5, paddingBottom: 20), + subTitle: "Account", + paddingTop: 38.5, + paddingBottom: 20, + ), Padding( padding: const EdgeInsets.only(left: 22.25), child: GestureDetector( @@ -261,8 +205,7 @@ class _MenuTabState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - BlocBuilder( + BlocBuilder( bloc: getIt() ..add(const BuildInformationEvent.fetch()), builder: (context, state) { @@ -273,7 +216,6 @@ class _MenuTabState extends State { ); }, ), - ], ) ], @@ -285,10 +227,11 @@ class _MenuTabState extends State { ); } - Widget _buildSubTitle( - {required String subTitle, - double paddingTop = 0.0, - double paddingBottom = 0.0}) { + Widget _buildSubTitle({ + required String subTitle, + double paddingTop = 0.0, + double paddingBottom = 0.0, + }) { return Padding( padding: EdgeInsets.only(left: 20, top: paddingTop, bottom: paddingBottom), diff --git a/lib/presentation/menu/widgets/avatar_info.dart b/lib/presentation/menu/widgets/avatar_info.dart index 4c128270..e93319eb 100644 --- a/lib/presentation/menu/widgets/avatar_info.dart +++ b/lib/presentation/menu/widgets/avatar_info.dart @@ -1,4 +1,3 @@ - import 'dart:io'; import 'package:flutter/material.dart'; @@ -14,12 +13,11 @@ class AvatarAndInfo extends StatefulWidget { final String? pictureUrl; final String? name; - const AvatarAndInfo( - {Key? key, - required this.pictureUrl, - required this.name, - }) - : super(key: key); + const AvatarAndInfo({ + Key? key, + required this.pictureUrl, + required this.name, + }) : super(key: key); @override State createState() => _AvatarAndInfoState(); @@ -28,25 +26,22 @@ class AvatarAndInfo extends StatefulWidget { class _AvatarAndInfoState extends State { late final IUserRepository _userRepository; File? _image; + late String number; + @override void initState() { super.initState(); _userRepository = getIt(); } + @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // ProfilePicture( - // maxRadius: 40, - // profileImage: - // '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}', - // ), ProfilePicture( image: _image, - profileImage: widget.pictureUrl != - null + profileImage: widget.pictureUrl != null ? '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}' : null, maxRadius: 50, @@ -62,19 +57,18 @@ class _AvatarAndInfoState extends State { widget.name ?? "", style: nameTextStyle, ), - StreamBuilder(builder: (context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - final number = snapshot.data!.phoneNumber ?? 'no phone number'; + StreamBuilder( + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + number = snapshot.data!.phoneNumber ?? 'no phone number'; + } return Text( number, style: phoneNumberTextStyle, ); - } else { - return const Text('...'); - } - - },stream: _userRepository.observeUser() - ,), + }, + stream: _userRepository.observeUser(), + ), ], ) ], diff --git a/lib/presentation/menu/widgets/header_bar.dart b/lib/presentation/menu/widgets/header_bar.dart new file mode 100644 index 00000000..f6a0bdd1 --- /dev/null +++ b/lib/presentation/menu/widgets/header_bar.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; + +class HeaderBar extends StatelessWidget { + const HeaderBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.w700, + ), + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.search, + color: kPrimaryColor600, + size: 21.08, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/menu/widgets/legal_info_policy_widget.dart b/lib/presentation/menu/widgets/legal_info_policy_widget.dart index c5ed05a7..9cb21908 100644 --- a/lib/presentation/menu/widgets/legal_info_policy_widget.dart +++ b/lib/presentation/menu/widgets/legal_info_policy_widget.dart @@ -1,18 +1,17 @@ - import 'package:flutter/material.dart'; import '../../themes/constants.dart'; class LegalInfoAndPoliciesWidget extends StatefulWidget { - final onTap; + final Function onTap; final IconData iconWidget; final String label; const LegalInfoAndPoliciesWidget( {Key? key, - required this.onTap, - required this.iconWidget, - required this.label}) + required this.onTap, + required this.iconWidget, + required this.label}) : super(key: key); @override @@ -27,9 +26,7 @@ class _LegalInfoAndPoliciesWidgetState return Padding( padding: const EdgeInsets.only(left: 20, bottom: 27.6), child: InkWell( - onTap:(){ - widget.onTap(); - }, + onTap: () => widget.onTap(), child: Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/presentation/menu/widgets/user_info_and_avatar.dart b/lib/presentation/menu/widgets/user_info_and_avatar.dart new file mode 100644 index 00000000..eeb1ddf5 --- /dev/null +++ b/lib/presentation/menu/widgets/user_info_and_avatar.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; +import 'avatar_info.dart'; + +class UserInfoAndAvatar extends StatelessWidget { + final String? pictureUrl; + + final String? name; + + const UserInfoAndAvatar({Key? key, this.pictureUrl, this.name}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 85, + decoration: avatarInfoDecorationBox, + child: Padding( + padding: EdgeInsets.only( + left: 20, + top: 10, + bottom: 10, + right: 25.5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + AvatarAndInfo( + pictureUrl: pictureUrl, + name: name, + ), + GestureDetector( + onTap: () {}, + child: Container( + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 21, + ), + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index 91bf5ac3..656fae5c 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -25,6 +25,7 @@ const Color kPrimaryColor300 = Color(0xFF666666); const Color kPrimaryColor400 = Color(0xFF333333); const Color kPrimaryColor500 = Color(0xFF000000); const Color kPrimaryColor600 = Color(0xFF2EB494); + const TextStyle kCaption1 = TextStyle( fontSize: 12, height: 16 / 12, @@ -43,20 +44,20 @@ const TextStyle kTitle1 = TextStyle( ); const TextStyle nameTextStyle = TextStyle( - fontSize: 17 , - fontWeight: FontWeight.w500 , - color: kPrimaryColor400 , + fontSize: 17, + fontWeight: FontWeight.w500, + color: kPrimaryColor400, ); const TextStyle phoneNumberTextStyle = TextStyle( fontSize: 17, fontWeight: FontWeight.w300, - color: kPrimaryColor300 , + color: kPrimaryColor300, ); - - const BoxDecoration avatarInfoDecorationBox = BoxDecoration( - color: kAlmostTransparent , - borderRadius: BorderRadius.all(Radius.circular(20),) + color: kAlmostTransparent, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), ); diff --git a/pubspec.lock b/pubspec.lock index a566c260..979b280a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -193,14 +193,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" - charcode: - dependency: transitive - description: - name: charcode - sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 - url: "https://pub.dev" - source: hosted - version: "1.3.1" checked_yaml: dependency: transitive description: @@ -209,14 +201,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" - cli_notify: - dependency: transitive - description: - name: cli_notify - sha256: "778987d49794f07a25d34369a158600e325b6d0f2671f361a81143511db569f5" - url: "https://pub.dev" - source: hosted - version: "0.0.4" cli_util: dependency: transitive description: @@ -249,14 +233,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" - console: - dependency: transitive - description: - name: console - sha256: e04e7824384c5b39389acdd6dc7d33f3efe6b232f6f16d7626f194f6a01ad69a - url: "https://pub.dev" - source: hosted - version: "4.1.0" convert: dependency: transitive description: @@ -337,14 +313,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.1" - date_format: - dependency: transitive - description: - name: date_format - sha256: "8e5154ca363411847220c8cbc43afcf69c08e8debe40ba09d57710c25711760c" - url: "https://pub.dev" - source: hosted - version: "2.0.7" device_frame: dependency: transitive description: @@ -466,13 +434,13 @@ packages: source: hosted version: "2.7.1" firebase_core_platform_interface: - dependency: "direct overridden" + dependency: transitive description: name: firebase_core_platform_interface - sha256: b51257a8b4388565cd66062d727d3e60067b5f5cc3390eb0ecd20b8f97741bdb + sha256: "5615b30c36f55b2777d0533771deda7e5730e769e5d3cb7fda79e9bed86cfa55" url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.5.3" firebase_core_web: dependency: transitive description: @@ -608,14 +576,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.0" - fvm: - dependency: "direct main" - description: - name: fvm - sha256: "5b6f5ee02e779c555e5e2a782bbdca794bcc738daf2aad3ef8e399721c3ec85d" - url: "https://pub.dev" - source: hosted - version: "2.4.1" get_it: dependency: "direct main" description: @@ -1056,14 +1016,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.4" - process_run: - dependency: transitive - description: - name: process_run - sha256: "1142d7f4f0c3f36393a1319406efcf481def2b6d862b2bf600c8ae8fa74d5bd8" - url: "https://pub.dev" - source: hosted - version: "0.12.5+2" provider: dependency: transitive description: @@ -1381,14 +1333,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tint: - dependency: transitive - description: - name: tint - sha256: "9652d9a589f4536d5e392cf790263d120474f15da3cf1bee7f1fdb31b4de5f46" - url: "https://pub.dev" - source: hosted - version: "2.0.1" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 023288c7..43967b5d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,7 +29,6 @@ dependencies: flutter_bloc: ^8.1.1 flutter_dotenv: ^5.0.2 freezed_annotation: ^2.2.0 - fvm: ^2.4.1 get_it: ^7.2.0 http: ^0.13.5 image: ^3.2.2 @@ -68,8 +67,6 @@ dev_dependencies: lint: ^2.0.1 widgetbook: ^2.4.1 widgetbook_generator: ^2.4.1 -dependency_overrides: - firebase_core_platform_interface: 4.5.1 flutter_icons: android: true @@ -103,4 +100,4 @@ flutter: - asset: assets/fonts/Rubik/Rubik-Medium.ttf weight: 400 - asset: assets/fonts/Rubik/Rubik-Light.ttf - weight: 300 + weight: 300 \ No newline at end of file From 88a9f1b5a6e6c4f3edb0a1e593917208e9144863 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Tue, 14 Feb 2023 19:50:38 +0200 Subject: [PATCH 14/19] Solving the the inconsistencies. --- lib/infrastructure/core/injection.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/infrastructure/core/injection.dart b/lib/infrastructure/core/injection.dart index 535b983b..98ad4f10 100644 --- a/lib/infrastructure/core/injection.dart +++ b/lib/infrastructure/core/injection.dart @@ -8,5 +8,4 @@ final GetIt getIt = GetIt.instance; @injectableInit void configureInjection() { getIt.init(); - } From 061f6e80f13b2840052902e00619b6d11bd029fa Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sat, 4 Mar 2023 21:09:30 +0200 Subject: [PATCH 15/19] Deleting settings folder at the testing part --- .env.example | 5 - lib/application/auth/auth_bloc.dart | 2 + lib/presentation/demo/demo_screen.dart | 1 + lib/presentation/home/home_screen.dart | 6 +- .../build_information_tile_test.dart | 2 +- .../settings/settings_layout_test.dart | 45 --- .../settings/settings_layout_test.ext.dart | 15 - .../settings/settings_list_tile_test.dart | 28 -- .../settings/settings_screen_test.dart | 262 ------------------ .../settings/settings_screen_test.ext.dart | 25 -- .../share_collaction_list_tile_test.dart | 40 --- 11 files changed, 8 insertions(+), 423 deletions(-) delete mode 100644 .env.example rename test/presentation/{settings => menu}/build_information_tile_test.dart (93%) delete mode 100644 test/presentation/settings/settings_layout_test.dart delete mode 100644 test/presentation/settings/settings_layout_test.ext.dart delete mode 100644 test/presentation/settings/settings_list_tile_test.dart delete mode 100644 test/presentation/settings/settings_screen_test.dart delete mode 100644 test/presentation/settings/settings_screen_test.ext.dart delete mode 100644 test/presentation/settings/share_collaction_list_tile_test.dart diff --git a/.env.example b/.env.example deleted file mode 100644 index 4bf673e2..00000000 --- a/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -ENV = development - -# Full base URL including protocol (http or https), host and optionally the port and the base api path without trailing forward slash -BASE_API_ENDPOINT_URL = -BASE_STATIC_ENDPOINT_URL = diff --git a/lib/application/auth/auth_bloc.dart b/lib/application/auth/auth_bloc.dart index fb746907..f54a0a79 100644 --- a/lib/application/auth/auth_bloc.dart +++ b/lib/application/auth/auth_bloc.dart @@ -14,7 +14,9 @@ import '../../domain/user/i_user_repository.dart'; import '../../domain/user/user.dart'; part 'auth_bloc.freezed.dart'; + part 'auth_event.dart'; + part 'auth_state.dart'; @injectable diff --git a/lib/presentation/demo/demo_screen.dart b/lib/presentation/demo/demo_screen.dart index 26412a7f..9188a681 100644 --- a/lib/presentation/demo/demo_screen.dart +++ b/lib/presentation/demo/demo_screen.dart @@ -9,6 +9,7 @@ import 'components_demo/current_user_status_text.dart'; class DemoPage extends StatelessWidget { DemoPage({super.key}); + final settingsRepository = getIt(); final _pageScrollController = ScrollController(); diff --git a/lib/presentation/home/home_screen.dart b/lib/presentation/home/home_screen.dart index 4cc0cf81..4e61ff52 100644 --- a/lib/presentation/home/home_screen.dart +++ b/lib/presentation/home/home_screen.dart @@ -31,7 +31,7 @@ class HomePage extends StatelessWidget { unselectedItemColor: kDisabledButtonColor, type: BottomNavigationBarType.fixed, elevation: 0, - items: [ + items: [ BottomNavigationBarItem( icon: Icon(CollactionIcons.collaction), label: '', @@ -49,7 +49,9 @@ class HomePage extends StatelessWidget { ), ], BottomNavigationBarItem( - icon: Icon(Icons.grid_view,), + icon: Icon( + Icons.grid_view, + ), label: '', ), ], diff --git a/test/presentation/settings/build_information_tile_test.dart b/test/presentation/menu/build_information_tile_test.dart similarity index 93% rename from test/presentation/settings/build_information_tile_test.dart rename to test/presentation/menu/build_information_tile_test.dart index b9d4b315..38b45191 100644 --- a/test/presentation/settings/build_information_tile_test.dart +++ b/test/presentation/menu/build_information_tile_test.dart @@ -1,5 +1,5 @@ import 'package:collaction_app/domain/settings/build_information.dart'; -import 'package:collaction_app/presentation/settings/widgets/build_information_tile.dart'; +import 'package:collaction_app/presentation/menu/widgets/build_information_tile.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../test_helper.dart'; diff --git a/test/presentation/settings/settings_layout_test.dart b/test/presentation/settings/settings_layout_test.dart deleted file mode 100644 index bdf4dfe0..00000000 --- a/test/presentation/settings/settings_layout_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:collaction_app/presentation/settings/settings_layout.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mocktail/mocktail.dart'; - -import '../router.mocks.dart'; - -part 'settings_layout_test.ext.dart'; - -void main() { - late StackRouter stackRouter; - - setUpAll(() { - stackRouter = RouteHelpers.setUpRouterStubs(); - }); - - group('SettingsLayout tests:', () { - testWidgets('can render', (WidgetTester tester) async { - await tester.pumpSettingsLayout(stackRouter); - await tester.pumpAndSettle(); - - expect(find.byType(SettingsLayout), findsOneWidget); - }); - - testWidgets('back ElevatedButton works', (WidgetTester tester) async { - await tester.pumpSettingsLayout(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.byType(ElevatedButton)); - final capturedPops = verify(() => stackRouter.pop()).callCount; - - expect(capturedPops, 1); - }); - - testWidgets('back RawMaterialButton works', (WidgetTester tester) async { - await tester.pumpSettingsLayout(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.byType(RawMaterialButton)); - final capturedPops = verify(() => stackRouter.pop()); - expect(capturedPops.callCount, 1); - }); - }); -} diff --git a/test/presentation/settings/settings_layout_test.ext.dart b/test/presentation/settings/settings_layout_test.ext.dart deleted file mode 100644 index 3998c210..00000000 --- a/test/presentation/settings/settings_layout_test.ext.dart +++ /dev/null @@ -1,15 +0,0 @@ -part of 'settings_layout_test.dart'; - -extension WidgetX on WidgetTester { - Future pumpSettingsLayout([ - StackRouter? stackRouter, - ]) async { - await pumpWidget( - MaterialApp( - home: Scaffold( - body: SettingsLayout(), - ), - ).withRouterScope(stackRouter), - ); - } -} diff --git a/test/presentation/settings/settings_list_tile_test.dart b/test/presentation/settings/settings_list_tile_test.dart deleted file mode 100644 index 0a5db946..00000000 --- a/test/presentation/settings/settings_list_tile_test.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:collaction_app/presentation/settings/widgets/settings_list_tile.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../../test_helper.dart'; - -void main() { - group('SettingsListTile tests', () { - testWidgets('onTap', (WidgetTester tester) async { - int counter = 0; - - await buildAndPump( - tester: tester, - widget: SettingsListTile( - title: 'title', - icon: Icons.abc, - onTap: () => counter++, - ), - ); - - await tester.pumpAndSettle(); - - expect(counter, 0); - await tester.tap(find.byType(SettingsListTile)); - expect(counter, 1); - }); - }); -} diff --git a/test/presentation/settings/settings_screen_test.dart b/test/presentation/settings/settings_screen_test.dart deleted file mode 100644 index 6e87405a..00000000 --- a/test/presentation/settings/settings_screen_test.dart +++ /dev/null @@ -1,262 +0,0 @@ -import 'dart:io'; - -import 'package:auto_route/auto_route.dart'; -import 'package:collaction_app/application/auth/auth_bloc.dart'; -import 'package:collaction_app/application/settings/build_information/build_information_bloc.dart'; -import 'package:collaction_app/application/user/profile/profile_bloc.dart'; -import 'package:collaction_app/domain/settings/build_information.dart'; -import 'package:collaction_app/infrastructure/core/injection.dart'; -import 'package:collaction_app/presentation/routes/app_routes.gr.dart'; -import 'package:collaction_app/presentation/settings/settings_screen.dart'; -import 'package:collaction_app/presentation/settings/widgets/build_information_tile.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:get_it/get_it.dart'; -import 'package:mocktail/mocktail.dart'; - -import '../../application/auth/auth_bloc.mocks.dart'; -import '../../application/settings/build_information_bloc.mocks.dart'; -import '../../application/user/profile/profile_bloc.mocks.dart'; -import '../../utils/user.fixtures.dart'; -import '../router.mocks.dart'; - -part 'settings_screen_test.ext.dart'; - -void main() { - late StackRouter stackRouter; - late AuthBloc authBloc; - late ProfileBloc profileBloc; - late BuildInformationBloc buildInformationBloc; - - final channels = [ - MethodChannel( - Platform.isLinux - ? 'plugins.flutter.io/url_launcher_linux' - : Platform.isWindows - ? 'plugins.flutter.io/url_launcher_windows' - : 'plugins.flutter.io/url_launcher_macos', - ), - MethodChannel('plugins.flutter.io/url_launcher') - ]; - - setUp(() async { - for (final channel in channels) { - channel.setMockMethodCallHandler((MethodCall methodCall) async { - return methodCall.method == 'canLaunch' ? true : null; - }); - } - }); - - tearDown(() { - for (final channel in channels) { - channel.setMockMethodCallHandler(null); - } - }); - - setUpAll(() { - stackRouter = RouteHelpers.setUpRouterStubs(); - - // Auth Bloc - authBloc = MockAuthBloc(); - when(() => authBloc.state).thenAnswer((_) => AuthState.initial()); - GetIt.I.registerSingleton(authBloc); - - // Profile Bloc - profileBloc = MockProfileBloc(); - when(() => profileBloc.state).thenAnswer((_) => ProfileState.initial()); - GetIt.I.registerSingleton(profileBloc); - registerFallbackValue(GetUserProfile()); - - // Build Information Bloc - buildInformationBloc = MockBuildInformationBloc(); - when(() => buildInformationBloc.state).thenAnswer( - (_) => BuildInformationState.fetched( - BuildInformation( - buildNumber: 'tBuildNumber', - version: 'tVersion', - ), - ), - ); - GetIt.I.registerSingleton(buildInformationBloc); - }); - - tearDownAll(() { - GetIt.I.unregister(); - GetIt.I.unregister(); - GetIt.I.unregister(); - }); - - group('SettingsPage tests:', () { - testWidgets('can render', (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect(find.byType(SettingsPage), findsOneWidget); - }); - - testWidgets('onTap, "Contact Us" button routes to ContactForm', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.text('Contact us')); - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - }); - - testWidgets('onTap, "Onboarding" button routes to Onboarding', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.text('Onboarding')); - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - }); - - testWidgets('onTap, "Open source libraries" button routes to Licenses', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.tap(find.text('Open source libraries')); - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - }); - - testWidgets('onTap, "Terms of use" button opens terms webpage', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.runAsync(() async { - await tester.tap(find.text('Terms of use')); - await tester.pumpAndSettle(); - }); - - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - - final route = capturedRoutes.first as WebViewRoute; - expect(route.args?.url, 'https://www.collaction.org/terms'); - }); - - testWidgets('onTap, "Privacy policy" button opens privacy webpage', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.runAsync(() async { - await tester.scrollUntilVisible( - find.text( - 'Privacy policy', - skipOffstage: false, - ), - 15, - ); - await tester.tap(find.text('Privacy policy')); - await tester.pumpAndSettle(); - }); - - final capturedRoutes = verify( - () => stackRouter.push(captureAny()), - ).captured; - - expect(capturedRoutes.length, 1); - expect(capturedRoutes.first, isA()); - - final route = capturedRoutes.first as WebViewRoute; - expect(route.args?.url, 'https://www.collaction.org/privacy'); - }); - - testWidgets('"Log out" button not available when not logged in', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect( - find.text( - 'Log out', - skipOffstage: false, - ), - findsNothing, - ); - }); - - testWidgets('onTap, "Log out" button starts logout event', - (WidgetTester tester) async { - when(() => profileBloc.state) - .thenAnswer((_) => ProfileState(userProfile: testUserProfile)); - - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - await tester.scrollUntilVisible( - find.text( - 'Log out', - skipOffstage: false, - ), - 15, - ); - await tester.tap(find.text('Log out')); - - final capturedPops = verify(() => stackRouter.pop()); - expect(capturedPops.callCount, 1); - - verify(() => authBloc.add(AuthEvent.signedOut())); - - final profileEvents = verify(() => profileBloc.add(any())); - expect(profileEvents.callCount, 1); - }); - - testWidgets('BuildInformationTile renders when fetched', - (WidgetTester tester) async { - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect( - find.byType( - BuildInformationTile, - skipOffstage: false, - ), - findsOneWidget, - ); - }); - - testWidgets('BuildInformationTile does not render when loading', - (WidgetTester tester) async { - when(() => buildInformationBloc.state).thenAnswer( - (_) => BuildInformationState.loading(), - ); - - await tester.pumpSettingsPage(stackRouter); - await tester.pumpAndSettle(); - - expect( - find.byType( - BuildInformationTile, - skipOffstage: false, - ), - findsNothing, - ); - }); - }); -} diff --git a/test/presentation/settings/settings_screen_test.ext.dart b/test/presentation/settings/settings_screen_test.ext.dart deleted file mode 100644 index ff0d65bf..00000000 --- a/test/presentation/settings/settings_screen_test.ext.dart +++ /dev/null @@ -1,25 +0,0 @@ -part of 'settings_screen_test.dart'; - -extension WidgetX on WidgetTester { - Future pumpSettingsPage([ - StackRouter? stackRouter, - ]) async { - await pumpWidget( - MaterialApp( - home: Scaffold( - body: MultiBlocProvider( - providers: [ - BlocProvider( - create: (_) => getIt(), - ), - BlocProvider( - create: (_) => getIt(), - ), - ], - child: SettingsPage(), - ), - ), - ).withRouterScope(stackRouter), - ); - } -} diff --git a/test/presentation/settings/share_collaction_list_tile_test.dart b/test/presentation/settings/share_collaction_list_tile_test.dart deleted file mode 100644 index 8febe882..00000000 --- a/test/presentation/settings/share_collaction_list_tile_test.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:collaction_app/presentation/settings/widgets/share_collaction_list_tile.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../../test_helper.dart'; - -void main() { - group('ShareCollActionListTile tests', () { - testWidgets('can render', (WidgetTester tester) async { - await buildAndPump(tester: tester, widget: ShareCollactionListTile()); - await tester.pumpAndSettle(); - - expect(find.byType(ShareCollactionListTile), findsOneWidget); - }); - - testWidgets('state', (WidgetTester tester) async { - await buildAndPump(tester: tester, widget: ShareCollactionListTile()); - await tester.pumpAndSettle(); - - expect(find.byType(ShareCollactionListTile), findsOneWidget); - - await tester.tap(find.byType(ShareCollactionListTile)); - await tester.pumpAndSettle(const Duration(seconds: 1)); - }); - - testWidgets('onFocusChange', (WidgetTester tester) async { - final ShareCollactionListTile shareCollactionButton = - ShareCollactionListTile(); - - await buildAndPump(tester: tester, widget: shareCollactionButton); - await tester.pumpAndSettle(); - - final state = tester.state( - find.byType(ShareCollactionListTile), - ); - - state.onFocusChange(true); - state.onFocusChange(false); - }); - }); -} From f727c0ceb8719b1dceb416792dc9173d48241797 Mon Sep 17 00:00:00 2001 From: Mathias Mogensen Date: Thu, 16 Mar 2023 08:18:56 +0100 Subject: [PATCH 16/19] refactor: amend according to design, fix connecitivty, remove redundancy, make readable --- .env.example | 5 + .../build_information_bloc.dart | 2 - .../i_participation_repository.dart | 3 +- lib/infrastructure/core/page_info_dto.dart | 2 +- .../crowdaction/crowdaction_repository.dart | 2 - .../paginated_crowdactions_dto.dart | 2 +- .../auth/unauthenticated_screen.dart | 4 +- .../components_demo_screen.dart | 8 +- lib/presentation/menu/menu_screen.dart | 326 +++++++----------- .../menu/widgets/avatar_info.dart | 76 ++-- .../menu/widgets/build_information_tile.dart | 109 +++--- .../menu/widgets/ca_menu_item.dart | 65 ++++ lib/presentation/menu/widgets/header_bar.dart | 10 +- .../widgets/legal_info_policy_widget.dart | 53 --- .../menu/widgets/menu_category.dart | 26 ++ .../menu/widgets/menu_subtitle.dart | 27 ++ .../menu/widgets/user_info_and_avatar.dart | 51 +-- lib/presentation/profile/profile_screen.dart | 8 +- .../profile/widget/profile_picture.dart | 3 +- lib/presentation/routes/app_routes.dart | 2 +- lib/presentation/themes/constants.dart | 19 - .../menu/build_information_tile_test.dart | 52 ++- 22 files changed, 418 insertions(+), 437 deletions(-) create mode 100644 .env.example create mode 100644 lib/presentation/menu/widgets/ca_menu_item.dart delete mode 100644 lib/presentation/menu/widgets/legal_info_policy_widget.dart create mode 100644 lib/presentation/menu/widgets/menu_category.dart create mode 100644 lib/presentation/menu/widgets/menu_subtitle.dart diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..f2888839 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +ENV = development + +# Full base URL including protocol (http or https), host and optionally the port and the base api path without trailing forward slash +BASE_API_ENDPOINT_URL = +BASE_STATIC_ENDPOINT_URL = \ No newline at end of file diff --git a/lib/application/settings/build_information/build_information_bloc.dart b/lib/application/settings/build_information/build_information_bloc.dart index c07dad77..daadbb35 100644 --- a/lib/application/settings/build_information/build_information_bloc.dart +++ b/lib/application/settings/build_information/build_information_bloc.dart @@ -19,8 +19,6 @@ class BuildInformationBloc on((event, emit) async { await event.when( fetch: () async { - emit(const BuildInformationState.loading()); - final buildInfo = await _settingsRepository.getBuildInformation(); emit(BuildInformationState.fetched(buildInfo)); }, diff --git a/lib/domain/participation/i_participation_repository.dart b/lib/domain/participation/i_participation_repository.dart index 1e8280d9..d6fcebc4 100644 --- a/lib/domain/participation/i_participation_repository.dart +++ b/lib/domain/participation/i_participation_repository.dart @@ -1,7 +1,8 @@ +import 'package:dartz/dartz.dart'; + import 'paginated_participations.dart'; import 'participation.dart'; import 'participation_failures.dart'; -import 'package:dartz/dartz.dart'; abstract class IParticipationRepository { Future> getParticipation({ diff --git a/lib/infrastructure/core/page_info_dto.dart b/lib/infrastructure/core/page_info_dto.dart index 90c2be6e..88d9b293 100644 --- a/lib/infrastructure/core/page_info_dto.dart +++ b/lib/infrastructure/core/page_info_dto.dart @@ -2,8 +2,8 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import '../../domain/core/page_info.dart'; -part 'page_info_dto.g.dart'; part 'page_info_dto.freezed.dart'; +part 'page_info_dto.g.dart'; @freezed class PageInfoDto with _$PageInfoDto { diff --git a/lib/infrastructure/crowdaction/crowdaction_repository.dart b/lib/infrastructure/crowdaction/crowdaction_repository.dart index 0c8e948e..841117d5 100644 --- a/lib/infrastructure/crowdaction/crowdaction_repository.dart +++ b/lib/infrastructure/crowdaction/crowdaction_repository.dart @@ -9,12 +9,10 @@ import '../../domain/auth/i_auth_repository.dart'; import '../../domain/core/i_settings_repository.dart'; import '../../domain/crowdaction/crowdaction.dart'; import '../../domain/crowdaction/crowdaction_failures.dart'; - import '../../domain/crowdaction/i_crowdaction_repository.dart'; import '../../domain/crowdaction/paginated_crowdactions.dart'; import '../core/page_info_dto.dart'; import 'crowdaction_dto.dart'; - import 'paginated_crowdactions_dto.dart'; @LazySingleton(as: ICrowdActionRepository) diff --git a/lib/infrastructure/crowdaction/paginated_crowdactions_dto.dart b/lib/infrastructure/crowdaction/paginated_crowdactions_dto.dart index b5b0187d..0b72668d 100644 --- a/lib/infrastructure/crowdaction/paginated_crowdactions_dto.dart +++ b/lib/infrastructure/crowdaction/paginated_crowdactions_dto.dart @@ -4,8 +4,8 @@ import '../../domain/crowdaction/paginated_crowdactions.dart'; import '../core/page_info_dto.dart'; import 'crowdaction_dto.dart'; -part 'paginated_crowdactions_dto.g.dart'; part 'paginated_crowdactions_dto.freezed.dart'; +part 'paginated_crowdactions_dto.g.dart'; @freezed class PaginatedCrowdActionsDto with _$PaginatedCrowdActionsDto { diff --git a/lib/presentation/auth/unauthenticated_screen.dart b/lib/presentation/auth/unauthenticated_screen.dart index f5e91a29..4cd5ff0a 100644 --- a/lib/presentation/auth/unauthenticated_screen.dart +++ b/lib/presentation/auth/unauthenticated_screen.dart @@ -1,11 +1,11 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import '../../domain/core/i_settings_repository.dart'; +import '../../infrastructure/core/injection.dart'; import '../routes/app_routes.gr.dart'; import '../shared_widgets/pill_button.dart'; import '../themes/constants.dart'; -import '../../domain/core/i_settings_repository.dart'; -import '../../infrastructure/core/injection.dart'; class UnauthenticatedPage extends StatelessWidget { @override diff --git a/lib/presentation/demo/components_demo/components_demo_screen.dart b/lib/presentation/demo/components_demo/components_demo_screen.dart index c89d83b6..8e07cae0 100644 --- a/lib/presentation/demo/components_demo/components_demo_screen.dart +++ b/lib/presentation/demo/components_demo/components_demo_screen.dart @@ -2,6 +2,10 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../../../domain/crowdaction/crowdaction.dart'; +import '../../crowdaction/crowdaction_comments/widgets/comment_delete_button.dart'; +import '../../crowdaction/crowdaction_comments/widgets/comment_flag_button.dart'; +import '../../crowdaction/crowdaction_comments/widgets/comment_like_button.dart'; +import '../../crowdaction/crowdaction_comments/widgets/flag_comment.dart'; import '../../shared_widgets/accent_chip.dart'; import '../../shared_widgets/crowdaction_card.dart'; import '../../shared_widgets/custom_app_bars/clean_app_bar.dart'; @@ -9,10 +13,6 @@ import '../../shared_widgets/custom_fab.dart'; import '../../shared_widgets/pill_button.dart'; import '../../shared_widgets/rectangle_button.dart'; import '../../shared_widgets/secondary_chip.dart'; -import '../../crowdaction/crowdaction_comments/widgets/comment_delete_button.dart'; -import '../../crowdaction/crowdaction_comments/widgets/comment_like_button.dart'; -import '../../crowdaction/crowdaction_comments/widgets/comment_flag_button.dart'; -import '../../crowdaction/crowdaction_comments/widgets/flag_comment.dart'; import '../../themes/constants.dart'; class ComponentsDemoPage extends StatefulWidget { diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index 61320857..de738848 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -1,19 +1,18 @@ import 'package:auto_route/auto_route.dart'; -import 'widgets/build_information_tile.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:ionicons/ionicons.dart'; import '../../application/auth/auth_bloc.dart'; -import '../../application/settings/build_information/build_information_bloc.dart'; import '../../application/user/profile/profile_bloc.dart'; -import '../../infrastructure/core/injection.dart'; +import '../core/collaction_icons.dart'; import '../routes/app_routes.gr.dart'; +import '../themes/constants.dart'; import '../utils/launch_url.dart'; -import 'widgets/avatar_info.dart'; +import 'widgets/build_information_tile.dart'; +import 'widgets/ca_menu_item.dart'; import 'widgets/header_bar.dart'; -import 'widgets/legal_info_policy_widget.dart'; -import 'package:flutter/material.dart'; -import '../themes/constants.dart'; -import '../core/collaction_icons.dart'; +import 'widgets/menu_category.dart'; import 'widgets/user_info_and_avatar.dart'; class MenuPage extends StatelessWidget { @@ -24,225 +23,146 @@ class MenuPage extends StatelessWidget { return Scaffold( body: SafeArea( child: SingleChildScrollView( + // TODO: Have it's own BLoC child: BlocProvider.value( value: BlocProvider.of(context), child: BlocBuilder( - builder: (context, state) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: - const EdgeInsets.only(left: 20, top: 10, right: 22.5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - HeaderBar(), - UserInfoAndAvatar( - pictureUrl: state.userProfile?.profile.avatar, - name: state.userProfile?.profile.firstName, - ), - SizedBox( - height: 30, - ), - SizedBox( - height: 18, - ), - GestureDetector( - onTap: () async { - BlocProvider.of(context) - .add(const AuthEvent.signedOut()); - BlocProvider.of(context) - .add(GetUserProfile()); - await context.router.pop(); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.logout, - color: kErrorColor, - ), - SizedBox( - width: 2.5, - ), - Text( - "Log out", - style: TextStyle( - color: kErrorColor, - fontSize: 15, - fontWeight: FontWeight.w700, - ), - ) - ], - ), - ), - ], - ), - ), - _buildSubTitle( - subTitle: "Account", - paddingTop: 38.5, - paddingBottom: 20, - ), - Padding( - padding: const EdgeInsets.only(left: 22.25), - child: GestureDetector( - onTap: () {}, - child: Row( + builder: (context, state) { + if (state.userProfile == null) { + // TODO: Loading state + return const Center(child: CircularProgressIndicator()); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20) + + const EdgeInsets.only(top: 10, bottom: 6), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Icon( - Icons.account_circle, - color: kPrimaryColor300, - size: 19.5, + HeaderBar(), + const SizedBox(height: 30), + UserInfoAndAvatar( + avatar: state.userProfile!.profile.avatar, + fullName: state.userProfile!.profile.fullName, ), - SizedBox( - width: 12.25, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Account Information", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 306, - child: Text( - "View and update your account and contact information that is associated with your CollAction account.", + SizedBox(height: 16), + // TODO: Extract Logout button to widget + GestureDetector( + onTap: () async { + BlocProvider.of(context) + .add(const AuthEvent.signedOut()); + BlocProvider.of(context) + .add(GetUserProfile()); + await context.router.pop(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.logout, + color: kErrorColor, size: 20), + SizedBox(width: 10), + Text( + "Log out", style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], - ) + color: kErrorColor, + fontSize: 16, + fontWeight: FontWeight.w700, + ), + ) + ], + ), + ), ], ), ), - ), - _buildSubTitle( - subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), - Padding( - padding: const EdgeInsets.only( - left: 22.5, + MenuCategory( + label: 'Account', + items: [ + CAMenuItem( + icon: Icon( + Ionicons.person_circle_outline, + color: kPrimaryColor300, + ), + label: "Account Information", + description: + "View and update your account and contact information that is associated with your CollAction account.", + onTap: () { + // TODO: Open Account Information Page + }, + ), + ], ), - child: GestureDetector( - onTap: () {}, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( + MenuCategory( + label: 'Feedback', + items: [ + CAMenuItem( + icon: Icon( CollactionIcons.message, + size: 20, color: kPrimaryColor300, - size: 15, ), - SizedBox( - width: 16.25, + label: "Contact us", + description: + "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", + onTap: () { + // TODO: Open Contact Us Full-screen Dialog + }, + ), + ], + ), + MenuCategory( + label: 'Legal information and policies', + items: [ + CAMenuItem( + icon: Icon( + CollactionIcons.lock, + size: 20, + color: kPrimaryColor300, ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Contact us", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300), - ), - SizedBox( - height: 5, - ), - SizedBox( - width: 305, - child: Text( - "Have a general enquiry, business proposal, or simply want us to send your feedback or regards? Get in contact with us through our form.", - style: TextStyle( - fontSize: 12, - color: kPrimaryColor300, - fontWeight: FontWeight.w400), - ), - ), - ], + label: "Privacy Policy", + onTap: () => launchUrl( + 'https://www.collaction.org/privacy', + useWebView: true, + context: context, ), - ], - ), - ), - ), - _buildSubTitle( - subTitle: "Legal information and policies", - paddingBottom: 24, - paddingTop: 30), - LegalInfoAndPoliciesWidget( - onTap: () async { - launchUrl( - 'https://www.collaction.org/privacy', - useWebView: true, - context: context, - ); - }, - iconWidget: CollactionIcons.lock, - label: "Privacy Policy"), - LegalInfoAndPoliciesWidget( - onTap: () => launchUrl( + ), + CAMenuItem( + icon: Icon( + CollactionIcons.file, + size: 20, + color: kPrimaryColor300, + ), + label: "Terms & conditions", + onTap: () => launchUrl( 'https://www.collaction.org/terms', useWebView: true, context: context, ), - iconWidget: CollactionIcons.file, - label: "Terms & conditions"), - LegalInfoAndPoliciesWidget( - onTap: () => context.router.push(const LicensesRoute()), - iconWidget: CollactionIcons.opensource, - label: "Open-source libraries"), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - BlocBuilder( - bloc: getIt() - ..add(const BuildInformationEvent.fetch()), - builder: (context, state) { - return state.when( - loading: () => const SizedBox(), - fetched: (buildInfo) => - BuildInformationTile(information: buildInfo), - ); - }, - ), - ], - ) - ], - ), + ), + CAMenuItem( + icon: Icon( + CollactionIcons.opensource, + size: 20, + color: kPrimaryColor300, + ), + label: "Open-source libraries", + onTap: () => + context.router.push(const LicensesRoute()), + ), + ], + ), + const SizedBox(height: 10), + Center(child: BuildInformationTile()), + ], + ); + }, ), ), ), ), ); } - - Widget _buildSubTitle({ - required String subTitle, - double paddingTop = 0.0, - double paddingBottom = 0.0, - }) { - return Padding( - padding: - EdgeInsets.only(left: 20, top: paddingTop, bottom: paddingBottom), - child: Text( - subTitle, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: kPrimaryColor300, - ), - ), - ); - } } diff --git a/lib/presentation/menu/widgets/avatar_info.dart b/lib/presentation/menu/widgets/avatar_info.dart index e93319eb..9fedb4a7 100644 --- a/lib/presentation/menu/widgets/avatar_info.dart +++ b/lib/presentation/menu/widgets/avatar_info.dart @@ -1,38 +1,18 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import '../../../domain/user/i_user_repository.dart'; -import '../../../domain/user/user.dart'; -import '../../../infrastructure/core/injection.dart'; import '../../profile/widget/profile_picture.dart'; import '../../themes/constants.dart'; -class AvatarAndInfo extends StatefulWidget { - final String? pictureUrl; - final String? name; +class AvatarAndInfo extends StatelessWidget { + final String fullName; + final String phoneNumber; + final String? avatar; const AvatarAndInfo({ - Key? key, - required this.pictureUrl, - required this.name, - }) : super(key: key); - - @override - State createState() => _AvatarAndInfoState(); -} - -class _AvatarAndInfoState extends State { - late final IUserRepository _userRepository; - File? _image; - late String number; - - @override - void initState() { - super.initState(); - _userRepository = getIt(); - } + required this.fullName, + required this.phoneNumber, + this.avatar, + }); @override Widget build(BuildContext context) { @@ -40,34 +20,30 @@ class _AvatarAndInfoState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ ProfilePicture( - image: _image, - profileImage: widget.pictureUrl != null - ? '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${widget.pictureUrl}' - : null, - maxRadius: 50, - ), - SizedBox( - width: 10, + profileImage: avatar, + maxRadius: 32.5, ), + SizedBox(width: 10), Column( - mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.name ?? "", - style: nameTextStyle, + fullName, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: kPrimaryColor400, + ), ), - StreamBuilder( - builder: (context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - number = snapshot.data!.phoneNumber ?? 'no phone number'; - } - return Text( - number, - style: phoneNumberTextStyle, - ); - }, - stream: _userRepository.observeUser(), + const SizedBox(height: 5), + // TODO: Use Profile, not firebase? + Text( + phoneNumber, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w300, + color: kPrimaryColor300, + ), ), ], ) diff --git a/lib/presentation/menu/widgets/build_information_tile.dart b/lib/presentation/menu/widgets/build_information_tile.dart index 2d2c575e..552a9fc9 100644 --- a/lib/presentation/menu/widgets/build_information_tile.dart +++ b/lib/presentation/menu/widgets/build_information_tile.dart @@ -1,61 +1,72 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../../domain/settings/build_information.dart'; +import '../../../application/settings/build_information/build_information_bloc.dart'; +import '../../../infrastructure/core/injection.dart'; import '../../themes/constants.dart'; class BuildInformationTile extends StatelessWidget { - final BuildInformation information; - - const BuildInformationTile({super.key, required this.information}); + const BuildInformationTile({super.key}); @override Widget build(BuildContext context) { - return Column( - children: [ - const SizedBox(height: 50), - const SizedBox( - width: 56, - child: Image(image: AssetImage('assets/images/collaction.png')), - ), - const SizedBox(height: 5), - Text( - 'Build ${information.buildNumber}', - style: const TextStyle( - color: kPrimaryColor100, - fontSize: 17, - fontWeight: FontWeight.w300, - ), - ), - const SizedBox(height: 5), - Text( - 'Version ${information.version}', - style: const TextStyle( - color: kPrimaryColor100, - fontSize: 17, - fontWeight: FontWeight.w300, - ), - ), - const SizedBox(height: 5), - const Text( - 'Stichting CollAction', - style: TextStyle( - color: kPrimaryColor100, - fontSize: 17, - fontWeight: FontWeight.w300, - ), - ), - if (information.environment == 'development') ...[ - const SizedBox(height: 5), - Text( - 'Environment ${information.environment!.toUpperCase()}', - style: const TextStyle( - color: kPrimaryColor100, - fontSize: 17, - fontWeight: FontWeight.w300, + return BlocProvider( + create: (context) => getIt() + ..add(const BuildInformationEvent.fetch()), + child: BlocBuilder( + builder: (context, state) { + return state.when( + loading: () => const SizedBox.shrink(), + fetched: (buildInfo) => Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Column( + children: [ + const SizedBox( + width: 120, + child: Image( + image: AssetImage('assets/images/collaction.png')), + ), + const SizedBox(height: 5), + Text( + 'Build ${buildInfo.buildNumber}', + style: const TextStyle( + color: kPrimaryColor100, + fontSize: 17, + fontWeight: FontWeight.w300, + ), + ), + Text( + 'Version ${buildInfo.version}', + style: const TextStyle( + color: kPrimaryColor100, + fontSize: 17, + fontWeight: FontWeight.w300, + ), + ), + const Text( + 'Stichting CollAction', + style: TextStyle( + color: kPrimaryColor100, + fontSize: 17, + fontWeight: FontWeight.w300, + ), + ), + if (buildInfo.environment == 'development') ...[ + Text( + 'Environment ${buildInfo.environment!.toUpperCase()}', + style: const TextStyle( + color: kPrimaryColor100, + fontSize: 17, + fontWeight: FontWeight.w300, + ), + ), + ] + ], + ), ), - ), - ] - ], + ); + }, + ), ); } } diff --git a/lib/presentation/menu/widgets/ca_menu_item.dart b/lib/presentation/menu/widgets/ca_menu_item.dart new file mode 100644 index 00000000..3e98e5c1 --- /dev/null +++ b/lib/presentation/menu/widgets/ca_menu_item.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; + +class CAMenuItem extends StatelessWidget { + final Widget icon; + final String label; + final String? description; + final VoidCallback onTap; + + const CAMenuItem({ + super.key, + required this.icon, + required this.label, + this.description, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 54) + + const EdgeInsets.symmetric(vertical: 10), + child: Row( + crossAxisAlignment: description == null + ? CrossAxisAlignment.center + : CrossAxisAlignment.start, + children: [ + icon, + SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + label, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: kPrimaryColor300, + ), + ), + if (description != null) ...[ + SizedBox(height: 5), + Text( + description!, + style: TextStyle( + fontSize: 12, + color: kPrimaryColor300, + fontWeight: FontWeight.w400, + ), + ), + ], + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/presentation/menu/widgets/header_bar.dart b/lib/presentation/menu/widgets/header_bar.dart index f6a0bdd1..08bd3600 100644 --- a/lib/presentation/menu/widgets/header_bar.dart +++ b/lib/presentation/menu/widgets/header_bar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:ionicons/ionicons.dart'; import '../../themes/constants.dart'; @@ -16,14 +17,17 @@ class HeaderBar extends StatelessWidget { style: TextStyle( fontSize: 28, fontWeight: FontWeight.w700, + color: kPrimaryColor400, ), ), IconButton( - onPressed: () {}, + onPressed: () { + // TODO: Search bar functionality + }, icon: Icon( - Icons.search, + Ionicons.search, color: kPrimaryColor600, - size: 21.08, + size: 26, ), ), ], diff --git a/lib/presentation/menu/widgets/legal_info_policy_widget.dart b/lib/presentation/menu/widgets/legal_info_policy_widget.dart deleted file mode 100644 index 9cb21908..00000000 --- a/lib/presentation/menu/widgets/legal_info_policy_widget.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../themes/constants.dart'; - -class LegalInfoAndPoliciesWidget extends StatefulWidget { - final Function onTap; - final IconData iconWidget; - final String label; - - const LegalInfoAndPoliciesWidget( - {Key? key, - required this.onTap, - required this.iconWidget, - required this.label}) - : super(key: key); - - @override - State createState() => - _LegalInfoAndPoliciesWidgetState(); -} - -class _LegalInfoAndPoliciesWidgetState - extends State { - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 20, bottom: 27.6), - child: InkWell( - onTap: () => widget.onTap(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - widget.iconWidget, - size: 20, - ), - SizedBox( - width: 14, - ), - Text( - widget.label, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: kPrimaryColor300, - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/presentation/menu/widgets/menu_category.dart b/lib/presentation/menu/widgets/menu_category.dart new file mode 100644 index 00000000..2cc0eb1e --- /dev/null +++ b/lib/presentation/menu/widgets/menu_category.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +import 'ca_menu_item.dart'; +import 'menu_subtitle.dart'; + +class MenuCategory extends StatelessWidget { + final String label; + final List items; + + const MenuCategory({ + super.key, + required this.label, + required this.items, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MenuSubtitle(label: label), + ...items, + ], + ); + } +} diff --git a/lib/presentation/menu/widgets/menu_subtitle.dart b/lib/presentation/menu/widgets/menu_subtitle.dart new file mode 100644 index 00000000..98367ab1 --- /dev/null +++ b/lib/presentation/menu/widgets/menu_subtitle.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +import '../../themes/constants.dart'; + +class MenuSubtitle extends StatelessWidget { + final String label; + + const MenuSubtitle({ + super.key, + required this.label, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(left: 20, top: 30, bottom: 10), + child: Text( + label, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w700, + color: kPrimaryColor300, + ), + ), + ); + } +} diff --git a/lib/presentation/menu/widgets/user_info_and_avatar.dart b/lib/presentation/menu/widgets/user_info_and_avatar.dart index eeb1ddf5..b0b345c0 100644 --- a/lib/presentation/menu/widgets/user_info_and_avatar.dart +++ b/lib/presentation/menu/widgets/user_info_and_avatar.dart @@ -4,42 +4,43 @@ import '../../themes/constants.dart'; import 'avatar_info.dart'; class UserInfoAndAvatar extends StatelessWidget { - final String? pictureUrl; + final String? avatar; + final String fullName; - final String? name; - - const UserInfoAndAvatar({Key? key, this.pictureUrl, this.name}) - : super(key: key); + const UserInfoAndAvatar({ + Key? key, + this.avatar, + required this.fullName, + }) : super(key: key); @override Widget build(BuildContext context) { - return Container( - height: 85, - decoration: avatarInfoDecorationBox, + return DecoratedBox( + decoration: BoxDecoration( + color: kAlmostTransparent, + borderRadius: BorderRadius.all(Radius.circular(20)), + ), child: Padding( - padding: EdgeInsets.only( - left: 20, - top: 10, - bottom: 10, - right: 25.5, - ), + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AvatarAndInfo( - pictureUrl: pictureUrl, - name: name, + avatar: avatar, + phoneNumber: '+31 612345678', + fullName: fullName, ), + const Spacer(), GestureDetector( - onTap: () {}, + onTap: () { + // TODO: Open Settings Page + }, child: Container( - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Icon( - Icons.settings, - color: kPrimaryColor600, - size: 21, - ), + height: 36, + width: 36, + child: Icon( + Icons.settings, + color: kPrimaryColor600, + size: 24, ), decoration: BoxDecoration( color: Colors.white, diff --git a/lib/presentation/profile/profile_screen.dart b/lib/presentation/profile/profile_screen.dart index 8f9ee041..f30d4e6a 100644 --- a/lib/presentation/profile/profile_screen.dart +++ b/lib/presentation/profile/profile_screen.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:share_plus/share_plus.dart'; import '../../application/user/profile/profile_bloc.dart'; @@ -94,11 +93,8 @@ class _UserProfilePageState extends State { padding: const EdgeInsets.all(10.0), child: ProfilePicture( image: _image, - profileImage: state - .userProfile?.profile.avatar != - null - ? '${dotenv.get('BASE_STATIC_ENDPOINT_URL')}/${state.userProfile?.profile.avatar}' - : null, + profileImage: + state.userProfile?.profile.avatar, maxRadius: 50, ), ), diff --git a/lib/presentation/profile/widget/profile_picture.dart b/lib/presentation/profile/widget/profile_picture.dart index 7a790567..0fd0b497 100644 --- a/lib/presentation/profile/widget/profile_picture.dart +++ b/lib/presentation/profile/widget/profile_picture.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; class ProfilePicture extends StatelessWidget { final File? image; @@ -23,7 +24,7 @@ class ProfilePicture extends StatelessWidget { if (profileImage != null && imageProvider == null) { imageProvider = NetworkImage( - profileImage!, + "${dotenv.env['BASE_STATIC_ENDPOINT_URL']}/$profileImage", ); } diff --git a/lib/presentation/routes/app_routes.dart b/lib/presentation/routes/app_routes.dart index f5373caa..23aee5ca 100644 --- a/lib/presentation/routes/app_routes.dart +++ b/lib/presentation/routes/app_routes.dart @@ -2,8 +2,8 @@ import 'package:auto_route/auto_route.dart'; import 'package:auto_route/empty_router_widgets.dart'; import '../../../presentation/profile/profile_screen.dart'; -import '../auth/unauthenticated_screen.dart'; import '../auth/auth_screen.dart'; +import '../auth/unauthenticated_screen.dart'; import '../auth/widgets/verified.dart'; import '../contact_form/contact_form_screen.dart'; import '../crowdaction/crowdaction_browse/crowdaction_browse_screen.dart'; diff --git a/lib/presentation/themes/constants.dart b/lib/presentation/themes/constants.dart index 656fae5c..125ebcef 100644 --- a/lib/presentation/themes/constants.dart +++ b/lib/presentation/themes/constants.dart @@ -42,22 +42,3 @@ const TextStyle kTitle1 = TextStyle( height: 34 / 28, fontWeight: FontWeight.w700, ); - -const TextStyle nameTextStyle = TextStyle( - fontSize: 17, - fontWeight: FontWeight.w500, - color: kPrimaryColor400, -); - -const TextStyle phoneNumberTextStyle = TextStyle( - fontSize: 17, - fontWeight: FontWeight.w300, - color: kPrimaryColor300, -); - -const BoxDecoration avatarInfoDecorationBox = BoxDecoration( - color: kAlmostTransparent, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), -); diff --git a/test/presentation/menu/build_information_tile_test.dart b/test/presentation/menu/build_information_tile_test.dart index 38b45191..a589037c 100644 --- a/test/presentation/menu/build_information_tile_test.dart +++ b/test/presentation/menu/build_information_tile_test.dart @@ -1,48 +1,72 @@ +import 'package:collaction_app/application/settings/build_information/build_information_bloc.dart'; import 'package:collaction_app/domain/settings/build_information.dart'; import 'package:collaction_app/presentation/menu/widgets/build_information_tile.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:get_it/get_it.dart'; +import 'package:mocktail/mocktail.dart'; +import '../../application/settings/build_information_bloc.mocks.dart'; import '../../test_helper.dart'; void main() { group('BuildInformationTile tests', () { - testWidgets('With BuildInformation', (WidgetTester tester) async { - await buildAndPump( - tester: tester, - widget: BuildInformationTile( - information: BuildInformation( + late final MockBuildInformationBloc bloc; + + setUpAll(() { + bloc = MockBuildInformationBloc(); + GetIt.I.registerSingleton(bloc); + }); + + tearDownAll(() { + GetIt.I.unregister(); + }); + + testWidgets('With BuildInformation development', + (WidgetTester tester) async { + when(() => bloc.state).thenReturn( + BuildInformationState.fetched( + BuildInformation( version: '1.0.0', buildNumber: '1', - environment: 'test', + environment: 'DEVELOPMENT', ), ), ); + await buildAndPump( + tester: tester, + widget: BuildInformationTile(), + ); + await tester.pumpAndSettle(); expect(find.text('Version 1.0.0'), findsOneWidget); expect(find.text('Build 1'), findsOneWidget); - expect(find.text('Environment TEST'), findsNothing); + expect(find.text('Environment DEVELOPMENT'), findsNothing); }); - testWidgets('With BuildInformation on development', + testWidgets('With BuildInformation on production', (WidgetTester tester) async { - await buildAndPump( - tester: tester, - widget: BuildInformationTile( - information: BuildInformation( + when(() => bloc.state).thenReturn( + BuildInformationState.fetched( + BuildInformation( version: '1.0.0', buildNumber: '1', - environment: 'development', + environment: 'PRODUCTION', ), ), ); + await buildAndPump( + tester: tester, + widget: BuildInformationTile(), + ); + await tester.pumpAndSettle(); expect(find.text('Version 1.0.0'), findsOneWidget); expect(find.text('Build 1'), findsOneWidget); - expect(find.text('Environment DEVELOPMENT'), findsOneWidget); + expect(find.text('Environment PRODUCTION'), findsNothing); }); }); } From 1309fa0a0e40b6d807d0fc472c23ff9d53eaccca Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sat, 15 Apr 2023 00:45:45 +0200 Subject: [PATCH 17/19] Update lib/presentation/menu/menu_screen.dart Co-authored-by: Isaac Obella --- lib/presentation/menu/menu_screen.dart | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index de738848..5980772e 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -42,7 +42,31 @@ class MenuPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - HeaderBar(), + appBar: AppBar( + elevation: 0, + backgroundColor: Colors.transparent, + centerTitle: false, + title: Text( + "Menu", + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.w700, + color: kPrimaryColor400, + ), + ), + actions: [ + IconButton( + onPressed: () { + // TODO: Search bar functionality + }, + icon: Icon( + Ionicons.search, + color: kPrimaryColor600, + size: 26, + ), + ), + ], + ), const SizedBox(height: 30), UserInfoAndAvatar( avatar: state.userProfile!.profile.avatar, From a74ca0bf64b63cb4b2243e57faf24a823fe148c8 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sat, 15 Apr 2023 00:46:39 +0200 Subject: [PATCH 18/19] Update lib/presentation/menu/menu_screen.dart Co-authored-by: Isaac Obella --- lib/presentation/menu/menu_screen.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index 5980772e..b7c1043b 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -37,8 +37,7 @@ class MenuPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 20) + - const EdgeInsets.only(top: 10, bottom: 6), +padding: const EdgeInsets.fromLTRB(20, 10, 20, 6),``` child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ From 0575f6a1b3c309c27a3b44544a35bea627b3d7d7 Mon Sep 17 00:00:00 2001 From: Abdelrhman Yaseen <78448350+AbedrahmanYassen@users.noreply.github.com> Date: Sat, 15 Apr 2023 01:16:14 +0200 Subject: [PATCH 19/19] I have added the .env.example and edited the _subTitle function into a Widget --- .env.example | 5 +++++ lib/presentation/menu/menu_screen.dart | 28 ++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..3df68e3a --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +ENV = development + +# Full base URL including protocol (http or https), host and optionally the port and the base api path without trailing forward slash +BASE_API_ENDPOINT_URL = +BASE_STATIC_ENDPOINT_URL = \ No newline at end of file diff --git a/lib/presentation/menu/menu_screen.dart b/lib/presentation/menu/menu_screen.dart index 61320857..b4cc027a 100644 --- a/lib/presentation/menu/menu_screen.dart +++ b/lib/presentation/menu/menu_screen.dart @@ -79,7 +79,7 @@ class MenuPage extends StatelessWidget { ], ), ), - _buildSubTitle( + Subtitle( subTitle: "Account", paddingTop: 38.5, paddingBottom: 20, @@ -128,7 +128,7 @@ class MenuPage extends StatelessWidget { ), ), ), - _buildSubTitle( + Subtitle( subTitle: "Feedback", paddingTop: 30, paddingBottom: 20), Padding( padding: const EdgeInsets.only( @@ -176,7 +176,7 @@ class MenuPage extends StatelessWidget { ), ), ), - _buildSubTitle( + Subtitle( subTitle: "Legal information and policies", paddingBottom: 24, paddingTop: 30), @@ -226,12 +226,24 @@ class MenuPage extends StatelessWidget { ), ); } +} + +class Subtitle extends StatelessWidget { + final double paddingTop; + + final double paddingBottom; + + final String subTitle; - Widget _buildSubTitle({ - required String subTitle, - double paddingTop = 0.0, - double paddingBottom = 0.0, - }) { + const Subtitle( + {Key? key, + required this.paddingTop, + required this.paddingBottom, + required this.subTitle}) + : super(key: key); + + @override + Widget build(BuildContext context) { return Padding( padding: EdgeInsets.only(left: 20, top: paddingTop, bottom: paddingBottom),