From 5637b3b81b4cad6ae1bf3e28172d02d89731cce2 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:32:23 +0100 Subject: [PATCH 01/68] first commit --- .../presentation/widget/search_filter.dart | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 lib/features/search/presentation/widget/search_filter.dart diff --git a/lib/features/search/presentation/widget/search_filter.dart b/lib/features/search/presentation/widget/search_filter.dart new file mode 100644 index 0000000..74e7cdb --- /dev/null +++ b/lib/features/search/presentation/widget/search_filter.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:neocloud_mobile/components/texts.dart'; +import 'package:neocloud_mobile/constraints.dart'; + +class SearchFilter extends StatelessWidget { + const SearchFilter({ + super.key, + required this.updateIndex, + required this.selectedIndex, + required this.searchFilter, + }); + + final int selectedIndex; + final Function(int index) updateIndex; + final List searchFilter; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.generate( + searchFilter.length, + (index) => GestureDetector( + onTap: () => updateIndex(index), + child: Container( + color: Colors.transparent, + margin: const EdgeInsets.only(top: 10), + padding: index == 0 + ? const EdgeInsets.fromLTRB( + 40, + 10, + 18, + 10, + ) + : const EdgeInsets.symmetric( + horizontal: 18, + vertical: 10, + ), + child: TextMedium( + title: searchFilter[index], + color: selectedIndex == index ? kBlack90 : kBlack50, + weight: selectedIndex == index + ? FontWeight.w600 + : FontWeight.w500, + ), + ), + ), + ), + ), + ), + Divider(color: kBlack.withOpacity(.3)), + ], + ); + } +} From 541e820c0bc3cf7e481deac2a7c8ae6dcded8c40 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:32:28 +0100 Subject: [PATCH 02/68] first commit --- .../data_sources/remote/search_service.dart | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 lib/features/search/data/data_sources/remote/search_service.dart diff --git a/lib/features/search/data/data_sources/remote/search_service.dart b/lib/features/search/data/data_sources/remote/search_service.dart new file mode 100644 index 0000000..ececc2f --- /dev/null +++ b/lib/features/search/data/data_sources/remote/search_service.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:neocloud_mobile/app_secure_storage.dart'; +import 'package:neocloud_mobile/components/popups/popups.dart'; +import 'package:neocloud_mobile/graphql/graphql_config.dart'; +import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; +import 'package:graphql_flutter/graphql_flutter.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; +import 'package:neocloud_mobile/utils/error_handler.dart'; + + +class SearchService { + static var config = GraphQLConfig(); + var client = config.client; + + Future> getUsers({int? limit, String? name}) async { + String usersQuery = """ + query Query(\$limit: Int, \$userName: String) { + users(name: \$userName, limit: \$limit) { + _id + name + bio + avatar + cover + email + phone + role { + _id + name + } + } + } + """; + + try { + print('TOKEN BEFORE'); + print(await AppSecureStorage.getToken()); + // print(await client.value); + + var result = await client.value.query(QueryOptions( + document: gql(usersQuery), + variables: {'limit': limit, 'userName': name}, + )); + + print('TOKEN AFTER'); + print(await AppSecureStorage.getToken()); + + print('RESULT:'); + print(result); + + if (result.hasException) { + debugPrint("getUsers Status: ❌❌"); + String error = await handleErrors(result); + if (error == 'jwt expired') { + return await getUsers(limit: limit, name: name); + } + return []; + + } else { + debugPrint("getUsers Status: ✅"); + + List? users = result.data?['users']; + + if (users == null) []; + + List userList = + users!.map((user) => UserModel.fromMap(user: user)).toList(); + + print(userList); + + return userList; + } + } catch (e) { + debugPrint("getUsers Status: ❌"); + showTopAlertDialog(text: 'Something went wrong!'); + throw Exception(e); + } + } + + Future> getClasses({int? limit, String? name}) async { + String classesQuery = """ + query Query(\$limit: Int, \$className: String) { + classes(limit: \$limit, name: \$className) { + _id + name + about + avatar + faculty { + _id + name + hod { + _id + name + } + } + educators { + _id + name + } + } + } + """; + + try { + var result = await client.value.query(QueryOptions( + document: gql(classesQuery), + variables: {'limit': limit, 'className': name}, + )); + + if (result.hasException) { + debugPrint("getClasses Status: ❌❌"); + String error = await handleErrors(result); + if (error == 'jwt expired') { + return await getClasses(limit: limit, name: name); + } + return []; + + } else { + debugPrint("getClasses Status: ✅"); + + List? classes = result.data?['classes']; + + if (classes == null) return []; + + List classList = + classes.map((clas) => ClassModel.fromMap(aClass: clas)).toList(); + + return classList; + } + } catch (e) { + debugPrint("getClasses Status: ❌"); + showTopAlertDialog(text: 'Something went wrong!'); + throw Exception(e); + } + } + +} \ No newline at end of file From 8acbdea96f5c256d713b5cfc2e54ce399e954463 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:32:36 +0100 Subject: [PATCH 03/68] first commit --- .../search/data/models/class_model.dart | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/features/search/data/models/class_model.dart diff --git a/lib/features/search/data/models/class_model.dart b/lib/features/search/data/models/class_model.dart new file mode 100644 index 0000000..712b45e --- /dev/null +++ b/lib/features/search/data/models/class_model.dart @@ -0,0 +1,54 @@ +import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; +import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; +// : (){} "" <> ? _ ! * + +class ClassModel extends ClassEntity { + ClassModel({ + String ? id, + String ? name, + String ? about, + String ? avatar, + FacultyModel ? faculty, + List ? educators, + }) : super( + id: id, + name: name, + about: about, + avatar: avatar, + faculty: faculty, + educators: educators, + ); + + factory ClassModel.fromMap({required Map data}) => ClassModel( + id: data['_id'], + name: data['name'], + about: data['about'], + avatar: data['avatar'], + faculty: data.containsKey('faculty') ? FacultyModel.fromMap(faculty: data['faculty']) : null, + educators: data.containsKey('educators') + ? List.generate(data['educators'].length, (index) => UserModel.fromMap(user: data['educators'][index])).toList() + : null, + ); +} + +// query Query($limit: Int, $name: String) { +// classes(limit: $limit, name: $name) { +// _id +// name +// about +// avatar +// faculty { +// _id +// name +// hod { +// _id +// name +// } +// } +// educators { +// _id +// name +// } +// } +// } \ No newline at end of file From 31ff9d14e8417f20ec0ec95d66f23e14d12c4ed9 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:32:42 +0100 Subject: [PATCH 04/68] first commit --- lib/core/resources/data_state.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/core/resources/data_state.dart diff --git a/lib/core/resources/data_state.dart b/lib/core/resources/data_state.dart new file mode 100644 index 0000000..f18800a --- /dev/null +++ b/lib/core/resources/data_state.dart @@ -0,0 +1,15 @@ +abstract class DataState { + final T ? data; + final Error ? error; + + DataState({this.data, this.error}); +} + +class DataSuccess extends DataState { + DataSuccess(T data) : super(data: data); +} + +class DataError extends DataState { + DataError(Error error) : super(error: error); +} + From 7fef07973851137986df6ccc34b023efeaaf1a88 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:32:47 +0100 Subject: [PATCH 05/68] first commit --- .../search/data/models/user_model.dart | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 lib/features/search/data/models/user_model.dart diff --git a/lib/features/search/data/models/user_model.dart b/lib/features/search/data/models/user_model.dart new file mode 100644 index 0000000..b66ca2a --- /dev/null +++ b/lib/features/search/data/models/user_model.dart @@ -0,0 +1,70 @@ +// : (){} "" <> ? _ ! * +import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; +import 'package:neocloud_mobile/graphql/models/RoleModel.dart'; + +class UserModel extends UserEntity { + + UserModel({ + String ? id, + String ? name, + String ? avatar, + String ? cover, + String ? email, + String ? bio, + String ? phone, + RoleModel ? role, + }) : super( + id: id, + name: name, + avatar: avatar, + bio: bio, + cover: cover, + email: email, + phone: phone, + role: role, + ); + + static UserModel fromMap({required Map user}) => UserModel( + id: user['_id'], + name: user['name'], + email: user['email'], + avatar: _keyValueIsPresent(user, 'avatar') ? user['avatar'] : defaultProfileAvatar, + cover: _keyValueIsPresent(user, 'cover') ? user['cover'] : defaultProfileCover, + bio: user['bio'], + phone: user['phone'], + role: _keyValueIsPresent(user, 'role') ? RoleModel.fromMap(role: user['role']) : null, + ); + + static UserModel fromMapEssentials({required Map user}) => UserModel( + id: user['_id'], + name: user['name'], + avatar: _keyValueIsPresent(user, 'avatar') ? user['avatar'] : defaultProfileAvatar, + ); + + static bool _keyValueIsPresent(Map map, String key) { + if (map.containsKey(key)) { + if (map[key] != null) { + return true; + } + } + return false; + } +} + + +// query Query($name: String, $limit: Int) { +// users(name: $name, limit: $limit) { +// _id +// name +// bio +// avatar +// cover +// email +// phone +// role { +// _id +// name +// } +// } +// } \ No newline at end of file From 3c6791a58023cdfd8aec30ad06086c0350c9ec87 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:32:52 +0100 Subject: [PATCH 06/68] first commit --- .../data/repository/class_repository_impl.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 lib/features/search/data/repository/class_repository_impl.dart diff --git a/lib/features/search/data/repository/class_repository_impl.dart b/lib/features/search/data/repository/class_repository_impl.dart new file mode 100644 index 0000000..adc702c --- /dev/null +++ b/lib/features/search/data/repository/class_repository_impl.dart @@ -0,0 +1,18 @@ +import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; +import 'package:neocloud_mobile/core/resources/data_state.dart'; +import 'package:neocloud_mobile/features/search/domain/repository/class_repository.dart'; +import 'package:neocloud_mobile/features/search/data/data_sources/remote/search_service.dart'; + + +class ClassRepositoryImpl implements ClassRepository { + final SearchService _apiService; + + ClassRepositoryImpl(this._apiService); + + @override + Future>> getClasses() { + // TODO: implement getClasses + throw UnimplementedError(); + } + +} \ No newline at end of file From 7be2a2317ac2a121640535ebae1bd1f10b6a0440 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:48:34 +0100 Subject: [PATCH 07/68] update: add deps --- pubspec.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index 91aea92..c151d83 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -51,6 +51,11 @@ dependencies: # Dependency injection package get_it: ^7.6.0 get: ^4.6.5 + + flutter_bloc: ^8.1.3 + equatable: ^2.0.5 + floor: ^1.4.2 + cached_network_image: ^3.2.3 # shared_preferences: ^2.2.0 # auto_route: ^7.8.0 From c4f558e7853c08fe00066a4686875d177ebe11b3 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:49:00 +0100 Subject: [PATCH 08/68] improve code --- lib/screens/create/create_class_instance.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/create/create_class_instance.dart b/lib/screens/create/create_class_instance.dart index fdf54ce..edfcc19 100644 --- a/lib/screens/create/create_class_instance.dart +++ b/lib/screens/create/create_class_instance.dart @@ -31,7 +31,7 @@ class CreateClassInstanceScreen extends StatelessWidget { c.reset(); if (clas != null) { - c.titleController.value.text = clas!.name; + c.titleController.value.text = clas!.name!; } c.enableSetDateAndTime = true.obs; @@ -179,7 +179,7 @@ class CreateClassInstanceScreen extends StatelessWidget { // Selected faculty Name const SizedBox(width: 10), TextMedium( - title: clas != null ? clas!.name : 'Class name...', + title: clas != null ? clas!.name! : 'Class name...', color: Colors.black54), ], ), From f12758ccc6d87a9cc51b9cfcff3d0b74a95be6b0 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:49:13 +0100 Subject: [PATCH 09/68] improve code --- lib/components/input/input_fields.dart | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/components/input/input_fields.dart b/lib/components/input/input_fields.dart index 7ea0e40..5b30fff 100644 --- a/lib/components/input/input_fields.dart +++ b/lib/components/input/input_fields.dart @@ -27,12 +27,12 @@ class _LoginInputFieldState extends State { @override Widget build(BuildContext context) { return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(defaultSize)), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), ), child: ClipRRect( clipBehavior: Clip.antiAlias, - borderRadius: BorderRadius.vertical(top: Radius.circular(defaultSize)), + borderRadius: const BorderRadius.vertical(top: Radius.circular(10)), child: TextFormField( keyboardType: getKeyboardType(widget.labelText), obscureText: widget.obsureText, @@ -59,7 +59,7 @@ class _LoginInputFieldState extends State { // Style - our form fields input text styles TextStyle buildInputTextStyle() { return TextStyle( - fontSize: defaultSize * 1.8, + fontSize: 18, fontWeight: FontWeight.w500, color: kBlack60, ); @@ -103,7 +103,7 @@ class _InputFieldSettingsState extends State { decoration: InputDecoration( hintText: widget.fieldName, ), - style: TextStyle(), + style: const TextStyle(), validator: (value) { return null; }, @@ -178,12 +178,12 @@ class _AppsTextFieldState extends State { InputDecoration buildDecoration() { return InputDecoration( - contentPadding: EdgeInsets.symmetric(vertical: defaultSize), + contentPadding: const EdgeInsets.symmetric(vertical: 10), prefixIcon: - widget.prefixIcon != null ? Icon(widget.prefixIcon) : SizedBox(), + widget.prefixIcon != null ? Icon(widget.prefixIcon) : const SizedBox(), suffixIcon: widget.showCancel != null && !hideCancel ? IconButton( - icon: Icon(Icons.cancel, size: defaultSize * 2), + icon: const Icon(Icons.cancel, size: 20), onPressed: () { _controller.clear(); setState(() { @@ -191,7 +191,7 @@ class _AppsTextFieldState extends State { }); }, ) - : SizedBox(), + : const SizedBox(), prefixIconColor: kBlack50, suffixIconColor: kBlack50, hintText: widget.hintText, @@ -298,7 +298,7 @@ class FormTextarea extends StatelessWidget { style: appsTextStyle(color: textColor, fontSize: fontSize, fontWeight: fontWeight), decoration: InputDecoration( hintText: hintText, - contentPadding: EdgeInsets.symmetric(vertical: defaultSize * 1.5), + contentPadding: const EdgeInsets.symmetric(vertical: 15), hintStyle: appsTextStyle(color: textColor.withOpacity(.7), fontSize: fontSize, fontWeight: fontWeight), border: const OutlineInputBorder(borderSide: BorderSide.none) ), From 4db0dd7d48717ca2a1e92ae1e6b8826973262e62 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:49:23 +0100 Subject: [PATCH 10/68] improve code --- lib/main.dart | 70 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b2fee6e..33ee2b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,10 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/auth/auth_guard.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_bloc.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_event.dart'; +import 'package:neocloud_mobile/injection_container.dart'; import 'package:neocloud_mobile/providers/NavItem.dart'; import 'package:neocloud_mobile/providers/UserProvider.dart'; import 'package:neocloud_mobile/screens/Profile/profile_sceen.dart'; @@ -8,7 +13,7 @@ import 'package:neocloud_mobile/screens/cart/cart_screen.dart'; import 'package:neocloud_mobile/screens/comming_soon/comming_soon_screen.dart'; import 'package:neocloud_mobile/screens/dashboard/dashboard_screen.dart'; import 'package:neocloud_mobile/screens/login_signup/login_signup_screen.dart'; -import 'package:neocloud_mobile/screens/search/search_screen.dart'; +import 'package:neocloud_mobile/features/search/presentation/pages/search_screen.dart'; import 'package:neocloud_mobile/screens/settings/components/system_logos_screen.dart'; import 'package:neocloud_mobile/screens/settings/screens/language_screen.dart'; import 'package:neocloud_mobile/screens/settings/screens/manage_account_screen.dart'; @@ -19,6 +24,7 @@ import 'package:neocloud_mobile/screens/settings/screens/system_screen.dart'; import 'package:neocloud_mobile/screens/settings/settings_screen.dart'; import 'package:neocloud_mobile/screens/splash/splash_screen.dart'; import 'package:neocloud_mobile/screens/welcome/welcome_screen.dart'; +import 'package:neocloud_mobile/size_config.dart'; import 'package:provider/provider.dart'; import 'utils/locator.dart'; @@ -30,6 +36,7 @@ void main() async { await Firebase.initializeApp(); // Register App Services setupServiceLocator(); + initiallizeDependencies(); runApp( MultiProvider( @@ -48,35 +55,44 @@ class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - title: 'NCT Pro', - theme: buildTheme(), - initialRoute: '/' + AcademicScreen.screenName, - // navigatorObservers: [AuthGuardObserver()], // Middleware observer - routes: { - '/': (context) => const SplashScreen(), - '/auth': (context) => LoginSignupScreen(), - '/welcome': (context) => const WelcomeScreen(), - '/comingsoon': (context) => const ComingSoonScreen(), - '/academic': (context) => const AcademicScreen(), - '/dashboard': (context) => const DashboardScreen(), - '/profile': (context) => ProfileScreen(), - '/search': (context) => const SearchScreen(), - '/cart': (context) => const CartScreen(), - // Settings - '/settings': (context) => const SettingsScreen(), - '/manage-account': (context) => const ManageAccountScreen(), - '/system': (context) => const SystemScreen(), - '/payment': (context) => const PaymentScreen(), - '/language': (context) => const LanguageScreen(), - '/smtp': (context) => SmtpScreen(), - '/general': (context) => SystemGeneralScreen(), - '/system-logos': (context) => SystemLogosScreen(), - }, + return MultiBlocProvider( + providers: [ + BlocProvider(create: (context) => sl()), + ], + child: MaterialApp( + debugShowCheckedModeBanner: false, + title: 'NCT Pro', + theme: buildTheme(), + initialRoute: '/' + WelcomeScreen.screenName, + navigatorObservers: [AuthGuardObserver()], // Middleware observer + routes: routes, + ), ); } + Map get routes { + return { + '/': (context) => const SplashScreen(), + '/auth': (context) => LoginSignupScreen(), + '/welcome': (context) => const WelcomeScreen(), + '/comingsoon': (context) => const ComingSoonScreen(), + '/academic': (context) => const AcademicScreen(), + '/dashboard': (context) => const DashboardScreen(), + '/profile': (context) => ProfileScreen(), + '/search': (context) => SearchScreen(), + '/cart': (context) => const CartScreen(), + // Settings + '/settings': (context) => const SettingsScreen(), + '/manage-account': (context) => const ManageAccountScreen(), + '/system': (context) => const SystemScreen(), + '/payment': (context) => const PaymentScreen(), + '/language': (context) => const LanguageScreen(), + '/smtp': (context) => SmtpScreen(), + '/general': (context) => SystemGeneralScreen(), + '/system-logos': (context) => SystemLogosScreen(), + }; + } + ThemeData buildTheme() { return ThemeData( primarySwatch: Colors.blue, From 48823c3be0fd69fcfea288be66942d0b923ce7ae Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Thu, 28 Sep 2023 22:55:40 +0100 Subject: [PATCH 11/68] update --- .../data/repository/user_repository_impl.dart | 23 +++ .../search/domain/entities/class_entity.dart | 41 +++++ .../search/domain/entities/user_entity.dart | 41 +++++ .../domain/repository/class_repository.dart | 6 + .../domain/repository/user_repository.dart | 6 + .../search/domain/usecases/get_class.dart | 15 ++ .../search/domain/usecases/get_users.dart | 15 ++ .../search/domain/usecases/usecase.dart | 3 + .../bloc/remote/users/remote_user_bloc.dart | 17 ++ .../bloc/remote/users/remote_user_event.dart | 8 + .../bloc/remote/users/remote_user_state.dart | 28 ++++ .../bloc/search_navbar/search_navbar.dart | 0 .../presentation/pages/search_screen.dart | 144 +++++++++++++++++ lib/injection_container.dart | 26 +++ lib/main.dart | 66 +++++--- lib/screens/create/create_class_instance.dart | 43 ++--- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 152 ++++++++++++++++++ 18 files changed, 581 insertions(+), 55 deletions(-) create mode 100644 lib/features/search/data/repository/user_repository_impl.dart create mode 100644 lib/features/search/domain/entities/class_entity.dart create mode 100644 lib/features/search/domain/entities/user_entity.dart create mode 100644 lib/features/search/domain/repository/class_repository.dart create mode 100644 lib/features/search/domain/repository/user_repository.dart create mode 100644 lib/features/search/domain/usecases/get_class.dart create mode 100644 lib/features/search/domain/usecases/get_users.dart create mode 100644 lib/features/search/domain/usecases/usecase.dart create mode 100644 lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart create mode 100644 lib/features/search/presentation/bloc/remote/users/remote_user_event.dart create mode 100644 lib/features/search/presentation/bloc/remote/users/remote_user_state.dart create mode 100644 lib/features/search/presentation/bloc/search_navbar/search_navbar.dart create mode 100644 lib/features/search/presentation/pages/search_screen.dart create mode 100644 lib/injection_container.dart diff --git a/lib/features/search/data/repository/user_repository_impl.dart b/lib/features/search/data/repository/user_repository_impl.dart new file mode 100644 index 0000000..718c96b --- /dev/null +++ b/lib/features/search/data/repository/user_repository_impl.dart @@ -0,0 +1,23 @@ +import 'package:neocloud_mobile/features/search/data/data_sources/remote/search_service.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; +import 'package:neocloud_mobile/core/resources/data_state.dart'; +import 'package:neocloud_mobile/features/search/domain/repository/user_repository.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; + +class UserRepositoryImpl implements UserRepository { + final SearchService _apiService; + + UserRepositoryImpl(this._apiService); + + @override + Future>> getUsers({required String name, int ? limit}) async { + var usersList = await _apiService.getUsers(limit: limit, name: name); + print('Users List'); + print(usersList); + + + throw UnimplementedError(); + + // return DataSuccess>(usersList); + } +} \ No newline at end of file diff --git a/lib/features/search/domain/entities/class_entity.dart b/lib/features/search/domain/entities/class_entity.dart new file mode 100644 index 0000000..a1e88ec --- /dev/null +++ b/lib/features/search/domain/entities/class_entity.dart @@ -0,0 +1,41 @@ +import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; + +class ClassEntity { + final String ? id; + final String ? name; + final String ? about; + final String ? avatar; + final FacultyModel ? faculty; + final List ? educators; + + ClassEntity({ + this.id, + this.name, + this.about, + this.avatar, + this.faculty, + this.educators, + }); +} + +// query Query($limit: Int, $name: String) { +// classes(limit: $limit, name: $name) { +// _id +// name +// about +// avatar +// faculty { +// _id +// name +// hod { +// _id +// name +// } +// } +// educators { +// _id +// name +// } +// } +// } \ No newline at end of file diff --git a/lib/features/search/domain/entities/user_entity.dart b/lib/features/search/domain/entities/user_entity.dart new file mode 100644 index 0000000..125ddaa --- /dev/null +++ b/lib/features/search/domain/entities/user_entity.dart @@ -0,0 +1,41 @@ +// : (){} "" <> ? _ ! * +import 'package:neocloud_mobile/graphql/models/RoleModel.dart'; + +class UserEntity { + final String ? id; + final String ? name; + final String ? avatar; + final String ? cover; + final String ? email; + final String ? bio; + final String ? phone; + final RoleModel ? role; + + UserEntity({ + this.id, + this.name, + this.avatar, + this.cover, + this.email, + this.bio, + this.phone, + this.role, + }); +} + + +// query Query($name: String, $limit: Int) { +// users(name: $name, limit: $limit) { +// _id +// name +// bio +// avatar +// cover +// email +// phone +// role { +// _id +// name +// } +// } +// } \ No newline at end of file diff --git a/lib/features/search/domain/repository/class_repository.dart b/lib/features/search/domain/repository/class_repository.dart new file mode 100644 index 0000000..0fcee85 --- /dev/null +++ b/lib/features/search/domain/repository/class_repository.dart @@ -0,0 +1,6 @@ +import 'package:neocloud_mobile/core/resources/data_state.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; + +abstract class ClassRepository { + Future>> getClasses(); +} \ No newline at end of file diff --git a/lib/features/search/domain/repository/user_repository.dart b/lib/features/search/domain/repository/user_repository.dart new file mode 100644 index 0000000..b1eec5e --- /dev/null +++ b/lib/features/search/domain/repository/user_repository.dart @@ -0,0 +1,6 @@ +import 'package:neocloud_mobile/core/resources/data_state.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; + +abstract class UserRepository { + Future>> getUsers({required String name, int ? limit}); +} \ No newline at end of file diff --git a/lib/features/search/domain/usecases/get_class.dart b/lib/features/search/domain/usecases/get_class.dart new file mode 100644 index 0000000..8318a01 --- /dev/null +++ b/lib/features/search/domain/usecases/get_class.dart @@ -0,0 +1,15 @@ +import 'package:neocloud_mobile/core/resources/data_state.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; +import 'package:neocloud_mobile/features/search/domain/repository/class_repository.dart'; +import 'package:neocloud_mobile/features/search/domain/usecases/usecase.dart'; + +class GetClassUseCase implements UseCase { + final ClassRepository _classRepository; + + const GetClassUseCase(this._classRepository); + + @override + Future>> call({param}) { + return _classRepository.getClasses(); + } +} \ No newline at end of file diff --git a/lib/features/search/domain/usecases/get_users.dart b/lib/features/search/domain/usecases/get_users.dart new file mode 100644 index 0000000..e467d14 --- /dev/null +++ b/lib/features/search/domain/usecases/get_users.dart @@ -0,0 +1,15 @@ +import 'package:neocloud_mobile/core/resources/data_state.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; +import 'package:neocloud_mobile/features/search/domain/repository/user_repository.dart'; +import 'package:neocloud_mobile/features/search/domain/usecases/usecase.dart'; + +class GetUsersUseCase implements UseCase>, String> { + final UserRepository _userRepository; + + const GetUsersUseCase(this._userRepository); + + @override + Future>> call({required String param}) async { + return await _userRepository.getUsers(name: param); + } +} diff --git a/lib/features/search/domain/usecases/usecase.dart b/lib/features/search/domain/usecases/usecase.dart new file mode 100644 index 0000000..8c2b499 --- /dev/null +++ b/lib/features/search/domain/usecases/usecase.dart @@ -0,0 +1,3 @@ +abstract class UseCase { + Future call({required Param param}); +} \ No newline at end of file diff --git a/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart b/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart new file mode 100644 index 0000000..104dcc9 --- /dev/null +++ b/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart @@ -0,0 +1,17 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/features/search/domain/usecases/get_users.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_event.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_state.dart'; + +class RemoteUserBloc extends Bloc { + final GetUsersUseCase _getUsersUseCase; + + RemoteUserBloc(this._getUsersUseCase) : super(const RemoteUserWaitingState()) { + on(onGetUsers); + } + + void onGetUsers(GetUserEvent getUserEvent, Emitter emit) { + print('onGetUsers RAN!'); + final data = _getUsersUseCase.call(param: getUserEvent.text); + } +} \ No newline at end of file diff --git a/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart b/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart new file mode 100644 index 0000000..6ef57c5 --- /dev/null +++ b/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart @@ -0,0 +1,8 @@ +abstract class RemoteUserEvent { + final String text; + const RemoteUserEvent(this.text); +} + +class GetUserEvent extends RemoteUserEvent { + const GetUserEvent(super.text); +} \ No newline at end of file diff --git a/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart b/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart new file mode 100644 index 0000000..227299b --- /dev/null +++ b/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart @@ -0,0 +1,28 @@ +import 'package:equatable/equatable.dart'; +import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; + +abstract class RemoteUserState extends Equatable { + final List ? users; + final Error ? error; + + const RemoteUserState({this.users, this.error}); + + @override + List get props => [users, error]; +} + +class RemoteUserLoadingState extends RemoteUserState { + const RemoteUserLoadingState(); +} + +class RemoteUserWaitingState extends RemoteUserState { + const RemoteUserWaitingState(); +} + +class RemoteUserDoneState extends RemoteUserState { + const RemoteUserDoneState(List users) : super(users: users); +} + +class RemoteUserErrorState extends RemoteUserState { + const RemoteUserErrorState(Error error) : super(error: error); +} \ No newline at end of file diff --git a/lib/features/search/presentation/bloc/search_navbar/search_navbar.dart b/lib/features/search/presentation/bloc/search_navbar/search_navbar.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/features/search/presentation/pages/search_screen.dart b/lib/features/search/presentation/pages/search_screen.dart new file mode 100644 index 0000000..5a74acf --- /dev/null +++ b/lib/features/search/presentation/pages/search_screen.dart @@ -0,0 +1,144 @@ +// import 'package:auto_route/annotations.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/components/Lists/class_list.dart'; +import 'package:neocloud_mobile/components/Lists/user_list.dart'; +import 'package:neocloud_mobile/components/bottom_navbar/apps_bottom_navbar.dart'; +import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_bloc.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_event.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_state.dart'; +import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; +import 'package:neocloud_mobile/graphql/services/search_service.dart'; +// import 'package:neocloud_mobile/features/search/presentation/widget/search_filter.dart'; +import 'package:neocloud_mobile/features/search/presentation/pages/search_screen.dart'; +import 'package:neocloud_mobile/features/search/presentation/widget/search_filter.dart'; + +class SearchNavbar { + static final items = ["All", "Educators", "Students", "Classes"]; + static int selectedItems = 0; +} + +class SearchScreen extends StatelessWidget { + SearchScreen({super.key}); + static String screenName = "search"; + + var searchService = SearchService(); + List? usersList; + List? classesList; + + List searchFilter = [ + "All", + "Educators", + "Students", + "Classes", + ]; + int _selectedIndex = 0; + + void loadData(String value) { + // searchService.getUsersClasses(name: value).then((data) { + // print(mounted); + // if (mounted) { + // setState(() { + // print('SET STATE'); + // usersList = data['users'] as List; + // classesList = data['classes'] as List; + // }); + // } + // }); + } + + void updateIndex(int index) { + // setState(() { + // _selectedIndex = index; + // }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: BlocBuilder( + builder: (context, state) => SafeArea( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Search + const SizedBox(height: 20), + + Padding( + padding: screenPadding, + child: buildSearchTextField( + press: (String v) {}, + onChangePress: (value) { + debugPrint('*'); + BlocProvider.of(context).add(GetUserEvent(value)); + }, + ), + ), + + // Filter + SearchFilter( + searchFilter: searchFilter, + selectedIndex: _selectedIndex, + updateIndex: updateIndex, + ), + + // Result + const SizedBox(height: 10), + Padding( + padding: _selectedIndex != 3 + ? const EdgeInsets.fromLTRB(20, 0, 20, 20) + : const EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Users List + _selectedIndex == 0 && usersList != null + ? UserList( + usersList: usersList! + .where((user) => + (user.role!.name.toLowerCase() == + "educator" || + user.role!.name.toLowerCase() == + 'student')) + .toList()) + : const SizedBox(), + + _selectedIndex == 1 && usersList != null + ? UserList( + usersList: usersList! + .where((user) => + (user.role!.name.toLowerCase() == + "educator")) + .toList()) + : const SizedBox(), + + _selectedIndex == 2 && usersList != null + ? UserList( + usersList: usersList! + .where((user) => + (user.role!.name.toLowerCase() == + 'student')) + .toList()) + : const SizedBox(), + + _selectedIndex == 3 + ? ClassList( + classList: classesList!, showClassAvatar: true) + : const SizedBox(), + + const SizedBox(height: 30), + ], + ), + ) + ], + ), + ), + ), + ), + bottomNavigationBar: const AppsBottomNavBar(), + ); + } +} diff --git a/lib/injection_container.dart b/lib/injection_container.dart new file mode 100644 index 0000000..d3d8301 --- /dev/null +++ b/lib/injection_container.dart @@ -0,0 +1,26 @@ +import 'package:get_it/get_it.dart'; +import 'package:neocloud_mobile/features/search/domain/repository/class_repository.dart'; +import 'package:neocloud_mobile/features/search/domain/usecases/get_class.dart'; +import 'package:neocloud_mobile/features/search/domain/usecases/get_users.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_bloc.dart'; + +import 'features/search/data/data_sources/remote/search_service.dart'; +import 'features/search/data/repository/class_repository_impl.dart'; +import 'features/search/data/repository/user_repository_impl.dart'; +import 'features/search/domain/repository/user_repository.dart'; + +final sl = GetIt.instance; + +void initiallizeDependencies () { + // Data + sl.registerSingleton(SearchService()); + sl.registerSingleton(UserRepositoryImpl(sl())); + sl.registerSingleton(ClassRepositoryImpl(sl())); + + // Domain + sl.registerSingleton(GetUsersUseCase(sl())); + sl.registerSingleton(GetClassUseCase(sl())); + + // Presentation (bloc) + sl.registerFactory(() => RemoteUserBloc(sl())); +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 9ba28e6..33ee2b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,10 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/auth/auth_guard.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_bloc.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_event.dart'; +import 'package:neocloud_mobile/injection_container.dart'; import 'package:neocloud_mobile/providers/NavItem.dart'; import 'package:neocloud_mobile/providers/UserProvider.dart'; import 'package:neocloud_mobile/screens/Profile/profile_sceen.dart'; @@ -50,35 +55,44 @@ class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - title: 'NCT Pro', - theme: buildTheme(), - initialRoute: '/' + AcademicScreen.screenName, - // navigatorObservers: [AuthGuardObserver()], // Middleware observer - routes: { - '/': (context) => const SplashScreen(), - '/auth': (context) => LoginSignupScreen(), - '/welcome': (context) => const WelcomeScreen(), - '/comingsoon': (context) => const ComingSoonScreen(), - '/academic': (context) => const AcademicScreen(), - '/dashboard': (context) => const DashboardScreen(), - '/profile': (context) => ProfileScreen(), - '/search': (context) => const SearchScreen(), - '/cart': (context) => const CartScreen(), - // Settings - '/settings': (context) => const SettingsScreen(), - '/manage-account': (context) => const ManageAccountScreen(), - '/system': (context) => const SystemScreen(), - '/payment': (context) => const PaymentScreen(), - '/language': (context) => const LanguageScreen(), - '/smtp': (context) => SmtpScreen(), - '/general': (context) => SystemGeneralScreen(), - '/system-logos': (context) => SystemLogosScreen(), - }, + return MultiBlocProvider( + providers: [ + BlocProvider(create: (context) => sl()), + ], + child: MaterialApp( + debugShowCheckedModeBanner: false, + title: 'NCT Pro', + theme: buildTheme(), + initialRoute: '/' + WelcomeScreen.screenName, + navigatorObservers: [AuthGuardObserver()], // Middleware observer + routes: routes, + ), ); } + Map get routes { + return { + '/': (context) => const SplashScreen(), + '/auth': (context) => LoginSignupScreen(), + '/welcome': (context) => const WelcomeScreen(), + '/comingsoon': (context) => const ComingSoonScreen(), + '/academic': (context) => const AcademicScreen(), + '/dashboard': (context) => const DashboardScreen(), + '/profile': (context) => ProfileScreen(), + '/search': (context) => SearchScreen(), + '/cart': (context) => const CartScreen(), + // Settings + '/settings': (context) => const SettingsScreen(), + '/manage-account': (context) => const ManageAccountScreen(), + '/system': (context) => const SystemScreen(), + '/payment': (context) => const PaymentScreen(), + '/language': (context) => const LanguageScreen(), + '/smtp': (context) => SmtpScreen(), + '/general': (context) => SystemGeneralScreen(), + '/system-logos': (context) => SystemLogosScreen(), + }; + } + ThemeData buildTheme() { return ThemeData( primarySwatch: Colors.blue, diff --git a/lib/screens/create/create_class_instance.dart b/lib/screens/create/create_class_instance.dart index 0ad9eb2..edfcc19 100644 --- a/lib/screens/create/create_class_instance.dart +++ b/lib/screens/create/create_class_instance.dart @@ -5,9 +5,6 @@ import 'package:neocloud_mobile/components/input/input_fields.dart'; import 'package:neocloud_mobile/components/widgets.dart'; import 'package:neocloud_mobile/constraints.dart'; import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; -import 'package:neocloud_mobile/graphql/models/ClassModuleModel.dart'; -import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; import 'package:neocloud_mobile/screens/create/components/form_add_cover.dart'; import 'package:neocloud_mobile/screens/create/components/form_modules.dart'; import 'package:neocloud_mobile/screens/create/components/form_select_user.dart'; @@ -19,34 +16,22 @@ import 'components/form_footer.dart'; import 'components/form_header.dart'; import 'components/form_select_users.dart'; -class ClassInstanceSettings { - static bool disableCoverImg = true; - static bool disableTitle = true; - static bool disableAddModules = true; - static bool disableUpdateModules = true; - static bool disableUpdateScheduleDescriptionAndClasswork = true; - static bool disableUpdateSetDate = false; - static bool disableAutomateDateAndTime = false; -} - /// POPUP /// This Screen is used in a showDialog, so it will basically not have /// its own screen per say but will be used in a pop up environment instead class CreateClassInstanceScreen extends StatelessWidget { CreateClassInstanceScreen({super.key, this.clas}); - ClassModel? clas; + final ClassModel? clas; static String screenName = 'create class instance'; var c = Get.put(ClassGetXController()); - var avatar = - "https://firebasestorage.googleapis.com/v0/b/neocloud-bd1f6.appspot.com/o/files%2Fassets%2Favatars%2Fbook-stack-avatar.png?alt=media&token=e167309c-51b9-4038-a9a4-e0f13987f15d"; @override Widget build(BuildContext context) { c.reset(); if (clas != null) { - c.titleController.value.text = clas!.name; + c.titleController.value.text = clas!.name!; } c.enableSetDateAndTime = true.obs; @@ -109,12 +94,12 @@ class CreateClassInstanceScreen extends StatelessWidget { // Class Avatar / Cover FormAddCover( - defaultImage: clas!.avatar, - disable: ClassInstanceSettings.disableCoverImg, press: (file) { c.coverImgFile = file.obs; }, ), + if (c.coverImgFileHasError.value == true) + const TextInputError(text: 'A class requires an image cover'), // Class Instance const SizedBox(height: 30), @@ -122,18 +107,17 @@ class CreateClassInstanceScreen extends StatelessWidget { controller: c.titleController.value, hintText: 'Auto Generated Class Name', fontSize: 20, - isEnabled: ClassInstanceSettings.disableTitle, fontWeight: FontWeight.w500, validator: validateRequireField, press: (_) {}, ), + if (c.hodHasError.value == true) const TextInputError(), // Class Name const SizedBox(height: 10), _buildClassName(), // Add Faculty - // TODO: users to select from should be fetched from the database const SizedBox(height: 20), FormSelectUser( buttonText: 'Educator', @@ -150,8 +134,8 @@ class CreateClassInstanceScreen extends StatelessWidget { // Add Educators const SizedBox(height: 15), FormSelectUsers( - buttonText: 'Students', - avatarText: 'ST', + buttonText: 'Educators', + avatarText: 'ED', selectedUsers: c.selectedEducatorsList, usersToSelectFrom: c.usersToSelectFrom, updateSelectedUsers: c.updateSelectedEducators, @@ -164,12 +148,13 @@ class CreateClassInstanceScreen extends StatelessWidget { // Form Modules const SizedBox(height: 15), - FormModules( - modules: clas!.modules, - enableAddModules: false, - enableAutomateDateTime: true, - enableUpdateModule: false, - ), + if (c.modulesHasError.value == true) + Padding( + padding: const EdgeInsets.only(bottom: 20), + child: TextInputError(text: c.modulesErrorMessage.value), + ), + + const FormModules(), ], ), ), diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 6e2a3ca..b3e1e68 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,6 +11,7 @@ import firebase_core import firebase_storage import flutter_secure_storage_macos import path_provider_foundation +import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) @@ -19,4 +20,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 84f3f92..1581e45 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -33,6 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.10.0" + bloc: + dependency: transitive + description: + name: bloc + sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49" + url: "https://pub.dev" + source: hosted + version: "8.1.2" boolean_selector: dependency: transitive description: @@ -41,6 +49,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + url: "https://pub.dev" + source: hosted + version: "3.2.3" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + url: "https://pub.dev" + source: hosted + version: "1.0.2" carousel_slider: dependency: "direct main" description: @@ -57,6 +89,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" clock: dependency: transitive description: @@ -129,6 +169,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.8" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -145,6 +193,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" file_selector_linux: dependency: transitive description: @@ -225,11 +281,51 @@ packages: url: "https://pub.dev" source: hosted version: "3.6.6" + floor: + dependency: "direct main" + description: + name: floor + sha256: "52a8eac2c8d274e7c0c54251226f59786bb5b749365a2d8537d8095aa5132d92" + url: "https://pub.dev" + source: hosted + version: "1.4.2" + floor_annotation: + dependency: transitive + description: + name: floor_annotation + sha256: fa3fa4f198cdd1d922a69ceb06e54663fe59256bf1cb3c036eff206b445a6960 + url: "https://pub.dev" + source: hosted + version: "1.4.2" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae + url: "https://pub.dev" + source: hosted + version: "8.1.3" + flutter_blurhash: + dependency: transitive + description: + name: flutter_blurhash + sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" flutter_hooks: dependency: transitive description: @@ -616,6 +712,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + url: "https://pub.dev" + source: hosted + version: "1.0.2" page_transition: dependency: "direct main" description: @@ -757,6 +861,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + url: "https://pub.dev" + source: hosted + version: "2.2.8+4" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + url: "https://pub.dev" + source: hosted + version: "2.4.5+1" + sqflite_common_ffi: + dependency: transitive + description: + name: sqflite_common_ffi + sha256: f86de82d37403af491b21920a696b19f01465b596f545d1acd4d29a0a72418ad + url: "https://pub.dev" + source: hosted + version: "2.2.5" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "281b672749af2edf259fc801f0fcba092257425bcd32a0ce1c8237130bc934c7" + url: "https://pub.dev" + source: hosted + version: "1.11.2" + sqlparser: + dependency: transitive + description: + name: sqlparser + sha256: "91f47610aa54d8abf9d795a7b4e49b2a788f65d7493d5a68fbf180c3cbcc6f38" + url: "https://pub.dev" + source: hosted + version: "0.27.0" stack_trace: dependency: transitive description: @@ -781,6 +925,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" table_calendar: dependency: "direct main" description: From 30fcf60db402c0dff29af9e63dcc1fc1206cb7fe Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:58:15 +0100 Subject: [PATCH 12/68] remove --- .../search/data/models/class_model.dart | 54 ------------------- 1 file changed, 54 deletions(-) delete mode 100644 lib/features/search/data/models/class_model.dart diff --git a/lib/features/search/data/models/class_model.dart b/lib/features/search/data/models/class_model.dart deleted file mode 100644 index 712b45e..0000000 --- a/lib/features/search/data/models/class_model.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; -import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; -// : (){} "" <> ? _ ! * - -class ClassModel extends ClassEntity { - ClassModel({ - String ? id, - String ? name, - String ? about, - String ? avatar, - FacultyModel ? faculty, - List ? educators, - }) : super( - id: id, - name: name, - about: about, - avatar: avatar, - faculty: faculty, - educators: educators, - ); - - factory ClassModel.fromMap({required Map data}) => ClassModel( - id: data['_id'], - name: data['name'], - about: data['about'], - avatar: data['avatar'], - faculty: data.containsKey('faculty') ? FacultyModel.fromMap(faculty: data['faculty']) : null, - educators: data.containsKey('educators') - ? List.generate(data['educators'].length, (index) => UserModel.fromMap(user: data['educators'][index])).toList() - : null, - ); -} - -// query Query($limit: Int, $name: String) { -// classes(limit: $limit, name: $name) { -// _id -// name -// about -// avatar -// faculty { -// _id -// name -// hod { -// _id -// name -// } -// } -// educators { -// _id -// name -// } -// } -// } \ No newline at end of file From 344afd988d12d3738d5b14d5f89cf8cbe7b6da05 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:58:23 +0100 Subject: [PATCH 13/68] remove --- .../search/data/models/user_model.dart | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 lib/features/search/data/models/user_model.dart diff --git a/lib/features/search/data/models/user_model.dart b/lib/features/search/data/models/user_model.dart deleted file mode 100644 index b66ca2a..0000000 --- a/lib/features/search/data/models/user_model.dart +++ /dev/null @@ -1,70 +0,0 @@ -// : (){} "" <> ? _ ! * -import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; -import 'package:neocloud_mobile/graphql/models/RoleModel.dart'; - -class UserModel extends UserEntity { - - UserModel({ - String ? id, - String ? name, - String ? avatar, - String ? cover, - String ? email, - String ? bio, - String ? phone, - RoleModel ? role, - }) : super( - id: id, - name: name, - avatar: avatar, - bio: bio, - cover: cover, - email: email, - phone: phone, - role: role, - ); - - static UserModel fromMap({required Map user}) => UserModel( - id: user['_id'], - name: user['name'], - email: user['email'], - avatar: _keyValueIsPresent(user, 'avatar') ? user['avatar'] : defaultProfileAvatar, - cover: _keyValueIsPresent(user, 'cover') ? user['cover'] : defaultProfileCover, - bio: user['bio'], - phone: user['phone'], - role: _keyValueIsPresent(user, 'role') ? RoleModel.fromMap(role: user['role']) : null, - ); - - static UserModel fromMapEssentials({required Map user}) => UserModel( - id: user['_id'], - name: user['name'], - avatar: _keyValueIsPresent(user, 'avatar') ? user['avatar'] : defaultProfileAvatar, - ); - - static bool _keyValueIsPresent(Map map, String key) { - if (map.containsKey(key)) { - if (map[key] != null) { - return true; - } - } - return false; - } -} - - -// query Query($name: String, $limit: Int) { -// users(name: $name, limit: $limit) { -// _id -// name -// bio -// avatar -// cover -// email -// phone -// role { -// _id -// name -// } -// } -// } \ No newline at end of file From 5755a9973120dc51c4e91ca3b0e2585aad59a429 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:58:31 +0100 Subject: [PATCH 14/68] remove --- .../search/domain/entities/class_entity.dart | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 lib/features/search/domain/entities/class_entity.dart diff --git a/lib/features/search/domain/entities/class_entity.dart b/lib/features/search/domain/entities/class_entity.dart deleted file mode 100644 index a1e88ec..0000000 --- a/lib/features/search/domain/entities/class_entity.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; - -class ClassEntity { - final String ? id; - final String ? name; - final String ? about; - final String ? avatar; - final FacultyModel ? faculty; - final List ? educators; - - ClassEntity({ - this.id, - this.name, - this.about, - this.avatar, - this.faculty, - this.educators, - }); -} - -// query Query($limit: Int, $name: String) { -// classes(limit: $limit, name: $name) { -// _id -// name -// about -// avatar -// faculty { -// _id -// name -// hod { -// _id -// name -// } -// } -// educators { -// _id -// name -// } -// } -// } \ No newline at end of file From f623c795733b3bc0753ae486e0c055edf12597ab Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:58:36 +0100 Subject: [PATCH 15/68] remove --- .../search/domain/entities/user_entity.dart | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 lib/features/search/domain/entities/user_entity.dart diff --git a/lib/features/search/domain/entities/user_entity.dart b/lib/features/search/domain/entities/user_entity.dart deleted file mode 100644 index 125ddaa..0000000 --- a/lib/features/search/domain/entities/user_entity.dart +++ /dev/null @@ -1,41 +0,0 @@ -// : (){} "" <> ? _ ! * -import 'package:neocloud_mobile/graphql/models/RoleModel.dart'; - -class UserEntity { - final String ? id; - final String ? name; - final String ? avatar; - final String ? cover; - final String ? email; - final String ? bio; - final String ? phone; - final RoleModel ? role; - - UserEntity({ - this.id, - this.name, - this.avatar, - this.cover, - this.email, - this.bio, - this.phone, - this.role, - }); -} - - -// query Query($name: String, $limit: Int) { -// users(name: $name, limit: $limit) { -// _id -// name -// bio -// avatar -// cover -// email -// phone -// role { -// _id -// name -// } -// } -// } \ No newline at end of file From 4eb69df60c2b9213088c1c6192709dc83456969a Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:58:47 +0100 Subject: [PATCH 16/68] remove --- .../search/presentation/bloc/search_navbar/search_navbar.dart | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/features/search/presentation/bloc/search_navbar/search_navbar.dart diff --git a/lib/features/search/presentation/bloc/search_navbar/search_navbar.dart b/lib/features/search/presentation/bloc/search_navbar/search_navbar.dart deleted file mode 100644 index e69de29..0000000 From a0f63823b41cf828f21a2ccdf93526b09ab3162a Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:58:59 +0100 Subject: [PATCH 17/68] remove --- .../presentation/widget/search_filter.dart | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100644 lib/features/search/presentation/widget/search_filter.dart diff --git a/lib/features/search/presentation/widget/search_filter.dart b/lib/features/search/presentation/widget/search_filter.dart deleted file mode 100644 index 74e7cdb..0000000 --- a/lib/features/search/presentation/widget/search_filter.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/texts.dart'; -import 'package:neocloud_mobile/constraints.dart'; - -class SearchFilter extends StatelessWidget { - const SearchFilter({ - super.key, - required this.updateIndex, - required this.selectedIndex, - required this.searchFilter, - }); - - final int selectedIndex; - final Function(int index) updateIndex; - final List searchFilter; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: List.generate( - searchFilter.length, - (index) => GestureDetector( - onTap: () => updateIndex(index), - child: Container( - color: Colors.transparent, - margin: const EdgeInsets.only(top: 10), - padding: index == 0 - ? const EdgeInsets.fromLTRB( - 40, - 10, - 18, - 10, - ) - : const EdgeInsets.symmetric( - horizontal: 18, - vertical: 10, - ), - child: TextMedium( - title: searchFilter[index], - color: selectedIndex == index ? kBlack90 : kBlack50, - weight: selectedIndex == index - ? FontWeight.w600 - : FontWeight.w500, - ), - ), - ), - ), - ), - ), - Divider(color: kBlack.withOpacity(.3)), - ], - ); - } -} From eb2570053dd2ff055ccbffdc87136ec7de9bf50f Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:59:09 +0100 Subject: [PATCH 18/68] remove --- lib/screens/search/search_screen.dart | 145 -------------------------- 1 file changed, 145 deletions(-) delete mode 100644 lib/screens/search/search_screen.dart diff --git a/lib/screens/search/search_screen.dart b/lib/screens/search/search_screen.dart deleted file mode 100644 index a6e5427..0000000 --- a/lib/screens/search/search_screen.dart +++ /dev/null @@ -1,145 +0,0 @@ -// import 'package:auto_route/annotations.dart'; -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/Lists/class_list.dart'; -import 'package:neocloud_mobile/components/Lists/user_list.dart'; -import 'package:neocloud_mobile/components/bottom_navbar/apps_bottom_navbar.dart'; -import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; -import 'package:neocloud_mobile/graphql/services/search_service.dart'; -import 'package:neocloud_mobile/screens/search/components/search_filter.dart'; - -// @RoutePage() -class SearchScreen extends StatefulWidget { - const SearchScreen({ - super.key, - }); - static String screenName = "search"; - - @override - State createState() => _SearchScreenState(); -} - -class _SearchScreenState extends State { - var searchService = SearchService(); - List? usersList; - List? classesList; - - List searchFilter = [ - "All", - "Educators", - "Students", - "Classes", - ]; - int _selectedIndex = 0; - - @override - void initState() { - super.initState(); - } - - void search(String value) { - print('search'); - loadData(value); - } - - void loadData(String value) { - searchService.getUsersClasses(name: value).then((data) { - print(mounted); - if (mounted) { - setState(() { - print('SET STATE'); - usersList = data['users'] as List; - classesList = data['classes'] as List; - }); - } - }); - } - - void updateIndex(int index) { - setState(() { - _selectedIndex = index; - }); - } - - @override - Widget build(BuildContext context) { - print('REBUILD UI'); - return Scaffold( - body: SafeArea( - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Search - const SizedBox(height: 20), - - // SearchHeader(updateSearch: search), - Padding( - padding: screenPadding, - child: buildSearchTextField( - press: (String v) {}, onChangePress: loadData), - ), - - // Filter - SearchFilter( - searchFilter: searchFilter, - selectedIndex: _selectedIndex, - updateIndex: updateIndex, - ), - - // Result - const SizedBox(height: 10), - Padding( - padding: _selectedIndex != 3 - ? const EdgeInsets.fromLTRB(20, 0, 20, 20) - : const EdgeInsets.all(0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Users List - _selectedIndex == 0 && usersList != null - ? UserList( - usersList: usersList! - .where((user) => (user.role!.name - .toLowerCase() == - "educator" || - user.role!.name.toLowerCase() == 'student')) - .toList()) - : const SizedBox(), - - _selectedIndex == 1 && usersList != null - ? UserList( - usersList: usersList! - .where((user) => - (user.role!.name.toLowerCase() == - "educator")) - .toList()) - : const SizedBox(), - - _selectedIndex == 2 && usersList != null - ? UserList( - usersList: usersList! - .where((user) => - (user.role!.name.toLowerCase() == - 'student')) - .toList()) - : const SizedBox(), - - _selectedIndex == 3 - ? ClassList( - classList: classesList!, showClassAvatar: true) - : const SizedBox(), - - const SizedBox(height: 30), - ], - ), - ) - ], - ), - ), - ), - bottomNavigationBar: const AppsBottomNavBar(), - ); - } -} From 2ff40f8d649dfc802501b9b223983b0c96a27175 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:59:18 +0100 Subject: [PATCH 19/68] remove --- .../search/components/search_filter.dart | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100644 lib/screens/search/components/search_filter.dart diff --git a/lib/screens/search/components/search_filter.dart b/lib/screens/search/components/search_filter.dart deleted file mode 100644 index 74e7cdb..0000000 --- a/lib/screens/search/components/search_filter.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/texts.dart'; -import 'package:neocloud_mobile/constraints.dart'; - -class SearchFilter extends StatelessWidget { - const SearchFilter({ - super.key, - required this.updateIndex, - required this.selectedIndex, - required this.searchFilter, - }); - - final int selectedIndex; - final Function(int index) updateIndex; - final List searchFilter; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: List.generate( - searchFilter.length, - (index) => GestureDetector( - onTap: () => updateIndex(index), - child: Container( - color: Colors.transparent, - margin: const EdgeInsets.only(top: 10), - padding: index == 0 - ? const EdgeInsets.fromLTRB( - 40, - 10, - 18, - 10, - ) - : const EdgeInsets.symmetric( - horizontal: 18, - vertical: 10, - ), - child: TextMedium( - title: searchFilter[index], - color: selectedIndex == index ? kBlack90 : kBlack50, - weight: selectedIndex == index - ? FontWeight.w600 - : FontWeight.w500, - ), - ), - ), - ), - ), - ), - Divider(color: kBlack.withOpacity(.3)), - ], - ); - } -} From 4adb17719ec85e28f251ccb65692e365db6e2d43 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:59:39 +0100 Subject: [PATCH 20/68] first commit --- lib/core/entities/class_entity.dart | 41 +++++++++++ lib/core/entities/user_entity.dart | 46 ++++++++++++ lib/core/models/class_model.dart | 54 ++++++++++++++ lib/core/models/user_model.dart | 70 +++++++++++++++++++ .../search/domain/entities/search_navbar.dart | 5 ++ .../remote/classes/remote_class_bloc.dart | 23 ++++++ .../remote/classes/remote_class_event.dart | 11 +++ .../remote/classes/remote_class_state.dart | 27 +++++++ 8 files changed, 277 insertions(+) create mode 100644 lib/core/entities/class_entity.dart create mode 100644 lib/core/entities/user_entity.dart create mode 100644 lib/core/models/class_model.dart create mode 100644 lib/core/models/user_model.dart create mode 100644 lib/features/search/domain/entities/search_navbar.dart create mode 100644 lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart create mode 100644 lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart create mode 100644 lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart diff --git a/lib/core/entities/class_entity.dart b/lib/core/entities/class_entity.dart new file mode 100644 index 0000000..a1e88ec --- /dev/null +++ b/lib/core/entities/class_entity.dart @@ -0,0 +1,41 @@ +import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; + +class ClassEntity { + final String ? id; + final String ? name; + final String ? about; + final String ? avatar; + final FacultyModel ? faculty; + final List ? educators; + + ClassEntity({ + this.id, + this.name, + this.about, + this.avatar, + this.faculty, + this.educators, + }); +} + +// query Query($limit: Int, $name: String) { +// classes(limit: $limit, name: $name) { +// _id +// name +// about +// avatar +// faculty { +// _id +// name +// hod { +// _id +// name +// } +// } +// educators { +// _id +// name +// } +// } +// } \ No newline at end of file diff --git a/lib/core/entities/user_entity.dart b/lib/core/entities/user_entity.dart new file mode 100644 index 0000000..3e81c4c --- /dev/null +++ b/lib/core/entities/user_entity.dart @@ -0,0 +1,46 @@ +// : (){} "" <> ? _ ! * +import 'package:equatable/equatable.dart'; +import 'package:neocloud_mobile/graphql/models/RoleModel.dart'; + +class UserEntity extends Equatable { + final String ? id; + final String ? name; + final String ? avatar; + final String ? cover; + final String ? email; + final String ? bio; + final String ? phone; + final RoleModel ? role; + + UserEntity({ + this.id, + this.name, + this.avatar, + this.cover, + this.email, + this.bio, + this.phone, + this.role, + }); + + @override + // TODO: implement props + List get props => [id, name, avatar, cover, email, bio, phone, role]; +} + + +// query Query($name: String, $limit: Int) { +// users(name: $name, limit: $limit) { +// _id +// name +// bio +// avatar +// cover +// email +// phone +// role { +// _id +// name +// } +// } +// } \ No newline at end of file diff --git a/lib/core/models/class_model.dart b/lib/core/models/class_model.dart new file mode 100644 index 0000000..3bed5f8 --- /dev/null +++ b/lib/core/models/class_model.dart @@ -0,0 +1,54 @@ +import 'package:neocloud_mobile/core/entities/class_entity.dart'; +import 'package:neocloud_mobile/graphql/models/FacultyModel.dart'; +import 'package:neocloud_mobile/graphql/models/UserModel.dart'; +// : (){} "" <> ? _ ! * + +class ClassModel extends ClassEntity { + ClassModel({ + String ? id, + String ? name, + String ? about, + String ? avatar, + FacultyModel ? faculty, + List ? educators, + }) : super( + id: id, + name: name, + about: about, + avatar: avatar, + faculty: faculty, + educators: educators, + ); + + factory ClassModel.fromMap({required Map data}) => ClassModel( + id: data['_id'], + name: data['name'], + about: data['about'], + avatar: data['avatar'], + faculty: data.containsKey('faculty') ? FacultyModel.fromMap(faculty: data['faculty']) : null, + educators: data.containsKey('educators') + ? List.generate(data['educators'].length, (index) => UserModel.fromMap(user: data['educators'][index])).toList() + : null, + ); +} + +// query Query($limit: Int, $name: String) { +// classes(limit: $limit, name: $name) { +// _id +// name +// about +// avatar +// faculty { +// _id +// name +// hod { +// _id +// name +// } +// } +// educators { +// _id +// name +// } +// } +// } \ No newline at end of file diff --git a/lib/core/models/user_model.dart b/lib/core/models/user_model.dart new file mode 100644 index 0000000..4866e84 --- /dev/null +++ b/lib/core/models/user_model.dart @@ -0,0 +1,70 @@ +// : (){} "" <> ? _ ! * +import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; +import 'package:neocloud_mobile/graphql/models/RoleModel.dart'; + +class UserModel extends UserEntity { + + UserModel({ + String ? id, + String ? name, + String ? avatar, + String ? cover, + String ? email, + String ? bio, + String ? phone, + RoleModel ? role, + }) : super( + id: id, + name: name, + avatar: avatar, + bio: bio, + cover: cover, + email: email, + phone: phone, + role: role, + ); + + factory UserModel.fromMap({required Map user}) => UserModel( + id: user['_id'], + name: user['name'], + email: user['email'], + avatar: _keyValueIsPresent(user, 'avatar') ? user['avatar'] : defaultProfileAvatar, + cover: _keyValueIsPresent(user, 'cover') ? user['cover'] : defaultProfileCover, + bio: user['bio'], + phone: user['phone'], + role: _keyValueIsPresent(user, 'role') ? RoleModel.fromMap(role: user['role']) : null, + ); + + factory UserModel.fromMapEssentials({required Map user}) => UserModel( + id: user['_id'], + name: user['name'], + avatar: _keyValueIsPresent(user, 'avatar') ? user['avatar'] : defaultProfileAvatar, + ); + + static bool _keyValueIsPresent(Map map, String key) { + if (map.containsKey(key)) { + if (map[key] != null) { + return true; + } + } + return false; + } +} + + +// query Query($name: String, $limit: Int) { +// users(name: $name, limit: $limit) { +// _id +// name +// bio +// avatar +// cover +// email +// phone +// role { +// _id +// name +// } +// } +// } \ No newline at end of file diff --git a/lib/features/search/domain/entities/search_navbar.dart b/lib/features/search/domain/entities/search_navbar.dart new file mode 100644 index 0000000..314b5ba --- /dev/null +++ b/lib/features/search/domain/entities/search_navbar.dart @@ -0,0 +1,5 @@ +class SearchNavbarEntity { + int index; + + SearchNavbarEntity({required this.index}); +} \ No newline at end of file diff --git a/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart b/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart new file mode 100644 index 0000000..d12d125 --- /dev/null +++ b/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart @@ -0,0 +1,23 @@ +import 'dart:async'; +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; +import 'package:neocloud_mobile/features/search/domain/usecases/get_class.dart'; + +part 'remote_class_event.dart'; +part 'remote_class_state.dart'; + +class RemoteClassBloc extends Bloc { + final GetClassUseCase _getClassUseCase; + + RemoteClassBloc(this._getClassUseCase) : super(const RemoteClassesInitialState()) { + on(onGetClassesEvent); + } + + Future onGetClassesEvent(RemoteClassesEvent event, Emitter emit) async { + emit(const RemoteClassesLoadingState()); + final dataState = await _getClassUseCase.call(param1: event.text); + final newState = RemoteClassesDoneState(dataState.data!); + emit(newState); + } +} \ No newline at end of file diff --git a/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart b/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart new file mode 100644 index 0000000..c1f09cc --- /dev/null +++ b/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart @@ -0,0 +1,11 @@ +part of 'remote_class_bloc.dart'; + +abstract class RemoteClassesEvent { + final String text; + + RemoteClassesEvent(this.text); +} + +class GetClassesEvent extends RemoteClassesEvent { + GetClassesEvent(String text) : super(text); +} diff --git a/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart b/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart new file mode 100644 index 0000000..94bedfd --- /dev/null +++ b/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart @@ -0,0 +1,27 @@ +part of 'remote_class_bloc.dart'; + +abstract class RemoteClassesState extends Equatable { + final List ? classes; + final Exception ? exception; + + const RemoteClassesState({this.classes, this.exception}); + + @override + List get props => [classes, exception]; +} + +class RemoteClassesLoadingState extends RemoteClassesState { + const RemoteClassesLoadingState(); +} + +class RemoteClassesInitialState extends RemoteClassesState { + const RemoteClassesInitialState(); +} + +class RemoteClassesDoneState extends RemoteClassesState { + const RemoteClassesDoneState(List classes) : super(classes: classes); +} + +class RemoteClassesFailState extends RemoteClassesState { + const RemoteClassesFailState(Exception exception) : super(exception: exception); +} \ No newline at end of file From 86ce47c23f3f2ff70e7f4971cf37a227b9d80a75 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:59:46 +0100 Subject: [PATCH 21/68] first commit --- .../search_navbar/search_navbar_bloc.dart | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 lib/features/search/presentation/bloc/search_navbar/search_navbar_bloc.dart diff --git a/lib/features/search/presentation/bloc/search_navbar/search_navbar_bloc.dart b/lib/features/search/presentation/bloc/search_navbar/search_navbar_bloc.dart new file mode 100644 index 0000000..9dfff1a --- /dev/null +++ b/lib/features/search/presentation/bloc/search_navbar/search_navbar_bloc.dart @@ -0,0 +1,34 @@ +import 'dart:async'; +import 'package:flutter_bloc/flutter_bloc.dart'; +part 'search_navbar_state.dart'; +part 'search_navbar_event.dart'; + + +class SearchNavbarBloc extends Bloc { + SearchNavbarBloc() : super(SearchNavbarAllState()) { + on(onAllEvent); + on(onEducatorsEvent); + on(onStudentsEvent); + on(onClassesEvent); + } + + Future onAllEvent(event, emit) async { + print('All Event Dispatched!'); + emit(SearchNavbarAllState()); + } + + Future onEducatorsEvent(event, emit) async { + print('Educators Event Dispatched!'); + emit(SearchNavbarEducatorsState()); + } + + Future onStudentsEvent(event, emit) async { + print('Students Event Dispatched!'); + emit(SearchNavbarStudentsState()); + } + + Future onClassesEvent(event, emit) async { + print('Classes Event Dispatched!'); + emit(SearchNavbarClassesState()); + } +} \ No newline at end of file From c24437605225fca4fc2b01fb300bb053b49e48cb Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:59:53 +0100 Subject: [PATCH 22/68] first commit --- .../bloc/search_navbar/search_navbar_event.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 lib/features/search/presentation/bloc/search_navbar/search_navbar_event.dart diff --git a/lib/features/search/presentation/bloc/search_navbar/search_navbar_event.dart b/lib/features/search/presentation/bloc/search_navbar/search_navbar_event.dart new file mode 100644 index 0000000..a1046b0 --- /dev/null +++ b/lib/features/search/presentation/bloc/search_navbar/search_navbar_event.dart @@ -0,0 +1,11 @@ +part of 'search_navbar_bloc.dart'; + +abstract class SearchNavbarEvent {} + +class SearchNavbarAllEvent extends SearchNavbarEvent {} + +class SearchNavbarEducatorsEvent extends SearchNavbarEvent {} + +class SearchNavbarStudentsEvent extends SearchNavbarEvent {} + +class SearchNavbarClassesEvent extends SearchNavbarEvent {} \ No newline at end of file From ba8cf642849480c14f679f1729895490ac11e49d Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 22:59:58 +0100 Subject: [PATCH 23/68] first commit --- .../search_navbar/search_navbar_state.dart | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 lib/features/search/presentation/bloc/search_navbar/search_navbar_state.dart diff --git a/lib/features/search/presentation/bloc/search_navbar/search_navbar_state.dart b/lib/features/search/presentation/bloc/search_navbar/search_navbar_state.dart new file mode 100644 index 0000000..fb133e2 --- /dev/null +++ b/lib/features/search/presentation/bloc/search_navbar/search_navbar_state.dart @@ -0,0 +1,25 @@ +part of 'search_navbar_bloc.dart'; + +abstract class SearchNavbarState { + // The title would either be + // - All, Educators, Students, Classes + final String title; + + SearchNavbarState(this.title); +} + +class SearchNavbarAllState extends SearchNavbarState { + SearchNavbarAllState() : super('All'); +} + +class SearchNavbarEducatorsState extends SearchNavbarState { + SearchNavbarEducatorsState() : super('Educators'); +} + +class SearchNavbarStudentsState extends SearchNavbarState { + SearchNavbarStudentsState() : super('Students'); +} + +class SearchNavbarClassesState extends SearchNavbarState { + SearchNavbarClassesState() : super('Classes'); +} \ No newline at end of file From 27eeff3fbee728b9eb1384aa3d2715589a50cfc8 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Fri, 29 Sep 2023 23:00:06 +0100 Subject: [PATCH 24/68] first commit --- .../presentation/widget/search_navbar.dart | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 lib/features/search/presentation/widget/search_navbar.dart diff --git a/lib/features/search/presentation/widget/search_navbar.dart b/lib/features/search/presentation/widget/search_navbar.dart new file mode 100644 index 0000000..3dfe96a --- /dev/null +++ b/lib/features/search/presentation/widget/search_navbar.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/components/texts.dart'; +import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/search_navbar/search_navbar_bloc.dart'; + +class SearchScreenNavbar extends StatelessWidget { + const SearchScreenNavbar({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + // All + GestureDetector( + onTap: () => _onPressNavbarItem( + context: context, event: SearchNavbarAllEvent()), + child: _buildNavItem( + state: SearchNavbarAllState(), + isSelected: state is SearchNavbarAllState), + ), + + // Educators + GestureDetector( + onTap: () => _onPressNavbarItem( + context: context, event: SearchNavbarEducatorsEvent()), + child: _buildNavItem( + state: SearchNavbarEducatorsState(), + isSelected: state is SearchNavbarEducatorsState), + ), + + // Students + GestureDetector( + onTap: () => _onPressNavbarItem( + context: context, event: SearchNavbarStudentsEvent()), + child: _buildNavItem( + state: SearchNavbarStudentsState(), + isSelected: state is SearchNavbarStudentsState), + ), + + // Classes + GestureDetector( + onTap: () => _onPressNavbarItem( + context: context, event: SearchNavbarClassesEvent()), + child: _buildNavItem( + state: SearchNavbarClassesState(), + isSelected: state is SearchNavbarClassesState), + ), + ], + ), + ), + Divider(color: kBlack.withOpacity(.3)), + ], + ); + }, + ); + } + + Container _buildNavItem( + {required SearchNavbarState state, required bool isSelected}) { + return Container( + color: Colors.transparent, + margin: const EdgeInsets.only(top: 10), + padding: state is SearchNavbarAllState + ? const EdgeInsets.fromLTRB(40, 10, 18, 10) + : const EdgeInsets.symmetric(horizontal: 18, vertical: 10), + child: TextMedium( + title: state.title, + color: isSelected ? kBlack90 : kBlack50, + weight: isSelected ? FontWeight.w600 : FontWeight.w500, + ), + ); + } + + _onPressNavbarItem({ + required BuildContext context, + required SearchNavbarEvent event, + }) { + return BlocProvider.of(context).add(event); + } +} From e9c77793d27987e6cdeb5652d0078ecd6e9d04fe Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:01:21 +0100 Subject: [PATCH 25/68] install: skeletons package --- pubspec.lock | 8 ++++++++ pubspec.yaml | 2 ++ 2 files changed, 10 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index 1581e45..4a4cb8f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -848,6 +848,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + skeletons: + dependency: "direct main" + description: + name: skeletons + sha256: "5b2d08ae7f908ee1f7007ca99f8dcebb4bfc1d3cb2143dec8d112a5be5a45c8f" + url: "https://pub.dev" + source: hosted + version: "0.0.3" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 2d276d3..9eb1f59 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,6 +60,8 @@ dependencies: # shared_preferences: ^2.2.0 # auto_route: ^7.8.0 + skeletons: ^0.0.3 + dev_dependencies: flutter_test: sdk: flutter From 1a04bced5bb3b2159099d19febe915e28bec3038 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:01:44 +0100 Subject: [PATCH 26/68] update: replace ClassModel with ClassEntity --- lib/screens/Profile/components/profile_content.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/screens/Profile/components/profile_content.dart b/lib/screens/Profile/components/profile_content.dart index 093b1fa..59496f3 100644 --- a/lib/screens/Profile/components/profile_content.dart +++ b/lib/screens/Profile/components/profile_content.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:neocloud_mobile/components/cards/class_card.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; import 'package:neocloud_mobile/graphql/services/class_service.dart'; import 'package:neocloud_mobile/models/Students.dart'; @@ -42,7 +43,7 @@ class ProfileClasses extends StatefulWidget { class _ProfileClassesState extends State { var classService = ClassService(); - List? classList; + List? classList; @override void initState() { From 357035027399e7077dccc938a4be09b6525b51df Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:02:06 +0100 Subject: [PATCH 27/68] update: replace ClassModel with ClassEntity --- lib/screens/class/class_screen.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/screens/class/class_screen.dart b/lib/screens/class/class_screen.dart index be6a0f6..fbd344c 100644 --- a/lib/screens/class/class_screen.dart +++ b/lib/screens/class/class_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:neocloud_mobile/components/cards/class_card.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; import 'package:neocloud_mobile/models/Class.dart'; import 'package:neocloud_mobile/screens/class/components/class_syllabus.dart'; @@ -10,7 +11,7 @@ import 'package:neocloud_mobile/screens/class/components/class_syllabus.dart'; class ClassScreen extends StatefulWidget { const ClassScreen({super.key, required this.clas}); static String screenName = 'class'; - final ClassModel clas; + final ClassEntity clas; @override State createState() => _ClassScreenState(); From 9a634ffbf91b7c05821d4b5f5f29c928e261bdb8 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:02:35 +0100 Subject: [PATCH 28/68] update: use updated ClassModel and ClassEntity --- lib/graphql/services/class_service.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/graphql/services/class_service.dart b/lib/graphql/services/class_service.dart index 9facbe5..9484977 100644 --- a/lib/graphql/services/class_service.dart +++ b/lib/graphql/services/class_service.dart @@ -1,7 +1,8 @@ import 'package:flutter/cupertino.dart'; import 'package:neocloud_mobile/components/popups/popups.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; +import 'package:neocloud_mobile/core/models/class_model.dart'; import 'package:neocloud_mobile/graphql/graphql_config.dart'; -import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:neocloud_mobile/utils/error_handler.dart'; // import 'package:graphql_flutter/graphql_flutter.dart'; @@ -11,7 +12,7 @@ class ClassService { static var config = GraphQLConfig(); var client = config.client; - Future> getClasses({int? limit}) async { + Future> getClasses({int? limit}) async { String classesQuery = """ query Query(\$limit: Int, \$name: String) { classes(limit: \$limit, name: \$name) { @@ -53,7 +54,7 @@ class ClassService { List? classes = result.data?['classes']; if (classes == null) return []; - List classList = classes.map((clas) => ClassModel.fromMap(aClass: clas)).toList(); + List classList = classes.map((clas) => ClassModel.fromMap(data: clas)).toList(); return classList; } From d871b5faee9d5f86772bbf3f342baa38d79c610a Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:02:57 +0100 Subject: [PATCH 29/68] improve code --- lib/screens/login_signup/login_signup_screen.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/screens/login_signup/login_signup_screen.dart b/lib/screens/login_signup/login_signup_screen.dart index cd67c28..ccda3fc 100644 --- a/lib/screens/login_signup/login_signup_screen.dart +++ b/lib/screens/login_signup/login_signup_screen.dart @@ -6,7 +6,6 @@ import 'package:neocloud_mobile/constraints.dart'; import 'package:neocloud_mobile/graphql/services/auth_service.dart'; import 'package:neocloud_mobile/screens/login_signup/components/login_form.dart'; import 'package:neocloud_mobile/screens/login_signup/components/signup_form.dart'; -import 'package:neocloud_mobile/screens/search/search_screen.dart'; import 'package:neocloud_mobile/size_config.dart'; // @RoutePage() From f23ba700b416964f5503009a97029be5b53b4ff6 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:03:19 +0100 Subject: [PATCH 30/68] comment out entire code --- .../components/personel_dashboard.dart | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/lib/screens/dashboard/components/personel_dashboard.dart b/lib/screens/dashboard/components/personel_dashboard.dart index c7d1f19..97f6c86 100644 --- a/lib/screens/dashboard/components/personel_dashboard.dart +++ b/lib/screens/dashboard/components/personel_dashboard.dart @@ -1,72 +1,72 @@ -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/models/Students.dart'; -import 'package:neocloud_mobile/screens/dashboard/components/list_user_activity_tile.dart'; -import 'package:neocloud_mobile/screens/dashboard/components/personel_navbar.dart'; +// import 'package:flutter/material.dart'; +// import 'package:neocloud_mobile/constraints.dart'; +// import 'package:neocloud_mobile/models/Students.dart'; +// import 'package:neocloud_mobile/screens/dashboard/components/list_user_activity_tile.dart'; +// import 'package:neocloud_mobile/screens/dashboard/components/personel_navbar.dart'; -class PersonelDashboard extends StatefulWidget { - const PersonelDashboard({ - super.key, - }); +// class PersonelDashboard extends StatefulWidget { +// const PersonelDashboard({ +// super.key, +// }); - @override - State createState() => _PersonelDashboardState(); -} +// @override +// State createState() => _PersonelDashboardState(); +// } -class _PersonelDashboardState extends State { - int selectedNavIndex = 0; - List navItems = ["Admin", "Educator", "Student"]; +// class _PersonelDashboardState extends State { +// int selectedNavIndex = 0; +// List navItems = ["Admin", "Educator", "Student"]; - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Navbar - Admins Educators Hods Students - PersonelNavBar( - navItems: navItems, - selectedIndex: selectedNavIndex, - press: (index) => setState(() { - selectedNavIndex = index; - }), - ), +// @override +// Widget build(BuildContext context) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// // Navbar - Admins Educators Hods Students +// PersonelNavBar( +// navItems: navItems, +// selectedIndex: selectedNavIndex, +// press: (index) => setState(() { +// selectedNavIndex = index; +// }), +// ), - // Personel List - Display based on selectedNavBarItem - const SizedBox(height: 20), - Container( - constraints: const BoxConstraints(minHeight: 270), - padding: screenPadding, - decoration: BoxDecoration(border: Border(bottom: appsBorder)), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Admins - 0 - selectedNavIndex == 0 - ? ListUserActivityTile(users: getFilteredUsersList(0)) - : const SizedBox(), - // Educators - 1 - selectedNavIndex == 1 - ? ListUserActivityTile(users: getFilteredUsersList(1)) - : const SizedBox(), - // Hods - 2 - selectedNavIndex == 2 - ? ListUserActivityTile(users: getFilteredUsersList(2)) - : const SizedBox(), - ], - ), - ) - ], - ) - ], - ); - } +// // Personel List - Display based on selectedNavBarItem +// const SizedBox(height: 20), +// Container( +// constraints: const BoxConstraints(minHeight: 270), +// padding: screenPadding, +// decoration: BoxDecoration(border: Border(bottom: appsBorder)), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// // Admins - 0 +// selectedNavIndex == 0 +// ? ListUserActivityTile(users: getFilteredUsersList(0)) +// : const SizedBox(), +// // Educators - 1 +// selectedNavIndex == 1 +// ? ListUserActivityTile(users: getFilteredUsersList(1)) +// : const SizedBox(), +// // Hods - 2 +// selectedNavIndex == 2 +// ? ListUserActivityTile(users: getFilteredUsersList(2)) +// : const SizedBox(), +// ], +// ), +// ) +// ], +// ) +// ], +// ); +// } - getFilteredUsersList(int i) { - return users.where((element) { - return element.role.contains(navItems[i]); - }).toList(); - } -} +// getFilteredUsersList(int i) { +// return users.where((element) { +// return element.role.contains(navItems[i]); +// }).toList(); +// } +// } From ac6ba7e1a2ca45006bdcd3315c7b7b29179f3371 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:03:33 +0100 Subject: [PATCH 31/68] comment out entire code --- .../components/grant_permission.dart | 142 +++++++++--------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/lib/screens/dashboard/components/grant_permission.dart b/lib/screens/dashboard/components/grant_permission.dart index adf80c1..06f77f3 100644 --- a/lib/screens/dashboard/components/grant_permission.dart +++ b/lib/screens/dashboard/components/grant_permission.dart @@ -1,74 +1,74 @@ -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/buttons.dart'; -import 'package:neocloud_mobile/components/texts.dart'; -import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/screens/comming_soon/comming_soon_screen.dart'; +// import 'package:flutter/material.dart'; +// import 'package:neocloud_mobile/components/buttons.dart'; +// import 'package:neocloud_mobile/components/texts.dart'; +// import 'package:neocloud_mobile/constraints.dart'; +// import 'package:neocloud_mobile/screens/comming_soon/comming_soon_screen.dart'; -class GrantPermission extends StatelessWidget { - const GrantPermission({ - super.key, - }); +// class GrantPermission extends StatelessWidget { +// const GrantPermission({ +// super.key, +// }); - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Grant Permission - const SizedBox(height: 30), - Padding( - padding: screenPadding, - child: TextCustom( - title: "Grant Permission", - fontSize: 22, - color: kBlack80, - weight: FontWeight.w600, - ), - ), - const SizedBox(height: 20), +// @override +// Widget build(BuildContext context) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// // Grant Permission +// const SizedBox(height: 30), +// Padding( +// padding: screenPadding, +// child: TextCustom( +// title: "Grant Permission", +// fontSize: 22, +// color: kBlack80, +// weight: FontWeight.w600, +// ), +// ), +// const SizedBox(height: 20), - // Thumbs up and Text - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(width: 40), - const Image( - image: AssetImage('assets/icons/thumbs-up.png'), - width: 50, - ), - const SizedBox(width: 20), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextMedium( - title: - 'Grant Permission for Students or Educators to be able to take certain courses at NCT', - color: kBlack60, - ), - const SizedBox(height: 20), - AppsButton( - title: 'Grant', - // press: (context) => context.router.push(const ComingSoonRoute()), - press: (_) => Navigator.push( - context, - MaterialPageRoute( - builder: (_) => const ComingSoonScreen(), - )), - bgColor: kBlue, - padTopBottom: 5, - borderRadius: 40, - ), - ], - ), - ), - const SizedBox(width: 40), - ], - ), - const SizedBox( - height: 50, - ) - ], - ); - } -} +// // Thumbs up and Text +// Row( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// const SizedBox(width: 40), +// const Image( +// image: AssetImage('assets/icons/thumbs-up.png'), +// width: 50, +// ), +// const SizedBox(width: 20), +// Expanded( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// TextMedium( +// title: +// 'Grant Permission for Students or Educators to be able to take certain courses at NCT', +// color: kBlack60, +// ), +// const SizedBox(height: 20), +// AppsButton( +// title: 'Grant', +// // press: (context) => context.router.push(const ComingSoonRoute()), +// press: (_) => Navigator.push( +// context, +// MaterialPageRoute( +// builder: (_) => const ComingSoonScreen(), +// )), +// bgColor: kBlue, +// padTopBottom: 5, +// borderRadius: 40, +// ), +// ], +// ), +// ), +// const SizedBox(width: 40), +// ], +// ), +// const SizedBox( +// height: 50, +// ) +// ], +// ); +// } +// } From 66916e0cf555e4d1d161f483ad447fc9edeb0afd Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:04:29 +0100 Subject: [PATCH 32/68] update: remove PersonelDashboard and GrantPermission widgets --- lib/screens/dashboard/components/body.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/screens/dashboard/components/body.dart b/lib/screens/dashboard/components/body.dart index e0f4577..2825993 100644 --- a/lib/screens/dashboard/components/body.dart +++ b/lib/screens/dashboard/components/body.dart @@ -29,12 +29,12 @@ class Body extends StatelessWidget { DashboardSlider(), - // Section 2 - SizedBox(height: 20), - PersonelDashboard(), + // // Section 2 + // SizedBox(height: 20), + // PersonelDashboard(), - // buildGrantPermission(), - GrantPermission(), + // // buildGrantPermission(), + // GrantPermission(), ], )), ], From 70e11cf2af173b70ae12b4924fb205ebcf0249ba Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:05:04 +0100 Subject: [PATCH 33/68] update: add TextEdittingController to buildSearchTextField --- lib/screens/create/select_user_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/create/select_user_screen.dart b/lib/screens/create/select_user_screen.dart index f453839..6e2d3af 100644 --- a/lib/screens/create/select_user_screen.dart +++ b/lib/screens/create/select_user_screen.dart @@ -90,7 +90,7 @@ class _SelectUsersScreenState extends State { .contains(value.toLowerCase())) .toList(); }); - }, + }, controller: TextEditingController(), ), // Selected Count From 51f2ab6ece5b191793e559fee4380857ab438fa7 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:05:14 +0100 Subject: [PATCH 34/68] update: add TextEdittingController to buildSearchTextField --- lib/screens/create/select_faculty_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/create/select_faculty_screen.dart b/lib/screens/create/select_faculty_screen.dart index 5c32c7f..ce1a6b2 100644 --- a/lib/screens/create/select_faculty_screen.dart +++ b/lib/screens/create/select_faculty_screen.dart @@ -86,7 +86,7 @@ class _SelectFacultyScreenState extends State { setState(() { facultiesToSelectFrom = widget.faculties.where((fac) => fac.name.toLowerCase().contains(value.toLowerCase())).toList(); }); - }, + }, controller: TextEditingController(), ), // Selected Count From 4dbab0d2ce551a3cf7209a68d30eeaf7593e71d6 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:05:32 +0100 Subject: [PATCH 35/68] improve code --- lib/providers/NavItem.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/providers/NavItem.dart b/lib/providers/NavItem.dart index 665dc26..e958ce1 100644 --- a/lib/providers/NavItem.dart +++ b/lib/providers/NavItem.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:neocloud_mobile/features/search/presentation/pages/search_screen.dart'; import 'package:neocloud_mobile/screens/Profile/profile_sceen.dart'; import 'package:neocloud_mobile/screens/academic/academic_screen.dart'; import 'package:neocloud_mobile/screens/dashboard/dashboard_screen.dart'; import 'package:neocloud_mobile/screens/notifications/notifications_screen.dart'; -import 'package:neocloud_mobile/screens/search/search_screen.dart'; +import 'package:neocloud_mobile/features/search/presentation/pages/search_screen.dart'; class NavItem { final String svgActive; @@ -37,7 +38,7 @@ class NavbarProvider extends ChangeNotifier { itemLabel: "Dashboard", destination: DashboardScreen(), ), - const NavItem( + NavItem( svgActive: "assets/icons/navbar/search-fill.svg", svgInactive: "assets/icons/navbar/search-outline.svg", itemLabel: "Search", From ed7df4a59a76ccd8130132a36daebf86bfd8ace3 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:06:10 +0100 Subject: [PATCH 36/68] improve code --- .../bloc/remote/users/remote_user_state.dart | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart b/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart index 227299b..009d9e1 100644 --- a/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart +++ b/lib/features/search/presentation/bloc/remote/users/remote_user_state.dart @@ -1,28 +1,31 @@ import 'package:equatable/equatable.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; -abstract class RemoteUserState extends Equatable { +abstract class RemoteUsersState extends Equatable { final List ? users; final Error ? error; - const RemoteUserState({this.users, this.error}); + const RemoteUsersState({this.users, this.error}); @override List get props => [users, error]; } -class RemoteUserLoadingState extends RemoteUserState { - const RemoteUserLoadingState(); +class RemoteUsersLoadingState extends RemoteUsersState { + const RemoteUsersLoadingState(); +} +class RemoteUsersLoadingMoreState extends RemoteUsersState { + const RemoteUsersLoadingMoreState(List ? existingUsers) : super(users: existingUsers); } -class RemoteUserWaitingState extends RemoteUserState { - const RemoteUserWaitingState(); +class RemoteUsersInitialState extends RemoteUsersState { + const RemoteUsersInitialState(); } -class RemoteUserDoneState extends RemoteUserState { - const RemoteUserDoneState(List users) : super(users: users); +class RemoteUsersDoneState extends RemoteUsersState { + const RemoteUsersDoneState(List users) : super(users: users); } -class RemoteUserErrorState extends RemoteUserState { - const RemoteUserErrorState(Error error) : super(error: error); +class RemoteUsersFailState extends RemoteUsersState { + const RemoteUsersFailState(Error error) : super(error: error); } \ No newline at end of file From 4c22c94b0cdcc07f2b66a61dae462b7308d67661 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:06:18 +0100 Subject: [PATCH 37/68] improve code --- .../presentation/bloc/remote/users/remote_user_event.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart b/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart index 6ef57c5..476d3db 100644 --- a/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart +++ b/lib/features/search/presentation/bloc/remote/users/remote_user_event.dart @@ -1,8 +1,12 @@ +import 'package:neocloud_mobile/core/entities/user_entity.dart'; + abstract class RemoteUserEvent { final String text; - const RemoteUserEvent(this.text); + final List existingUsers; + final int page; + const RemoteUserEvent({required this.text, required this.existingUsers, required this.page}); } class GetUserEvent extends RemoteUserEvent { - const GetUserEvent(super.text); + const GetUserEvent({required super.text, required super.existingUsers, required super.page}); } \ No newline at end of file From af10e0a208a0b0fce6c78b19223848a03dc2bec2 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:06:38 +0100 Subject: [PATCH 38/68] improve code --- .../presentation/bloc/remote/classes/remote_class_state.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart b/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart index 94bedfd..627a495 100644 --- a/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart +++ b/lib/features/search/presentation/bloc/remote/classes/remote_class_state.dart @@ -13,6 +13,9 @@ abstract class RemoteClassesState extends Equatable { class RemoteClassesLoadingState extends RemoteClassesState { const RemoteClassesLoadingState(); } +class RemoteClassesLoadingMoreState extends RemoteClassesState { + const RemoteClassesLoadingMoreState(List ? existingClasses) : super(classes: existingClasses); +} class RemoteClassesInitialState extends RemoteClassesState { const RemoteClassesInitialState(); From 8d6342b0a7d390fd54ca5d3b2162dd3ff12f8431 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:06:46 +0100 Subject: [PATCH 39/68] improve code --- .../bloc/remote/classes/remote_class_event.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart b/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart index c1f09cc..1935110 100644 --- a/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart +++ b/lib/features/search/presentation/bloc/remote/classes/remote_class_event.dart @@ -2,10 +2,12 @@ part of 'remote_class_bloc.dart'; abstract class RemoteClassesEvent { final String text; + final List existingClasses; + final int page; - RemoteClassesEvent(this.text); + RemoteClassesEvent({required this.text, required this.existingClasses, required this.page}); } class GetClassesEvent extends RemoteClassesEvent { - GetClassesEvent(String text) : super(text); + GetClassesEvent({required super.text, required super.existingClasses, required super.page}); } From d187aa18d7c2732b0aa9c56f8b08b8011d07af56 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:07:12 +0100 Subject: [PATCH 40/68] complete onGetClassesEvent Implementation --- .../remote/classes/remote_class_bloc.dart | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart b/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart index d12d125..c1f5f16 100644 --- a/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart +++ b/lib/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart @@ -14,10 +14,24 @@ class RemoteClassBloc extends Bloc { on(onGetClassesEvent); } - Future onGetClassesEvent(RemoteClassesEvent event, Emitter emit) async { - emit(const RemoteClassesLoadingState()); - final dataState = await _getClassUseCase.call(param1: event.text); - final newState = RemoteClassesDoneState(dataState.data!); - emit(newState); + Future onGetClassesEvent(RemoteClassesEvent getClassesEvent, Emitter emit) async { + if (getClassesEvent.text.isEmpty) { + var initialState = const RemoteClassesInitialState(); + return emit(initialState); + } + + if (getClassesEvent.page == 1) { + emit(const RemoteClassesLoadingState()); + } else { + emit(RemoteClassesLoadingMoreState(getClassesEvent.existingClasses)); + } + + final dataState = await _getClassUseCase.call(param1: getClassesEvent.text, param2: getClassesEvent.page); + if (dataState.data != null) { + final newState = RemoteClassesDoneState([...getClassesEvent.existingClasses, ...dataState.data!]); + emit(newState); + }else { + print('Dat State Classes Error 😄!'); + } } } \ No newline at end of file From 702f192ef67db07a9564872a4acae6910b66891f Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:07:25 +0100 Subject: [PATCH 41/68] complete onGetUsers Implementation --- .../bloc/remote/users/remote_user_bloc.dart | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart b/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart index 104dcc9..309cee2 100644 --- a/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart +++ b/lib/features/search/presentation/bloc/remote/users/remote_user_bloc.dart @@ -1,17 +1,33 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; import 'package:neocloud_mobile/features/search/domain/usecases/get_users.dart'; import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_event.dart'; import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_state.dart'; - -class RemoteUserBloc extends Bloc { +class RemoteUserBloc extends Bloc { final GetUsersUseCase _getUsersUseCase; - RemoteUserBloc(this._getUsersUseCase) : super(const RemoteUserWaitingState()) { + RemoteUserBloc(this._getUsersUseCase) : super(const RemoteUsersInitialState()) { on(onGetUsers); } + Future onGetUsers(GetUserEvent getUserEvent, Emitter emit) async { + if (getUserEvent.text.isEmpty) { + var initialState = const RemoteUsersInitialState(); + return emit(initialState); + } + + if (getUserEvent.page == 1) { + emit(const RemoteUsersLoadingState()); + } else { + emit(RemoteUsersLoadingMoreState(getUserEvent.existingUsers)); + } + + final dataState = await _getUsersUseCase.call(param1: getUserEvent.text, param2: getUserEvent.page); - void onGetUsers(GetUserEvent getUserEvent, Emitter emit) { - print('onGetUsers RAN!'); - final data = _getUsersUseCase.call(param: getUserEvent.text); + if (dataState.data != null) { + final newState = RemoteUsersDoneState([...getUserEvent.existingUsers, ...dataState.data!]); + emit(newState); + } else { + print('Bloc Data State Error Encountered 😄!'); + } } -} \ No newline at end of file +} From c38e8efa56fa9b82647419aa9d314c3b7ca01169 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:07:53 +0100 Subject: [PATCH 42/68] add 3rd generic type --- lib/features/search/domain/usecases/usecase.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/search/domain/usecases/usecase.dart b/lib/features/search/domain/usecases/usecase.dart index 8c2b499..94e77d3 100644 --- a/lib/features/search/domain/usecases/usecase.dart +++ b/lib/features/search/domain/usecases/usecase.dart @@ -1,3 +1,3 @@ -abstract class UseCase { - Future call({required Param param}); +abstract class UseCase { + Future call({required Param1 param1, required Param2 param2}); } \ No newline at end of file From e24ec8912a0e533af650bf611f1bf1a4577fc85a Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:08:52 +0100 Subject: [PATCH 43/68] complete code --- lib/features/search/domain/usecases/get_users.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/features/search/domain/usecases/get_users.dart b/lib/features/search/domain/usecases/get_users.dart index e467d14..8bd7d01 100644 --- a/lib/features/search/domain/usecases/get_users.dart +++ b/lib/features/search/domain/usecases/get_users.dart @@ -1,15 +1,15 @@ +import 'package:neocloud_mobile/core/entities/user_entity.dart'; import 'package:neocloud_mobile/core/resources/data_state.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; import 'package:neocloud_mobile/features/search/domain/repository/user_repository.dart'; import 'package:neocloud_mobile/features/search/domain/usecases/usecase.dart'; -class GetUsersUseCase implements UseCase>, String> { +class GetUsersUseCase implements UseCase>, String, int> { final UserRepository _userRepository; const GetUsersUseCase(this._userRepository); @override - Future>> call({required String param}) async { - return await _userRepository.getUsers(name: param); + Future>> call({required String param1, int ? param2}) async { + return await _userRepository.getUsers(name: param1, page: param2); } } From deda96c8db3661078978704b6d588a6f9a5ed79a Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:09:02 +0100 Subject: [PATCH 44/68] complete code --- lib/features/search/domain/usecases/get_class.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/features/search/domain/usecases/get_class.dart b/lib/features/search/domain/usecases/get_class.dart index 8318a01..98b854f 100644 --- a/lib/features/search/domain/usecases/get_class.dart +++ b/lib/features/search/domain/usecases/get_class.dart @@ -1,15 +1,15 @@ +import 'package:neocloud_mobile/core/entities/class_entity.dart'; import 'package:neocloud_mobile/core/resources/data_state.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; import 'package:neocloud_mobile/features/search/domain/repository/class_repository.dart'; import 'package:neocloud_mobile/features/search/domain/usecases/usecase.dart'; -class GetClassUseCase implements UseCase { +class GetClassUseCase implements UseCase>, String, int> { final ClassRepository _classRepository; const GetClassUseCase(this._classRepository); @override - Future>> call({param}) { - return _classRepository.getClasses(); + Future>> call({required String param1, int ? param2}) { + return _classRepository.getClasses(name: param1, page: param2); } } \ No newline at end of file From def6ca0775d3a10c299f64c4e4310bb0f5e8d1a1 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:09:10 +0100 Subject: [PATCH 45/68] complete code --- lib/features/search/domain/repository/user_repository.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/search/domain/repository/user_repository.dart b/lib/features/search/domain/repository/user_repository.dart index b1eec5e..b71098e 100644 --- a/lib/features/search/domain/repository/user_repository.dart +++ b/lib/features/search/domain/repository/user_repository.dart @@ -1,6 +1,6 @@ +import 'package:neocloud_mobile/core/entities/user_entity.dart'; import 'package:neocloud_mobile/core/resources/data_state.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; abstract class UserRepository { - Future>> getUsers({required String name, int ? limit}); + Future>> getUsers({required String name, int ? page}); } \ No newline at end of file From a149b31beeb84eb85764a3bf89a69e5546b52aef Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:09:20 +0100 Subject: [PATCH 46/68] complete code --- lib/features/search/domain/repository/class_repository.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/search/domain/repository/class_repository.dart b/lib/features/search/domain/repository/class_repository.dart index 0fcee85..169bd27 100644 --- a/lib/features/search/domain/repository/class_repository.dart +++ b/lib/features/search/domain/repository/class_repository.dart @@ -1,6 +1,6 @@ +import 'package:neocloud_mobile/core/entities/class_entity.dart'; import 'package:neocloud_mobile/core/resources/data_state.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; abstract class ClassRepository { - Future>> getClasses(); + Future>> getClasses({required String name, int ? page}); } \ No newline at end of file From cd155b5da2e7f18e3d9d031115d2bd3220ff6ebf Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:09:31 +0100 Subject: [PATCH 47/68] complete code --- .../data/repository/user_repository_impl.dart | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/features/search/data/repository/user_repository_impl.dart b/lib/features/search/data/repository/user_repository_impl.dart index 718c96b..a07a345 100644 --- a/lib/features/search/data/repository/user_repository_impl.dart +++ b/lib/features/search/data/repository/user_repository_impl.dart @@ -1,8 +1,9 @@ +import 'package:neocloud_mobile/components/popups/popups.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; import 'package:neocloud_mobile/features/search/data/data_sources/remote/search_service.dart'; -import 'package:neocloud_mobile/features/search/domain/entities/user_entity.dart'; import 'package:neocloud_mobile/core/resources/data_state.dart'; import 'package:neocloud_mobile/features/search/domain/repository/user_repository.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; + class UserRepositoryImpl implements UserRepository { final SearchService _apiService; @@ -10,14 +11,13 @@ class UserRepositoryImpl implements UserRepository { UserRepositoryImpl(this._apiService); @override - Future>> getUsers({required String name, int ? limit}) async { - var usersList = await _apiService.getUsers(limit: limit, name: name); - print('Users List'); - print(usersList); - - - throw UnimplementedError(); - - // return DataSuccess>(usersList); + Future>> getUsers({required String name, int ? page}) async { + try { + final users = await _apiService.getUsers(page: page, name: name); + return DataSuccess>(users); + } on Exception catch (e) { + showTopAlertDialog(text: 'Something went wrong!'); + return DataError(e); + } } } \ No newline at end of file From 0a585c42e9406b29679d2e78e03aafc1784c04da Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:09:38 +0100 Subject: [PATCH 48/68] complete code --- .../data/repository/class_repository_impl.dart | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/features/search/data/repository/class_repository_impl.dart b/lib/features/search/data/repository/class_repository_impl.dart index adc702c..e899c92 100644 --- a/lib/features/search/data/repository/class_repository_impl.dart +++ b/lib/features/search/data/repository/class_repository_impl.dart @@ -1,4 +1,6 @@ -import 'package:neocloud_mobile/features/search/domain/entities/class_entity.dart'; +import 'package:neocloud_mobile/components/popups/popups.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; +import 'package:neocloud_mobile/core/models/class_model.dart'; import 'package:neocloud_mobile/core/resources/data_state.dart'; import 'package:neocloud_mobile/features/search/domain/repository/class_repository.dart'; import 'package:neocloud_mobile/features/search/data/data_sources/remote/search_service.dart'; @@ -10,9 +12,14 @@ class ClassRepositoryImpl implements ClassRepository { ClassRepositoryImpl(this._apiService); @override - Future>> getClasses() { - // TODO: implement getClasses - throw UnimplementedError(); + Future>> getClasses({required String name, int ? page}) async { + try { + final classes = await _apiService.getClasses(page: page, name: name); + return DataSuccess>(classes); + } on Exception catch (e) { + showTopAlertDialog(text: 'Something went wrong!'); + return DataError(e); + } } } \ No newline at end of file From 011bd42d52b97fc2d6e748e4c2c37021c68448e8 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:10:03 +0100 Subject: [PATCH 49/68] complete code --- .../data_sources/remote/search_service.dart | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/lib/features/search/data/data_sources/remote/search_service.dart b/lib/features/search/data/data_sources/remote/search_service.dart index ececc2f..c695794 100644 --- a/lib/features/search/data/data_sources/remote/search_service.dart +++ b/lib/features/search/data/data_sources/remote/search_service.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/app_secure_storage.dart'; import 'package:neocloud_mobile/components/popups/popups.dart'; +import 'package:neocloud_mobile/core/models/class_model.dart'; +import 'package:neocloud_mobile/core/models/user_model.dart'; import 'package:neocloud_mobile/graphql/graphql_config.dart'; -import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; import 'package:neocloud_mobile/utils/error_handler.dart'; @@ -12,10 +11,10 @@ class SearchService { static var config = GraphQLConfig(); var client = config.client; - Future> getUsers({int? limit, String? name}) async { + Future> getUsers({int? page, String? name}) async { String usersQuery = """ - query Query(\$limit: Int, \$userName: String) { - users(name: \$userName, limit: \$limit) { + query Query(\$page: Int, \$userName: String) { + users(name: \$userName, page: \$page) { _id name bio @@ -32,26 +31,17 @@ class SearchService { """; try { - print('TOKEN BEFORE'); - print(await AppSecureStorage.getToken()); - // print(await client.value); - + print(page); var result = await client.value.query(QueryOptions( document: gql(usersQuery), - variables: {'limit': limit, 'userName': name}, + variables: {'page': page ?? 1, 'userName': name}, )); - print('TOKEN AFTER'); - print(await AppSecureStorage.getToken()); - - print('RESULT:'); - print(result); - if (result.hasException) { debugPrint("getUsers Status: ❌❌"); String error = await handleErrors(result); if (error == 'jwt expired') { - return await getUsers(limit: limit, name: name); + return await getUsers(page: page, name: name); } return []; @@ -65,21 +55,18 @@ class SearchService { List userList = users!.map((user) => UserModel.fromMap(user: user)).toList(); - print(userList); - return userList; } } catch (e) { debugPrint("getUsers Status: ❌"); - showTopAlertDialog(text: 'Something went wrong!'); throw Exception(e); } } - Future> getClasses({int? limit, String? name}) async { + Future> getClasses({int? page, String? name}) async { String classesQuery = """ - query Query(\$limit: Int, \$className: String) { - classes(limit: \$limit, name: \$className) { + query Query(\$page: Int, \$className: String) { + classes(page: \$page, name: \$className) { _id name about @@ -103,14 +90,14 @@ class SearchService { try { var result = await client.value.query(QueryOptions( document: gql(classesQuery), - variables: {'limit': limit, 'className': name}, + variables: {'page': page ?? 1, 'className': name}, )); if (result.hasException) { debugPrint("getClasses Status: ❌❌"); String error = await handleErrors(result); if (error == 'jwt expired') { - return await getClasses(limit: limit, name: name); + return await getClasses(page: page, name: name); } return []; @@ -122,7 +109,7 @@ class SearchService { if (classes == null) return []; List classList = - classes.map((clas) => ClassModel.fromMap(aClass: clas)).toList(); + classes.map((clas) => ClassModel.fromMap(data: clas)).toList(); return classList; } From 39a03bd1095843c1a2edac06bddb705b5dc027ea Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:10:18 +0100 Subject: [PATCH 50/68] complete code --- lib/core/resources/data_state.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/resources/data_state.dart b/lib/core/resources/data_state.dart index f18800a..d16db33 100644 --- a/lib/core/resources/data_state.dart +++ b/lib/core/resources/data_state.dart @@ -1,6 +1,6 @@ abstract class DataState { final T ? data; - final Error ? error; + final Exception ? error; DataState({this.data, this.error}); } @@ -10,6 +10,6 @@ class DataSuccess extends DataState { } class DataError extends DataState { - DataError(Error error) : super(error: error); + DataError(Exception error) : super(error: error); } From 29a826c05fdc62ed554e966054f99649e047d8c9 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Sun, 1 Oct 2023 22:10:33 +0100 Subject: [PATCH 51/68] first commit --- lib/components/tile/user_tile.dart | 95 ++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 lib/components/tile/user_tile.dart diff --git a/lib/components/tile/user_tile.dart b/lib/components/tile/user_tile.dart new file mode 100644 index 0000000..9c09581 --- /dev/null +++ b/lib/components/tile/user_tile.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:neocloud_mobile/components/texts.dart'; +import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; +import 'package:skeletons/skeletons.dart'; + + +class UserTile extends StatelessWidget { + const UserTile({ + super.key, + required this.user, + this.trailing, + }); + + final UserEntity user; + final Widget? trailing; + + @override + Widget build(BuildContext context) { + return Container( + color: Color.fromARGB(0, 52, 51, 51), + padding: EdgeInsets.only(bottom: defaultSize * 2), + child: Row( + children: [ + // Avatar + CircleAvatar( + backgroundImage: AssetImage(user.avatar ?? 'img'), radius: defaultSize * 2.8), + // StackedImageAndDot(img: avatar, text: "1"), + SizedBox(width: defaultSize * 2), + // Name and Role + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextMedium( + title: user.name!, weight: FontWeight.w600, color: kBlack90), + TextMedium( + title: user.role != null ? user.role!.name : 'unassigned', weight: FontWeight.w500, color: kBlack50), + ], + ), + + const Spacer(), + + // trailing != null ? trailing! : const SizedBox(), + ], + ), + ); + } +} + + +class UserTileSkeleton extends StatelessWidget { + const UserTileSkeleton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return SkeletonItem( + child: Row( + children: [ + // Avatar + const SkeletonAvatar( + style: SkeletonAvatarStyle( + height: 56, + width: 56, + borderRadius: BorderRadius.all(Radius.circular(60)), + ), + ), + + // Column (name, role) + const SizedBox(width: 18), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(width: 170, child: _buildParagraph()), + SizedBox(width: 100, child: _buildParagraph()), + ], + ), + ), + ], + )); + } + + Widget _buildParagraph() { + return const SkeletonLine( + style: SkeletonLineStyle( + height: 14, + borderRadius: BorderRadius.all(Radius.circular(10)), + padding: EdgeInsets.symmetric(vertical: 5), + ), + ); + } +} + From 6036096d24fbae8c2aeee72629c8a9b557f800ef Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Wed, 4 Oct 2023 07:37:11 +0100 Subject: [PATCH 52/68] first ccommit --- assets/brand/logo-black.png | Bin 0 -> 8112 bytes assets/brand/logo-white.png | Bin 0 -> 9013 bytes assets/brand/symbol.png | Bin 0 -> 1312 bytes lib/config/theme/theme.dart | 179 ++++++++++++++++++ lib/core/bloc/auth_user/auth_user_bloc.dart | 18 ++ lib/core/bloc/auth_user/auth_user_event.dart | 11 ++ lib/core/bloc/auth_user/auth_user_state.dart | 15 ++ lib/core/bloc/context/context_bloc.dart | 15 ++ lib/core/bloc/context/context_event.dart | 11 ++ lib/core/bloc/context/context_state.dart | 15 ++ lib/core/constants/constants.dart | 17 ++ lib/core/utils/utils.dart | 10 + .../academic/components/filter_section.dart | 160 ---------------- .../components/grant_permission.dart | 74 -------- .../welcome/components/welcome_button.dart | 1 - 15 files changed, 291 insertions(+), 235 deletions(-) create mode 100644 assets/brand/logo-black.png create mode 100644 assets/brand/logo-white.png create mode 100644 assets/brand/symbol.png create mode 100644 lib/config/theme/theme.dart create mode 100644 lib/core/bloc/auth_user/auth_user_bloc.dart create mode 100644 lib/core/bloc/auth_user/auth_user_event.dart create mode 100644 lib/core/bloc/auth_user/auth_user_state.dart create mode 100644 lib/core/bloc/context/context_bloc.dart create mode 100644 lib/core/bloc/context/context_event.dart create mode 100644 lib/core/bloc/context/context_state.dart create mode 100644 lib/core/constants/constants.dart create mode 100644 lib/core/utils/utils.dart delete mode 100644 lib/screens/academic/components/filter_section.dart delete mode 100644 lib/screens/dashboard/components/grant_permission.dart delete mode 100644 lib/screens/welcome/components/welcome_button.dart diff --git a/assets/brand/logo-black.png b/assets/brand/logo-black.png new file mode 100644 index 0000000000000000000000000000000000000000..a2e5d3dad60cbcb3e578f1af74a16f6eca1152fd GIT binary patch literal 8112 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 WcDrN4M)95i0000(Colors.white), + shape: MaterialStatePropertyAll( + RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), + ), + ); +} + +OutlinedButtonThemeData _darkOutlinedButtonTheme() { + return OutlinedButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll(Colors.grey.shade900), + shape: MaterialStatePropertyAll( + RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), + ), + ); +} + +TextTheme _lightTextTheme() { + return TextTheme( + // body (sm) + bodySmall: TextStyle(color: Colors.grey.shade700, fontSize: 14), + bodyMedium: TextStyle(color: Colors.grey.shade700, fontSize: 16), + bodyLarge: TextStyle(color: Colors.grey.shade700, fontSize: 18), + // label (md) + labelSmall: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 16, fontWeight: FontWeight.w500), + labelMedium: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 18, fontWeight: FontWeight.w500), + labelLarge: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 20, fontWeight: FontWeight.w500), + // title (lg) + titleSmall: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 18, fontWeight: FontWeight.w600), + titleMedium: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 20, fontWeight: FontWeight.w600), + titleLarge: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 22, fontWeight: FontWeight.w600), + // display (xl) + displaySmall: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 20, fontWeight: FontWeight.w700), + displayMedium: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 22, fontWeight: FontWeight.w700), + displayLarge: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 24, fontWeight: FontWeight.w700), + // headline (xxl) + headlineSmall: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 26, fontWeight: FontWeight.w700), + headlineMedium: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 28, fontWeight: FontWeight.w700), + headlineLarge: TextStyle(color: Colors.black.withOpacity(.8), fontSize: 30, fontWeight: FontWeight.w700), + ); +} + +TextTheme _darkTextTheme() { + return const TextTheme( + // body (sm) + bodySmall: TextStyle(color: Colors.white70, fontSize: 14), + bodyMedium: TextStyle(color: Colors.white70, fontSize: 16), + bodyLarge: TextStyle(color: Colors.white70, fontSize: 18), + // label (md) + labelSmall: TextStyle( + color: Colors.white70, fontSize: 16, fontWeight: FontWeight.w500), + labelMedium: TextStyle( + color: Colors.white70, fontSize: 18, fontWeight: FontWeight.w500), + labelLarge: TextStyle( + color: Colors.white70, fontSize: 20, fontWeight: FontWeight.w500), + // title (lg) + titleSmall: TextStyle( + color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600), + titleMedium: TextStyle( + color: Colors.white, fontSize: 20, fontWeight: FontWeight.w600), + titleLarge: TextStyle( + color: Colors.white, fontSize: 22, fontWeight: FontWeight.w600), + // display (xl) + displaySmall: TextStyle( + color: Colors.white, fontSize: 20, fontWeight: FontWeight.w700), + displayMedium: TextStyle( + color: Colors.white, fontSize: 22, fontWeight: FontWeight.w700), + displayLarge: TextStyle( + color: Colors.white, fontSize: 24, fontWeight: FontWeight.w700), + // headline (xxl) + headlineSmall: TextStyle( + color: Colors.white, fontSize: 26, fontWeight: FontWeight.w700), + headlineMedium: TextStyle( + color: Colors.white, fontSize: 28, fontWeight: FontWeight.w700), + headlineLarge: TextStyle( + color: Colors.white, fontSize: 30, fontWeight: FontWeight.w700), + ); +} + +// TextStyle _getTextStyle({required Color color, required double fontSize, FontWeight ? fontWeight}) { +// return TextStyle( +// fontFamily: 'Poppins', +// color: color, +// fontSize: fontSize, +// fontWeight: fontWeight ?? FontWeight.w400, +// ); +// } + +AppBarTheme _lightAppBarTheme() { + return const AppBarTheme( + backgroundColor: Colors.white, + centerTitle: true, + ); +} + +AppBarTheme _darkAppBarTheme() { + return const AppBarTheme( + backgroundColor: Color(0xFF000000), + centerTitle: true, + ); +} + +MaterialColor _primarySwatch() { + return const MaterialColor( + 0xFF6699FF, + { + 50: Color(0x1A6699FF), + 100: Color(0x336699FF), + 200: Color(0x4D6699FF), + 300: Color(0x806699FF), + 400: Color(0xB36699FF), + 500: Color(0xFF6699FF), + 600: Color(0x801679F7), + 700: Color(0x991679F7), + 800: Color(0xB31679F7), + 900: Color(0xFF1679F7), + }, + ); +} diff --git a/lib/core/bloc/auth_user/auth_user_bloc.dart b/lib/core/bloc/auth_user/auth_user_bloc.dart new file mode 100644 index 0000000..5fb06ea --- /dev/null +++ b/lib/core/bloc/auth_user/auth_user_bloc.dart @@ -0,0 +1,18 @@ +import 'dart:async'; + +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; + +part 'auth_user_event.dart'; +part 'auth_user_state.dart'; + +class AuthUserBloc extends Bloc { + AuthUserBloc() : super(AuthUserInitialState()) { + on(_onSetAuthUserEvent); + } + + FutureOr _onSetAuthUserEvent(AuthUserEvent event, Emitter emit) { + emit(AuthUserDoneState(event.authUser!)); + } +} \ No newline at end of file diff --git a/lib/core/bloc/auth_user/auth_user_event.dart b/lib/core/bloc/auth_user/auth_user_event.dart new file mode 100644 index 0000000..a50f406 --- /dev/null +++ b/lib/core/bloc/auth_user/auth_user_event.dart @@ -0,0 +1,11 @@ +part of 'auth_user_bloc.dart'; + +abstract class AuthUserEvent { + final UserEntity ? authUser; + + AuthUserEvent({this.authUser}); +} + +class SetAuthUserEvent extends AuthUserEvent { + SetAuthUserEvent(UserEntity user) : super(authUser: user); +} diff --git a/lib/core/bloc/auth_user/auth_user_state.dart b/lib/core/bloc/auth_user/auth_user_state.dart new file mode 100644 index 0000000..8db96c6 --- /dev/null +++ b/lib/core/bloc/auth_user/auth_user_state.dart @@ -0,0 +1,15 @@ +part of 'auth_user_bloc.dart'; + +abstract class AuthUserState { + final UserEntity ? authUser; + + AuthUserState({this.authUser}); +} + +class AuthUserInitialState extends AuthUserState { + AuthUserInitialState(); +} + +class AuthUserDoneState extends AuthUserState { + AuthUserDoneState(UserEntity user) : super(authUser: user); +} \ No newline at end of file diff --git a/lib/core/bloc/context/context_bloc.dart b/lib/core/bloc/context/context_bloc.dart new file mode 100644 index 0000000..e507bbf --- /dev/null +++ b/lib/core/bloc/context/context_bloc.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'context_event.dart'; +part 'context_state.dart'; + +class ContextBloc extends Bloc { + ContextBloc() : super(ContextInitialState()) { + on(_onSetContextEvent); + } + + Future _onSetContextEvent(ContextEvent event, Emitter emit) async { + emit(ContextDoneState(event.context!)); + } +} \ No newline at end of file diff --git a/lib/core/bloc/context/context_event.dart b/lib/core/bloc/context/context_event.dart new file mode 100644 index 0000000..ed6da16 --- /dev/null +++ b/lib/core/bloc/context/context_event.dart @@ -0,0 +1,11 @@ +part of 'context_bloc.dart'; + +abstract class ContextEvent { + final BuildContext ? context; + + ContextEvent({this.context}); +} + +class SetContextEvent extends ContextEvent { + SetContextEvent(BuildContext context) : super(context: context); +} \ No newline at end of file diff --git a/lib/core/bloc/context/context_state.dart b/lib/core/bloc/context/context_state.dart new file mode 100644 index 0000000..b32b97b --- /dev/null +++ b/lib/core/bloc/context/context_state.dart @@ -0,0 +1,15 @@ +part of 'context_bloc.dart'; + +abstract class ContextState { + final BuildContext ? context; + + ContextState({this.context}); +} + +class ContextInitialState extends ContextState { + ContextInitialState(); +} + +class ContextDoneState extends ContextState { + ContextDoneState(BuildContext context) : super(context: context); +} \ No newline at end of file diff --git a/lib/core/constants/constants.dart b/lib/core/constants/constants.dart new file mode 100644 index 0000000..a8e61d2 --- /dev/null +++ b/lib/core/constants/constants.dart @@ -0,0 +1,17 @@ +// Company +var nct_logo_black = 'assets/brand/logo-black.png'; +var nct_logo_white = 'assets/brand/logo-white.png'; +var nct_symbol = 'assets/brand/symbol.png'; + +// Images +// const nctFaviconBlue = 'assets/images/logos/logo-icon-blue.png'; +// const nctBannerBlack = 'assets/images/logos/logo-banner-dark.png'; +// const nctBannerWhite = 'assets/images/logos/logo-banner-light.png'; +const nctFaviconBlue = 'assets/icons/logos/favicon-blue.svg'; +const nctBannerBlueBlack = 'assets/icons/logos/banner-blue-black.svg'; +const nctBannerWhite = 'assets/icons/logos/banner-blue.svg'; +// default avatars +const defaultProfileCover = 'assets/images/nct-office.jpg'; +const defaultProfileAvatar = 'assets/avatars/coffee-avatar.png'; +const defaultSlugAvatar = 'assets/avatars/cool-slug-avatar.png'; +const defaultBookStackAvatar = 'assets/avatars/book-stack-avatar.png'; diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart new file mode 100644 index 0000000..92a912f --- /dev/null +++ b/lib/core/utils/utils.dart @@ -0,0 +1,10 @@ +import 'dart:ui'; + +Color getColorOpposite(Color color) { + return Color.fromARGB( + color.alpha, + 255 - color.red, + 255 - color.green, + 255 - color.blue, + ); +} \ No newline at end of file diff --git a/lib/screens/academic/components/filter_section.dart b/lib/screens/academic/components/filter_section.dart deleted file mode 100644 index 3236b5c..0000000 --- a/lib/screens/academic/components/filter_section.dart +++ /dev/null @@ -1,160 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/headers/headear_dropdown.dart'; -import 'package:neocloud_mobile/components/texts.dart'; -import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/models/Filters.dart'; - -class FilterSection extends StatefulWidget { - const FilterSection({ - Key? key, - required this.press, - this.showMonthYear = false, - this.showRange = false, - this.showStatus = false, - this.showClass = false, - this.showSection = false, - this.showSession = false, - this.label = "Filter", - this.buttonText = "Filter", - }) : super(key: key); - - final Function(Map filterData) press; - final bool showMonthYear; - final bool showRange; - final bool showStatus; - final bool showClass; - final bool showSection; - final bool showSession; - final String label; - final String buttonText; - - @override - State createState() => _FilterSectionState(); -} - -class _FilterSectionState extends State { - Map filter = {}; - double turns = 0; - bool showContent = false; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - // Filter Header and 🔻 - HeaderWithDropdown( - title: 'Filter', - showContent: showContent, - press: () => setState(() { - showContent = !showContent; - }), - ), - - showContent - ? Column( - children: [ - // Month, Year - widget.showMonthYear - ? const SizedBox(height: 10) - : const SizedBox(), - widget.showMonthYear ? buildMonthYearField() : const SizedBox(), - - // range - widget.showRange ? const SizedBox(height: 10) : const SizedBox(), - widget.showRange - ? buildAppsDropdownButton( - list: dateRangeFilters, - press: updateFilter(k: "range"), - ) - : const SizedBox(), - - // Status - widget.showStatus - ? const SizedBox(height: 10) - : const SizedBox(), - widget.showStatus - ? buildAppsDropdownButton( - list: statusFilters, - press: updateFilter(k: "status"), - ) - : const SizedBox(), - - // Class - widget.showClass ? const SizedBox(height: 10) : const SizedBox(), - widget.showClass - ? buildAppsDropdownButton( - list: coursesFilter, - press: updateFilter(k: "class"), - ) - : const SizedBox(), - - // Section - widget.showSection - ? const SizedBox(height: 10) - : const SizedBox(), - widget.showSection - ? buildAppsDropdownButton( - list: sectionFilters, - press: updateFilter(k: "section"), - ) - : const SizedBox(), - - // Session - widget.showSession - ? const SizedBox(height: 10) - : const SizedBox(), - widget.showSession - ? buildAppsDropdownButton( - list: sessionFilters, - press: updateFilter(k: "session"), - selected: sessionFilters.last, - ) - : const SizedBox(), - - // Button - const SizedBox(height: 10), - buildFilterButton( - press: (context) { - widget.press(filter); - }, - buttonText: widget.buttonText, - ), - ], - ) - : const SizedBox(), - ], - ); - } - - Row buildMonthYearField() { - return Row( - children: [ - Expanded( - child: buildAppsDropdownButton( - list: monthsFilter, - selected: currentMonth, - press: updateFilter(k: "month"), - ), - ), - const SizedBox(width: 20), - Expanded( - child: buildAppsDropdownButton( - list: yearsFilter, - selected: yearsFilter.last, - press: updateFilter(k: "year"), - ), - ) - ], - ); - } - - // This function returns a function that's used to update the filter - // with whatever value was selected using the dropDownButton - Function(String) updateFilter({required String k}) { - return (value) { - setState(() { - filter[k] = value; - }); - }; - } -} \ No newline at end of file diff --git a/lib/screens/dashboard/components/grant_permission.dart b/lib/screens/dashboard/components/grant_permission.dart deleted file mode 100644 index 06f77f3..0000000 --- a/lib/screens/dashboard/components/grant_permission.dart +++ /dev/null @@ -1,74 +0,0 @@ -// import 'package:flutter/material.dart'; -// import 'package:neocloud_mobile/components/buttons.dart'; -// import 'package:neocloud_mobile/components/texts.dart'; -// import 'package:neocloud_mobile/constraints.dart'; -// import 'package:neocloud_mobile/screens/comming_soon/comming_soon_screen.dart'; - -// class GrantPermission extends StatelessWidget { -// const GrantPermission({ -// super.key, -// }); - -// @override -// Widget build(BuildContext context) { -// return Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// // Grant Permission -// const SizedBox(height: 30), -// Padding( -// padding: screenPadding, -// child: TextCustom( -// title: "Grant Permission", -// fontSize: 22, -// color: kBlack80, -// weight: FontWeight.w600, -// ), -// ), -// const SizedBox(height: 20), - -// // Thumbs up and Text -// Row( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// const SizedBox(width: 40), -// const Image( -// image: AssetImage('assets/icons/thumbs-up.png'), -// width: 50, -// ), -// const SizedBox(width: 20), -// Expanded( -// child: Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// TextMedium( -// title: -// 'Grant Permission for Students or Educators to be able to take certain courses at NCT', -// color: kBlack60, -// ), -// const SizedBox(height: 20), -// AppsButton( -// title: 'Grant', -// // press: (context) => context.router.push(const ComingSoonRoute()), -// press: (_) => Navigator.push( -// context, -// MaterialPageRoute( -// builder: (_) => const ComingSoonScreen(), -// )), -// bgColor: kBlue, -// padTopBottom: 5, -// borderRadius: 40, -// ), -// ], -// ), -// ), -// const SizedBox(width: 40), -// ], -// ), -// const SizedBox( -// height: 50, -// ) -// ], -// ); -// } -// } diff --git a/lib/screens/welcome/components/welcome_button.dart b/lib/screens/welcome/components/welcome_button.dart deleted file mode 100644 index 8b13789..0000000 --- a/lib/screens/welcome/components/welcome_button.dart +++ /dev/null @@ -1 +0,0 @@ - From b08b7f1367c728bc916a5afda186860c54b529f8 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Wed, 4 Oct 2023 07:42:56 +0100 Subject: [PATCH 53/68] improve code --- lib/components/calendar_widget.dart | 192 ++++++++++++++++------------ lib/constraints.dart | 106 ++++++--------- lib/injection_container.dart | 14 ++ 3 files changed, 168 insertions(+), 144 deletions(-) diff --git a/lib/components/calendar_widget.dart b/lib/components/calendar_widget.dart index 2a1a33f..ac121ae 100644 --- a/lib/components/calendar_widget.dart +++ b/lib/components/calendar_widget.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/components/widgets.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/utils/utils.dart'; import 'package:neocloud_mobile/graphql/models/ClassScheduleModel.dart'; import 'package:neocloud_mobile/utils/calendar.dart'; import 'package:neocloud_mobile/utils/locator.dart'; - class CalendarWidget extends StatefulWidget { const CalendarWidget({ super.key, @@ -33,11 +33,14 @@ class _CalendarWidgetState extends State { super.initState(); final now = DateTime.now(); // Scroll to current month section - calendarYears = calendar.getMultipleCalendarYearData(now.year-1, now.year+1); - int yearHeight = 3900; // calendar year height + calendarYears = + calendar.getMultipleCalendarYearData(now.year - 1, now.year + 1); + int yearHeight = 3900; // calendar year height int skipYear = yearHeight * 1; double monthHeightPercentage = .083; - _scrollController = ScrollController(initialScrollOffset: skipYear + yearHeight * (monthHeightPercentage * ((now.month - 1)))); + _scrollController = ScrollController( + initialScrollOffset: skipYear + + yearHeight * (monthHeightPercentage * ((now.month - 1)))); _dateSelected = widget.defaultDateSelection; } @@ -50,85 +53,114 @@ class _CalendarWidgetState extends State { padding: screenPadding, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: List.generate( - calendarYears.length, - (yearIndex) { - CalendarYear calendarYear = calendarYears[yearIndex]; - List calendarMonths = calendarYear.months; - - // return SizedBox(); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: List.generate( - calendarMonths.length, + children: List.generate(calendarYears.length, (yearIndex) { + CalendarYear calendarYear = calendarYears[yearIndex]; + List calendarMonths = calendarYear.months; + + // return SizedBox(); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: List.generate( + calendarMonths.length, (monthIndex) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 20), - - // Title - Month and Year - TextMedium(title: '${calendarMonths[monthIndex].month} ${calendarYear.year}', color: Colors.grey[700], weight: FontWeight.w500), - - // Days - const SizedBox(height: 10), - GridView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 7, mainAxisSpacing: 5, crossAxisSpacing: 5), - itemCount: calendarMonths[monthIndex].daysInMonth + calendarMonths[monthIndex].startDay, - itemBuilder: (context, index) { + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + + // Title - Month and Year + // TextMedium(title: '${calendarMonths[monthIndex].month} ${calendarYear.year}', color: Colors.grey[700], weight: FontWeight.w500), + Text( + '${calendarMonths[monthIndex].month} ${calendarYear.year}', + style: TextStyle( + fontSize: 16, + color: Theme.of(context) + .canvasColor + .withOpacity(.7), + fontWeight: FontWeight.w500), + ), + + // Days + const SizedBox(height: 10), + GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, + mainAxisSpacing: 5, + crossAxisSpacing: 5), + itemCount: calendarMonths[monthIndex].daysInMonth + + calendarMonths[monthIndex].startDay, + itemBuilder: (context, index) { + var now = DateTime.now(); + bool isCurrentMonth = + calendarYear.year == now.year && + calendarMonths[monthIndex].monthNumber == + now.month; + int day = (index + 1) - + calendarMonths[monthIndex].startDay; + DateSelection dateSelection = DateSelection( + year: calendarYear.year, + month: monthIndex + 1, + day: day); + bool dateIsSelected = _dateSelected != null && + DateSelection.compareDateSelection( + _dateSelected!, dateSelection); - var now = DateTime.now(); - bool isCurrentMonth = calendarYear.year == now.year && calendarMonths[monthIndex].monthNumber == now.month; - int day = (index + 1) - calendarMonths[monthIndex].startDay; - DateSelection dateSelection = DateSelection(year: calendarYear.year, month: monthIndex + 1, day: day); - bool dateIsSelected = _dateSelected != null && DateSelection.compareDateSelection(_dateSelected!, dateSelection); - - if (index < calendarMonths[monthIndex].startDay) { - return const SizedBox(); - } else { - return GestureDetector( - onTap: () { - setState(() { - _dateSelected = dateSelection; - }); - // press - widget.updateDateSelection(dateSelection); - }, - child: AnimatedContainer( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - height: 10, - width: 10, - decoration: BoxDecoration( - color: dateIsSelected - ? kBlueLight - : isCurrentMonth && day == now.day - ? kBlueLight.withOpacity(.3) - : null, - borderRadius: const BorderRadius.all(Radius.circular(10)) - ), - child: Center( - child: TextMedium( - title: '$day', - color: dateIsSelected - ? Colors.white - : Colors.grey[900], + if (index < calendarMonths[monthIndex].startDay) { + return const SizedBox(); + } else { + return GestureDetector( + onTap: () { + setState(() { + _dateSelected = dateSelection; + }); + // press + widget.updateDateSelection(dateSelection); + }, + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + height: 10, + width: 10, + decoration: BoxDecoration( + color: dateIsSelected + ? kBlueLight + : isCurrentMonth && day == now.day + ? kBlueLight.withOpacity(.3) + : null, + borderRadius: const BorderRadius.all( + Radius.circular(10))), + child: Center( + // child: TextMedium( + // title: '$day', + // color: dateIsSelected + // ? Colors.white + // : Colors.grey[900], + // ), + child: Text( + '$day', + style: TextStyle( + fontSize: 16, + color: dateIsSelected + ? getColorOpposite( + Theme.of(context).canvasColor) + : Theme.of(context) + .canvasColor + .withOpacity(.9), + ), + )), ), - ), - ), - ); - } - }, - ), - const SizedBox(height: 20), - const HorizontalRule(), - ], - ) - ), - ); - } - ).toList(), + ); + } + }, + ), + const SizedBox(height: 20), + const HorizontalRule(), + ], + )), + ); + }).toList(), ), ), ); diff --git a/lib/constraints.dart b/lib/constraints.dart index 82accf9..962adc2 100644 --- a/lib/constraints.dart +++ b/lib/constraints.dart @@ -8,21 +8,6 @@ import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/models/Courses.dart'; import 'package:neocloud_mobile/size_config.dart'; -// Images -// const nctFaviconBlue = 'assets/images/logos/logo-icon-blue.png'; -// const nctBannerBlack = 'assets/images/logos/logo-banner-dark.png'; -// const nctBannerWhite = 'assets/images/logos/logo-banner-light.png'; -const nctFaviconBlue = 'assets/icons/logos/favicon-blue.svg'; -const nctBannerBlueBlack = 'assets/icons/logos/banner-blue-black.svg'; -const nctBannerWhite = 'assets/icons/logos/banner-blue.svg'; -// default avatars -const defaultProfileCover = 'assets/images/nct-office.jpg'; -const defaultProfileAvatar = 'assets/avatars/coffee-avatar.png'; -const defaultSlugAvatar = 'assets/avatars/cool-slug-avatar.png'; -const defaultBookStackAvatar = 'assets/avatars/book-stack-avatar.png'; - - - // Sizes (Integers and Doubles) var defaultSize = SizeConfig.defaultSize!; @@ -45,8 +30,6 @@ double buttonBorderRadius = 5; // Colors Color kBlue = const Color(0xFF1679F7); Color kBlueLight = const Color(0xFF1679F7).withOpacity(.7); -// Color kBlue = const Color(0xFF6699FF); -// Color kBlueLight = const Color(0xFF6699FF).withOpacity(.7); Color kWhite = const Color(0xFFFFFFFF); Color kBlack = const Color(0xFF000000); @@ -56,16 +39,12 @@ Color kBlack70 = const Color(0xFF000000).withOpacity(.7); Color kBlack80 = const Color(0xFF000000).withOpacity(.8); Color kBlack90 = const Color(0xFF000000).withOpacity(.9); -const kTextColor = Color(0xFF202E2E); -const kTextLigntColor = Color(0xFF7286A5); - // - Secondary Color kStarColor = const Color(0XFFF7AC16); Color kOrange = const Color(0xFFF7941D); Color kGreen = const Color(0xFF2B5D18); Color kRed = const Color(0xFFD0102B); -Color appsSplashColor = kBlack.withOpacity(.05); double appsSplashRadius = 50; // FUNCTIONS @@ -141,7 +120,6 @@ PreferredSize buildAppBar({ preferredSize: const Size.fromHeight(65), child: AppsAppBar( title: title, - isDark: isDark, bgColor: bgColor, actionIcon1: actionIcon, actionSvg1: actionSvg, @@ -155,8 +133,6 @@ PreferredSize buildAppBar({ AppsSliverAppBar buildSliverAppBar({ required String title, - bool isDark = false, - Color? bgColor, bool showLeading = true, bool showAction1 = true, bool showAction2 = false, @@ -171,8 +147,6 @@ AppsSliverAppBar buildSliverAppBar({ Widget? routeWidget2, // Function(BuildContext context)? press, }) { - // give to if it is null - bgColor ??= kBlue; // if neither actionSvg or actionIcon was provided, then we want to // set a default actionSvg value (to be displayed) actionSvg1 = actionSvg1 == null && actionIcon1 == null @@ -181,8 +155,6 @@ AppsSliverAppBar buildSliverAppBar({ return AppsSliverAppBar( title: title, - isDark: isDark, - bgColor: bgColor, actionIcon1: actionIcon1, actionIcon2: actionIcon2, actionSvg1: actionSvg1, @@ -296,43 +268,49 @@ Row buildDownloadButton({required Function(BuildContext? context) press}) { // - Avatar: Username // e.g 😎 john doe -Row buildAvatarAndName({ - required String avatar, - required String name, - double imgSize = 30, - double fontSize = 16, - double imgBorderSize = 0, - FontWeight weight = FontWeight.w400, - Color? color, -}) { - return Row( - children: [ - RoundBoxAvatar( - size: imgSize, - image: avatar, - borderSize: imgBorderSize, - ), - const SizedBox(width:10), - Expanded( - child: TextCustomMaxLine( - title: name, - color: color ?? kBlack70, - fontSize: fontSize, - weight: weight, - ), - ) - ], - ); -} -// - Search TextField -Widget buildSearchTextField({required Function(String value) press, required Function(String value) onChangePress}) { - return AppsTextField( - prefixIcon: Icons.search, - hintText: "Search", - onSubmitPress: press, - onChangePress: onChangePress, - ); +class CircularAvartarAndName extends StatelessWidget { + const CircularAvartarAndName({ + super.key, + required this.avatar, + required this.name, + this.imgSize = 30, + this.fontSize = 16, + this.imgBorderSize = 0, + this.weight = FontWeight.w400, + this.color, + }); + + final String avatar; + final String name; + final double imgSize; + final double fontSize; + final double imgBorderSize; + final FontWeight weight; + final Color? color; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + RoundBoxAvatar( + size: imgSize, + image: avatar, + borderSize: imgBorderSize, + ), + const SizedBox(width: 10), + Expanded( + child: TextCustomMaxLine( + title: name, + color: color ?? Theme.of(context).canvasColor.withOpacity(.7), + fontSize: fontSize, + weight: weight, + ), + ) + ], + ); + ; + } } // - Mini Course Card diff --git a/lib/injection_container.dart b/lib/injection_container.dart index d3d8301..730083e 100644 --- a/lib/injection_container.dart +++ b/lib/injection_container.dart @@ -1,8 +1,12 @@ import 'package:get_it/get_it.dart'; +import 'package:neocloud_mobile/core/bloc/auth_user/auth_user_bloc.dart'; +import 'package:neocloud_mobile/core/bloc/context/context_bloc.dart'; import 'package:neocloud_mobile/features/search/domain/repository/class_repository.dart'; import 'package:neocloud_mobile/features/search/domain/usecases/get_class.dart'; import 'package:neocloud_mobile/features/search/domain/usecases/get_users.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/remote/classes/remote_class_bloc.dart'; import 'package:neocloud_mobile/features/search/presentation/bloc/remote/users/remote_user_bloc.dart'; +import 'package:neocloud_mobile/features/search/presentation/bloc/search_navbar/search_navbar_bloc.dart'; import 'features/search/data/data_sources/remote/search_service.dart'; import 'features/search/data/repository/class_repository_impl.dart'; @@ -12,6 +16,14 @@ import 'features/search/domain/repository/user_repository.dart'; final sl = GetIt.instance; void initiallizeDependencies () { + searchFeatureDependencies(); + + // bloc + sl.registerFactory(() => AuthUserBloc()); + sl.registerFactory(() => ContextBloc()); +} + +void searchFeatureDependencies() { // Data sl.registerSingleton(SearchService()); sl.registerSingleton(UserRepositoryImpl(sl())); @@ -23,4 +35,6 @@ void initiallizeDependencies () { // Presentation (bloc) sl.registerFactory(() => RemoteUserBloc(sl())); + sl.registerFactory(() => RemoteClassBloc(sl())); + sl.registerFactory(() => SearchNavbarBloc()); } \ No newline at end of file From 2b89dff1c63eedd72ee766aa820b14f130727a72 Mon Sep 17 00:00:00 2001 From: dc <00danzy@gmail.com> Date: Wed, 4 Oct 2023 07:46:51 +0100 Subject: [PATCH 54/68] implement: use Theme color --- lib/components/Lists/class_list.dart | 71 ++- lib/components/Lists/class_schedule_list.dart | 4 +- lib/components/Lists/class_works_list.dart | 4 +- lib/components/Lists/faculty_list.dart | 4 +- lib/components/Lists/user_list.dart | 71 +-- lib/components/appbar/actions.dart | 8 +- lib/components/appbar/appbar.dart | 53 +-- lib/components/appbar/leading.dart | 9 +- .../bottom_navbar/apps_bottom_navbar.dart | 9 +- lib/components/buttons.dart | 169 +++---- lib/components/cards/cart_card.dart | 14 +- lib/components/cards/class_card.dart | 127 +++++- lib/components/cards/class_schedule_card.dart | 11 +- lib/components/cards/class_works_card.dart | 51 +-- .../cards/components/card_description.dart | 7 +- .../cards/components/card_sections.dart | 150 +++--- .../cards/components/display_filename.dart | 34 -- .../cards/components/label_text.dart | 23 - .../cards/components/seperator.dart | 28 +- lib/components/cards/components/tablets.dart | 9 +- .../cards/components/text_big_small.dart | 15 +- lib/components/cards/course_card.dart | 21 +- lib/components/cards/faculty_card.dart | 13 +- lib/components/cards/mini_course_card.dart | 17 +- lib/components/cards/review_card.dart | 10 +- lib/components/headers/headear_dropdown.dart | 7 +- lib/components/images.dart | 49 +- lib/components/input/input_fields.dart | 56 +-- lib/components/pills.dart | 28 +- lib/components/popups/popups.dart | 3 +- lib/components/ratings.dart | 2 +- lib/components/stacks.dart | 53 ++- lib/components/texts.dart | 32 +- lib/components/tile/tiles.dart | 78 +--- lib/components/tile/user_tile.dart | 26 +- lib/components/time_slider.dart | 2 +- lib/components/widgets.dart | 14 +- lib/core/models/user_model.dart | 1 + .../presentation/pages/search_screen.dart | 428 +++++++++++++----- .../presentation/widget/search_navbar.dart | 14 +- lib/graphql/models/UserModel.dart | 1 + lib/graphql/models/UsersClassesRoles.dart | 1 + .../models/UsersFacultiesRolesModel.dart | 1 + lib/main.dart | 152 +++++-- lib/screens/academic/academic_screen.dart | 17 +- .../academic/components/DisplayOptions.dart | 26 +- lib/screens/cart/cart_screen.dart | 7 +- lib/screens/class/class_screen.dart | 5 +- .../class_module_cards_container.dart | 11 +- .../class/components/class_syllabus.dart | 6 +- lib/screens/classwork/classwork_screen.dart | 2 - .../comming_soon/comming_soon_screen.dart | 2 +- .../course/components/course_outline.dart | 6 +- .../course/components/course_perks.dart | 4 +- .../course/components/educator_info.dart | 49 +- .../course/components/module_item.dart | 6 +- lib/screens/course/components/reviews.dart | 2 +- lib/screens/course/course_screen.dart | 8 +- .../create/components/form_add_cover.dart | 28 +- .../create/components/form_classwork.dart | 145 +++--- .../create/components/form_description.dart | 6 +- .../create/components/form_footer.dart | 90 ++-- .../create/components/form_header.dart | 4 +- .../create/components/form_module_tile.dart | 26 +- .../create/components/form_modules.dart | 3 +- .../form_schedule_date_time_generator.dart | 25 +- .../create/components/form_schedule_tile.dart | 36 +- .../create/components/form_schedules.dart | 10 +- .../components/form_select_faculty.dart | 3 +- .../create/components/form_select_user.dart | 14 +- .../create/components/form_select_users.dart | 18 +- .../components/form_set_date_and_time.dart | 26 +- .../create/components/form_set_time.dart | 9 +- lib/screens/create/create_class_instance.dart | 5 +- lib/screens/create/create_class_screen.dart | 4 +- lib/screens/create/create_faculty_screen.dart | 5 +- lib/screens/create/select_faculty_screen.dart | 79 ++-- lib/screens/create/select_user_screen.dart | 30 +- 78 files changed, 1458 insertions(+), 1139 deletions(-) delete mode 100644 lib/components/cards/components/display_filename.dart delete mode 100644 lib/components/cards/components/label_text.dart diff --git a/lib/components/Lists/class_list.dart b/lib/components/Lists/class_list.dart index 8176140..21f3ab2 100644 --- a/lib/components/Lists/class_list.dart +++ b/lib/components/Lists/class_list.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; import 'package:neocloud_mobile/components/cards/class_card.dart'; +import 'package:neocloud_mobile/components/texts.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; import 'package:neocloud_mobile/graphql/services/class_service.dart'; import 'package:neocloud_mobile/components/widgets.dart'; -class ClassList extends StatefulWidget { +class ClassList extends StatelessWidget { const ClassList({ Key? key, this.classList, @@ -13,55 +15,38 @@ class ClassList extends StatefulWidget { this.spinnerScreeMaxHeight, }) : super(key: key); - final List? classList; + final List ? classList; final bool showClassAvatar; final double bodySeparationSize; final double? spinnerScreeMaxHeight; - @override - State createState() => _ClassListState(); -} - -class _ClassListState extends State { - var classService = ClassService(); - List? dataList; - - @override - void initState() { - super.initState(); - loadData(); - } - - void loadData() { - if (!mounted) return; - - if (widget.classList == null) { - classService.getClasses().then((classes) { - setState(() { - dataList = classes; - }); - }); - } else { - dataList = widget.classList; - } - } @override Widget build(BuildContext context) { - return dataList == null - ? spinnerScreen() - : dataList!.isEmpty - ? nothingWasFoundScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) - : Column( - children: List.generate( - dataList!.length, - (index) => ClassCard( - clas: dataList![index], - showClassAvatar: widget.showClassAvatar, - bodySeparationSize: widget.bodySeparationSize, - ), - ), - ); + return Builder( + builder: (context) { + if (classList == null){ + return spinnerScreen(context: context); + } + if (classList!.isEmpty) { + return nothingWasFoundScreen(context: context, screenMaxHeight: spinnerScreeMaxHeight); + } + + if (classList != null) { + return Column( + children: List.generate( + classList!.length, + (index) => ClassCard( + clas: classList![index], + showClassAvatar: showClassAvatar, + bodySeparationSize: bodySeparationSize, + ), + ), + ); + } + return TextMedium(title: 'Fix',); + }, + ); } diff --git a/lib/components/Lists/class_schedule_list.dart b/lib/components/Lists/class_schedule_list.dart index deab50c..d2b2ee9 100644 --- a/lib/components/Lists/class_schedule_list.dart +++ b/lib/components/Lists/class_schedule_list.dart @@ -40,9 +40,9 @@ class _ClassSchedulesListState extends State { @override Widget build(BuildContext context) { return dataList == null - ? spinnerScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) + ? spinnerScreen(context: context, screenMaxHeight: widget.spinnerScreeMaxHeight) : dataList!.isEmpty - ? nothingWasFoundScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) + ? nothingWasFoundScreen(context: context, screenMaxHeight: widget.spinnerScreeMaxHeight) : Column( children: List.generate( dataList!.length, diff --git a/lib/components/Lists/class_works_list.dart b/lib/components/Lists/class_works_list.dart index 117e28f..4a021d9 100644 --- a/lib/components/Lists/class_works_list.dart +++ b/lib/components/Lists/class_works_list.dart @@ -48,9 +48,9 @@ class _ClassworksListState extends State { @override Widget build(BuildContext context) { return dataList == null - ? spinnerScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) + ? spinnerScreen(context: context, screenMaxHeight: widget.spinnerScreeMaxHeight) : dataList!.isEmpty - ? nothingWasFoundScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) + ? nothingWasFoundScreen(context: context, screenMaxHeight: widget.spinnerScreeMaxHeight) : Column( children: List.generate( dataList!.length, diff --git a/lib/components/Lists/faculty_list.dart b/lib/components/Lists/faculty_list.dart index a6ac022..1aa06e6 100644 --- a/lib/components/Lists/faculty_list.dart +++ b/lib/components/Lists/faculty_list.dart @@ -49,9 +49,9 @@ class _FacultyListState extends State { // (index) => FacultyCard(faculty: facultiesList[index])), // ); return dataList == null - ? spinnerScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) + ? spinnerScreen(context: context, screenMaxHeight: widget.spinnerScreeMaxHeight) : dataList!.isEmpty - ? nothingWasFoundScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) + ? nothingWasFoundScreen(context: context, screenMaxHeight: widget.spinnerScreeMaxHeight) : Column( children: List.generate( facultiesList.length, diff --git a/lib/components/Lists/user_list.dart b/lib/components/Lists/user_list.dart index cc2dac9..4f05e4a 100644 --- a/lib/components/Lists/user_list.dart +++ b/lib/components/Lists/user_list.dart @@ -1,66 +1,25 @@ import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/tile/tiles.dart'; -import 'package:neocloud_mobile/graphql/models/UserModel.dart'; -import 'package:neocloud_mobile/graphql/services/user_service.dart'; -import 'package:neocloud_mobile/screens/Profile/profile_sceen.dart'; - +import 'package:neocloud_mobile/components/tile/user_tile.dart'; +import 'package:neocloud_mobile/core/entities/user_entity.dart'; import '../widgets.dart'; -class UserList extends StatefulWidget { - const UserList({ - super.key, - this.usersList, - this.spinnerScreeMaxHeight - }); +class UserList extends StatelessWidget { + const UserList({super.key, this.users, this.spinnerScreeMaxHeight}); - final List? usersList; + final List? users; final double? spinnerScreeMaxHeight; - @override - State createState() => _UserListState(); -} - -class _UserListState extends State { - var userService = UserService(); - List? dataList; - - @override - void initState() { - super.initState(); - loadData(); - } - - void loadData() { - if (!mounted) return; - - if (widget.usersList == null) { - userService.getUsers().then((users) { - setState(() { dataList = users; }); - }); - } - } - @override Widget build(BuildContext context) { - if (widget.usersList != null) { dataList = widget.usersList; } - - return dataList == null - ? spinnerScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) - : dataList!.isEmpty - ? nothingWasFoundScreen(screenMaxHeight: widget.spinnerScreeMaxHeight) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: List.generate( - dataList!.length, - (index) => GestureDetector( - onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => ProfileScreen(user: dataList![index]),)), - child: UserTile( - user: dataList![index] - ), - ), - ), - ); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: List.generate( + users!.length, + (index) => GestureDetector( + // onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => ProfileScreen(user: dataList![index]),)), + child: UserTile(user: users![index]), + ), + ), + ); } - - toList() {} } diff --git a/lib/components/appbar/actions.dart b/lib/components/appbar/actions.dart index fa29c8f..2a245f3 100644 --- a/lib/components/appbar/actions.dart +++ b/lib/components/appbar/actions.dart @@ -8,7 +8,6 @@ class actionUserButton extends StatelessWidget { super.key, this.icon, this.svg, - this.isDark = false, this.routeWidget, }); @@ -16,9 +15,6 @@ class actionUserButton extends StatelessWidget { // to be displayed final IconData? icon; final String? svg; - // action button is dark when this is true and white when - // is false - final bool isDark; // the route to be navigated to when this action button is clicked on final String routeName; // @@ -41,8 +37,8 @@ class actionUserButton extends StatelessWidget { color: Colors.transparent, padding: EdgeInsets.symmetric(horizontal: defaultSize * 2), child: svg != null - ? IconOrSvg(svg: svg!, color: isDark ? kBlack80 : kWhite, size: defaultSize * 2.5,) - : IconOrSvg(icon: icon!, color: isDark ? kBlack80 : kWhite, size: defaultSize * 2.5), + ? IconOrSvg(svg: svg!, size: defaultSize * 2.5,) + : IconOrSvg(icon: icon!, size: defaultSize * 2.5), ) ); } diff --git a/lib/components/appbar/appbar.dart b/lib/components/appbar/appbar.dart index c072e6d..24e7381 100644 --- a/lib/components/appbar/appbar.dart +++ b/lib/components/appbar/appbar.dart @@ -3,13 +3,13 @@ import 'package:neocloud_mobile/components/appbar/actions.dart'; import 'package:neocloud_mobile/components/appbar/leading.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/utils/utils.dart'; class AppsAppBar extends StatelessWidget { AppsAppBar({ super.key, required this.title, - this.bgColor = Colors.white, - this.isDark = true, + this.bgColor, this.showLeading = true, this.elevation = 0, @@ -31,13 +31,7 @@ class AppsAppBar extends StatelessWidget { final String title; // the background color of the appbar - final Color bgColor; - - // this decides what the color of the title and the icons of the appbar - // are going to be. - // if isDark=true then the title, left icon and right icon are going to - // be {black}, else if isDark=false then they are all going to be {white} - final bool isDark; + final Color ? bgColor; // if this is true then the left icon is displayed, else it is not displayed final bool showLeading; @@ -55,14 +49,13 @@ class AppsAppBar extends StatelessWidget { // SvgPicture.asset() and // We expect either field above or the field to be // null, so that the other can render - final String? actionSvg1; - final String? actionSvg2; + String? actionSvg1; + String? actionSvg2; // Replacement // this is a callback function that is called when the action icon or svg // Function(BuildContext context)? pressAction; - // the elevation of the appBar final double elevation; @@ -72,37 +65,35 @@ class AppsAppBar extends StatelessWidget { final String routeName1; final String routeName2; - // routeWidget to be navigated to using push. Allows us to pass data to + // routeWidget to be navigated to using push. Allows us to pass data to // screens whose constructors requires passed in valued final Widget? routeWidget1; final Widget? routeWidget2; @override Widget build(BuildContext context) { + bgColor ?? getColorOpposite(Theme.of(context).canvasColor); + return AppBar( backgroundColor: bgColor, leadingWidth: defaultSize * 6, elevation: elevation, - leading: - showLeading ? LeadingBackButton(isDark: isDark) : const SizedBox(), - title: TextLarge( - title: title, - weight: FontWeight.w600, - color: isDark ? kBlack80 : Colors.white, + leading: showLeading ? LeadingBackButton() : const SizedBox(), + title: Text( + title, + style: Theme.of(context).textTheme.titleSmall, ), actions: showAction1 ? [ actionUserButton( icon: actionIcon1, svg: actionSvg2, - isDark: isDark, routeName: routeName2, routeWidget: routeWidget2, ), actionUserButton( icon: actionIcon1, svg: actionSvg1, - isDark: isDark, routeName: routeName1, routeWidget: routeWidget1, ), @@ -115,8 +106,6 @@ class AppsAppBar extends StatelessWidget { class AppsSliverAppBar extends AppsAppBar { AppsSliverAppBar({ required super.title, - super.bgColor, - super.isDark, super.actionIcon1, super.actionIcon2 = Icons.search, super.actionSvg1, @@ -133,25 +122,26 @@ class AppsSliverAppBar extends AppsAppBar { @override Widget build(BuildContext context) { + // if neither actionSvg or actionIcon was provided, then we want to + // set a default actionSvg value (to be displayed) + super.actionSvg1 = actionSvg1 == null && actionIcon1 == null + ? 'assets/icons/account.svg' + : null; return SliverAppBar( - backgroundColor: bgColor, leadingWidth: 60, elevation: elevation, floating: true, snap: true, - leading: - showLeading ? LeadingBackButton(isDark: isDark) : const SizedBox(), - title: TextLarge( - title: title, - weight: FontWeight.w600, - color: isDark ? kBlack80 : Colors.white, + leading: showLeading ? LeadingBackButton() : const SizedBox(), + title: Text( + title, + style: Theme.of(context).textTheme.titleSmall, ), actions: [ showAction2 ? actionUserButton( icon: actionIcon2, svg: actionSvg2, - isDark: isDark, routeName: routeName2, routeWidget: routeWidget2, ) @@ -160,7 +150,6 @@ class AppsSliverAppBar extends AppsAppBar { ? actionUserButton( icon: actionIcon1, svg: actionSvg1, - isDark: isDark, routeName: routeName1, routeWidget: routeWidget1, ) diff --git a/lib/components/appbar/leading.dart b/lib/components/appbar/leading.dart index d5bb25b..20fa875 100644 --- a/lib/components/appbar/leading.dart +++ b/lib/components/appbar/leading.dart @@ -1,15 +1,11 @@ import 'package:flutter/material.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/utils/utils.dart'; // This is the back button for the AppBar of our position (<) class LeadingBackButton extends StatelessWidget { - // final Color backgroundColor; - final bool isDark; - const LeadingBackButton({ super.key, - this.isDark = false, - // this.backgroundColor = Colors.white, }); @override @@ -23,11 +19,10 @@ class LeadingBackButton extends StatelessWidget { Navigator.pop(context); }, child: Container( - color: kWhite, + color: getColorOpposite(Theme.of(context).canvasColor), padding: EdgeInsets.fromLTRB(defaultSize * 2, defaultSize * 2, defaultSize * 1.5, defaultSize * 2), child: Icon( Icons.arrow_back_ios, - color: isDark ? kBlack80 : kWhite, size: defaultSize * 2.5, ), ), diff --git a/lib/components/bottom_navbar/apps_bottom_navbar.dart b/lib/components/bottom_navbar/apps_bottom_navbar.dart index f3157a9..bc10e38 100644 --- a/lib/components/bottom_navbar/apps_bottom_navbar.dart +++ b/lib/components/bottom_navbar/apps_bottom_navbar.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/utils/utils.dart'; import 'package:neocloud_mobile/providers/NavItem.dart'; import 'package:provider/provider.dart'; @@ -15,7 +16,7 @@ class AppsBottomNavBar extends StatelessWidget { builder: (context, navItems, child) => Container( decoration: BoxDecoration( border: Border( - top: BorderSide(color: kBlack.withOpacity(.5), width: .2), + top: BorderSide(color: Theme.of(context).canvasColor.withOpacity(.5), width: .2), ), ), child: Row( @@ -33,8 +34,8 @@ class AppsBottomNavBar extends StatelessWidget { navItems.changeNavIndex(index); } }, - highlightColor: kWhite, - splashColor: appsSplashColor, + highlightColor: getColorOpposite(Theme.of(context).canvasColor), + splashColor: Theme.of(context).canvasColor, radius: appsSplashRadius, child: Container( padding: EdgeInsets.only( @@ -47,7 +48,7 @@ class AppsBottomNavBar extends StatelessWidget { : item.svgInactive, color: navItems.getSelectedIndex() == index ? kBlue - : kBlack50, + : Theme.of(context).canvasColor.withOpacity(.5), ), ), ), diff --git a/lib/components/buttons.dart b/lib/components/buttons.dart index f4f7487..83adfc5 100644 --- a/lib/components/buttons.dart +++ b/lib/components/buttons.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/utils/utils.dart'; // Welcome Button class WelcomeButton extends StatelessWidget { @@ -21,15 +22,17 @@ class WelcomeButton extends StatelessWidget { Widget build(BuildContext context) { return TextButton( onPressed: press, - style: buildButtonStyle(), + style: buildButtonStyle(context), child: Container( // width: defaultSize * 22, padding: EdgeInsets.symmetric(vertical: defaultSize * 1), child: Stack( children: [ Center( - child: TextSmall( - title: title, color: Colors.white, weight: FontWeight.w500), + child: Text(title, + style: TextStyle( + color: getColorOpposite(Theme.of(context).canvasColor), + fontWeight: FontWeight.w500)), ), // Arrow @@ -39,7 +42,7 @@ class WelcomeButton extends StatelessWidget { top: defaultSize * .2, child: Icon( Icons.arrow_back_ios, - color: Colors.white, + color: getColorOpposite(Theme.of(context).canvasColor), size: defaultSize * 1.6, ), ) @@ -48,7 +51,7 @@ class WelcomeButton extends StatelessWidget { top: defaultSize * .2, child: Icon( Icons.arrow_forward_ios, - color: Colors.white, + color: getColorOpposite(Theme.of(context).canvasColor), size: defaultSize * 1.6, ), ), @@ -58,9 +61,10 @@ class WelcomeButton extends StatelessWidget { ); } - ButtonStyle buildButtonStyle() { + ButtonStyle buildButtonStyle(BuildContext context) { return ButtonStyle( - backgroundColor: MaterialStatePropertyAll(kBlueLight), + backgroundColor: + MaterialStatePropertyAll(Theme.of(context).primaryColor), shape: const MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: BorderRadius.all( @@ -74,67 +78,90 @@ class WelcomeButton extends StatelessWidget { // Apps Main Button class AppsButton extends StatelessWidget { - const AppsButton({ + AppsButton({ super.key, required this.title, required this.press, this.icon, - this.color = Colors.white, - this.iconColor = Colors.white, + this.color, + this.iconColor, this.bgColor = Colors.blueAccent, this.bgColorLoading = Colors.blue, this.border = 0, this.borderRadius = 10, + this.fontSize = 16, this.textIconSeperationSize = 5, this.padTopBottom = 6, - this.padLeftRight = 6, + this.padLeftRight = 6, this.weight = FontWeight.w400, this.isLoading = false, + this.minButtonHeight = 40, + this.maxButtonHeight = 60, }); final String title; - final Color color; + late Color? color; final Color bgColor; final Color bgColorLoading; - final Color iconColor; + late Color? iconColor; final IconData? icon; final double border; final double borderRadius; + final double fontSize; final double textIconSeperationSize; final Function(BuildContext context) press; final double padTopBottom; final double padLeftRight; final FontWeight weight; final bool isLoading; + final double minButtonHeight; + final double maxButtonHeight; @override Widget build(BuildContext context) { + color ??= Colors.white; + iconColor ??= getColorOpposite(Theme.of(context).canvasColor); + return TextButton( onPressed: !isLoading ? () => press(context) : null, - style: buildButtonStyle(), + style: buildButtonStyle(context), child: Container( - constraints: BoxConstraints(minHeight: defaultSize * 4, maxHeight: defaultSize * 4), + constraints: BoxConstraints( + minHeight: minButtonHeight, maxHeight: maxButtonHeight), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ icon != null ? Icon(icon, color: iconColor) : const SizedBox(), - icon != null ? SizedBox(width: textIconSeperationSize) : const SizedBox(), + icon != null + ? SizedBox(width: textIconSeperationSize) + : const SizedBox(), isLoading - ? SizedBox(height: 20, width: 20, child: CircularProgressIndicator(color: kWhite, strokeWidth: 3)) - : TextMedium(title: title, color: color, weight: weight), + ? const SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + color: Colors.white, + strokeWidth: 3, + ), + ) + : Text(title, + style: TextStyle(fontFamily: 'Poppins', color: color, fontWeight: weight, fontSize: fontSize)), ], ), ), ); } - ButtonStyle buildButtonStyle() { + ButtonStyle buildButtonStyle(BuildContext context) { return ButtonStyle( - backgroundColor: MaterialStatePropertyAll(!isLoading ? bgColor : bgColorLoading), + backgroundColor: MaterialStatePropertyAll( + !isLoading ? bgColor : bgColorLoading), shape: MaterialStatePropertyAll( RoundedRectangleBorder( side: border > 0 - ? BorderSide(width: border, color: kBlack50) + ? BorderSide( + width: border, + color: Theme.of(context).canvasColor.withOpacity(.5)) : const BorderSide(color: Colors.transparent), borderRadius: BorderRadius.all( Radius.circular(borderRadius), @@ -150,7 +177,7 @@ class AppsIconButton extends AppsButton { super.title = "", required super.press, super.icon, - super.iconColor = Colors.black87, + super.iconColor, super.bgColor, super.borderRadius, super.padTopBottom = 18, @@ -159,6 +186,8 @@ class AppsIconButton extends AppsButton { @override Widget build(BuildContext context) { + iconColor ??= Theme.of(context).canvasColor.withOpacity(.8); + return InkWell( onTap: () => press(context), borderRadius: BorderRadius.circular(borderRadius), @@ -171,41 +200,17 @@ class AppsIconButton extends AppsButton { borderRadius: BorderRadius.circular(borderRadius), color: bgColor, ), - child: Center(child: Icon(icon, color: iconColor,)), + child: Center( + child: Icon( + icon, + color: iconColor, + )), ), ); } } -// Option Button -class OptionButton extends StatelessWidget { - const OptionButton({ - Key? key, - required this.title, - required this.press, - this.bgColor = Colors.transparent, - }) : super(key: key); - - final String title; - final Color bgColor; - final Function() press; - - @override - Widget build(BuildContext context) { - return AppsButton( - title: title, - borderRadius: buttonBorderRadius, - bgColor: bgColor, - color: bgColor == kBlueLight? kWhite : kBlack70, - press: (context) => press(), - padTopBottom: .5, - weight: bgColor == kBlueLight? FontWeight.w600 : FontWeight.w400, - ); - } -} - - // Dropdown Button class AppsDropdownButton extends StatefulWidget { const AppsDropdownButton({ @@ -247,8 +252,12 @@ class _AppsDropdownButtonState extends State { underline: Container(height: 0), items: widget.list.map((String month) { return DropdownMenuItem( - child: - TextSmall(title: month, color: kBlack50, weight: FontWeight.w500), + child: Text( + month, + style: TextStyle( + color: Theme.of(context).canvasColor.withOpacity(.5), + fontWeight: FontWeight.w500), + ), value: month, ); }).toList(), @@ -256,59 +265,65 @@ class _AppsDropdownButtonState extends State { } } - // Icon Text Button class IconTextButton extends StatelessWidget { - const IconTextButton(this.text, { + IconTextButton( + this.text, { super.key, this.icon = Icons.add, - this.iconColor = Colors.black54, - this.textColor = Colors.black38, + this.iconColor, + this.textColor, this.backgroundColor = Colors.blue, this.borderWidth = 1.5, - this.borderColor = Colors.black, + this.borderColor, this.fullWidth = false, required this.press, }); - + final String text; final IconData? icon; - final Color iconColor; - final Color textColor; + late Color? iconColor; + late Color? textColor; final Color backgroundColor; final double borderWidth; - final Color borderColor; + late Color? borderColor; final bool fullWidth; final Function() press; @override Widget build(BuildContext context) { + borderColor ??= Theme.of(context).canvasColor; + iconColor ??= Theme.of(context).canvasColor.withOpacity(.5); + textColor ??= Theme.of(context).canvasColor.withOpacity(.4); return Container( height: defaultSize * 4.5, decoration: BoxDecoration( - color: backgroundColor, - border: Border.all(width: borderWidth, color: borderColor), - borderRadius: BorderRadius.circular(defaultSize) - ), + color: backgroundColor, + border: Border.all(width: borderWidth, color: borderColor!), + borderRadius: BorderRadius.circular(defaultSize)), child: TextButton( onPressed: press, style: ButtonStyle( - padding: MaterialStatePropertyAll( - EdgeInsets.symmetric(horizontal: defaultSize * .7, vertical: 0) - ) - - ), + padding: MaterialStatePropertyAll(EdgeInsets.symmetric( + horizontal: defaultSize * .7, vertical: 0))), child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: fullWidth ? MainAxisSize.max : MainAxisSize.min, children: [ - Icon(icon, color: Colors.black38, size: 30), - const SizedBox(width: 5), - TextLarge(title: text, weight: FontWeight.w500, color: textColor), + Icon(icon, + color: Theme.of(context).canvasColor.withOpacity(.4), size: 30), const SizedBox(width: 5), + Text( + text, + style: TextStyle( + color: textColor, + fontWeight: FontWeight.w500, + ), + ), + // const SizedBox(width: 5), ], ), - ), - ); + ), + ); } -} \ No newline at end of file +} diff --git a/lib/components/cards/cart_card.dart b/lib/components/cards/cart_card.dart index a65d1b0..0abdc17 100644 --- a/lib/components/cards/cart_card.dart +++ b/lib/components/cards/cart_card.dart @@ -32,34 +32,34 @@ class CartCard extends StatelessWidget { // Item Details SizedBox(width: defaultSize * 2), - buildCartInfo(), + buildCartInfo(context), ], ), ), ); } - Widget buildCartInfo() { + Widget buildCartInfo(BuildContext context) { return Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title TextExtraLarge( - title: course.title, weight: FontWeight.w600, color: kBlack80), + title: course.title, weight: FontWeight.w600, color: Theme.of(context).canvasColor.withOpacity(.8)), // Educator SizedBox(height: defaultSize * .5), TextSmall( title: course.user.fullName, - color: kBlack50, + color: Theme.of(context).canvasColor.withOpacity(.5), ), // {percentage} discount SizedBox(height: defaultSize * .5), TextSmall( title: "${course.discount}% discount", - color: kBlack70, + color: Theme.of(context).canvasColor.withOpacity(.7), weight: FontWeight.w500, ), @@ -72,7 +72,7 @@ class CartCard extends StatelessWidget { text1FontSize: defaultSize * 1.4, text1Decoration: TextDecoration.lineThrough, text2FontWeight: FontWeight.w600, - text2Color: kBlack80, + text2Color: Theme.of(context).canvasColor.withOpacity(.8), ), // Move to / Remove @@ -105,7 +105,7 @@ class CartCard extends StatelessWidget { title: "Purchase", press: (_) => print("Purchase Button clicked ..."), padTopBottom: defaultSize * .3, - bgColor: kBlack80, + bgColor: Theme.of(context).canvasColor.withOpacity(.8), borderRadius: defaultSize * .5, ) ], diff --git a/lib/components/cards/class_card.dart b/lib/components/cards/class_card.dart index 15a8255..378ab0e 100644 --- a/lib/components/cards/class_card.dart +++ b/lib/components/cards/class_card.dart @@ -3,10 +3,10 @@ import 'package:neocloud_mobile/components/images.dart'; import 'package:neocloud_mobile/components/cards/components/tablets.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/graphql/models/ClassModel.dart'; -import 'package:neocloud_mobile/models/Class.dart'; +import 'package:neocloud_mobile/core/entities/class_entity.dart'; import 'package:neocloud_mobile/screens/class/class_screen.dart'; import 'package:neocloud_mobile/utils/utils.dart'; +import 'package:skeletons/skeletons.dart'; class ClassCard extends StatelessWidget { const ClassCard({ @@ -19,7 +19,7 @@ class ClassCard extends StatelessWidget { this.showBottomBorder = true, }); - final ClassModel clas; + final ClassEntity clas; final bool allowSeeMore; final double bodySeparationSize; // we use this because we use this card in the class screen and @@ -72,7 +72,7 @@ class ClassCard extends StatelessWidget { TextCustom( title: clas.name!, fontSize: defaultSize * 2.2, - color: kBlack80, + color: Theme.of(context).canvasColor.withOpacity(.8), weight: FontWeight.w700, ), @@ -84,9 +84,9 @@ class ClassCard extends StatelessWidget { // Name SizedBox(height: defaultSize), Expanded( - child: buildAvatarAndName( + child: CircularAvartarAndName( avatar: clas.educators != null && clas.educators!.length > 0 - ? clas.educators![0].avatar ?? '' : '', + ? clas.educators![0].avatar : '', name: clas.educators != null && clas.educators!.length > 0 ? clas.educators![0].name : 'daniel', fontSize: defaultSize * 1.6, @@ -112,13 +112,13 @@ class ClassCard extends StatelessWidget { allowSeeMore ? TextSeeMore( text: clas.about ?? '', - color: kBlack70, + color: Theme.of(context).canvasColor.withOpacity(.7), fontSize: defaultSize * 1.6, maxLines: 2, ) : TextCustomMaxLine( title: clas.about ?? '', - color: kBlack70, + color: Theme.of(context).canvasColor.withOpacity(.7), fontSize: defaultSize * 1.6, maxLines: 3, ), @@ -147,3 +147,114 @@ class ClassCard extends StatelessWidget { ); } } + + +class ClassCardSkeleton extends StatelessWidget { + const ClassCardSkeleton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return SkeletonItem( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Cover + const SkeletonLine( + style: SkeletonLineStyle(height: 220), + ), + + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Title + const SkeletonLine( + style: SkeletonLineStyle( + height: 18, + width: 200, + borderRadius: BorderRadius.all(Radius.circular(20))), + ), + + // Row (Avatar, Name) + const SizedBox(height: 17), + Row( + children: const [ + // avatar + SkeletonAvatar( + style: SkeletonAvatarStyle( + width: 30, + height: 30, + borderRadius: BorderRadius.all(Radius.circular(30)), + ), + ), + + // name + SizedBox(width: 18), + SkeletonLine( + style: SkeletonLineStyle( + height: 14, + width: 120, + borderRadius: BorderRadius.all(Radius.circular(20))), + ), + ], + ), + + // Description + const SizedBox(height: 17), + const SkeletonLine( + style: SkeletonLineStyle( + height: 12, + borderRadius: BorderRadius.all(Radius.circular(20))), + ), + const SizedBox(height: 10), + const SkeletonLine( + style: SkeletonLineStyle( + height: 12, + borderRadius: BorderRadius.all(Radius.circular(20))), + ), + const SizedBox(height: 10), + + const SkeletonLine( + style: SkeletonLineStyle( + height: 12, + width: 140, + borderRadius: BorderRadius.all(Radius.circular(20))), + ), + + // Tablets (Faculty, Hod) + const SizedBox(height: 20), + Row( + children: const [ + // Faculty + SkeletonLine( + style: SkeletonLineStyle( + height: 30, + width: 100, + borderRadius: BorderRadius.all(Radius.circular(5))), + ), + + // Hod + SizedBox(width: 10), + SkeletonLine( + style: SkeletonLineStyle( + height: 30, + width: 120, + borderRadius: BorderRadius.all(Radius.circular(5))), + ), + ], + ) + ], + ), + ), + + const SizedBox(height: 20), + ], + ), + ); + } +} + diff --git a/lib/components/cards/class_schedule_card.dart b/lib/components/cards/class_schedule_card.dart index 504fb67..1e2a49d 100644 --- a/lib/components/cards/class_schedule_card.dart +++ b/lib/components/cards/class_schedule_card.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:neocloud_mobile/components/cards/components/tablets.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/constants/constants.dart'; import 'package:neocloud_mobile/graphql/models/ClassScheduleModel.dart'; class ClassScheduleCard extends StatelessWidget { @@ -18,14 +19,14 @@ class ClassScheduleCard extends StatelessWidget { return Container( padding: screenPadding, decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: kBlack50, width: .2))), + border: Border(bottom: BorderSide(color: Theme.of(context).canvasColor.withOpacity(.5), width: .2))), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Educator {Avatar - Name} SizedBox(height: defaultSize * 2), // TODO: use actual educators when a form that connects everything has been used to connect things up - buildAvatarAndName( + CircularAvartarAndName( // avatar: classwork.clas!.educators![0].avatar, // name: classwork.clas!.educators![0].name, avatar: defaultProfileAvatar, @@ -42,7 +43,7 @@ class ClassScheduleCard extends StatelessWidget { SizedBox(height: defaultSize * 1.5), TextSmall( title: classSchedule.description ?? '', - color: kBlack70, + color: Theme.of(context).canvasColor.withOpacity(.7), // weight: FontWeight.w400, ), @@ -53,13 +54,13 @@ class ClassScheduleCard extends StatelessWidget { IconText( title: 'August 12', icon: Icons.calendar_month, - iconColor: kBlack70, + iconColor: Theme.of(context).canvasColor.withOpacity(.7), fontSize: defaultSize * 1.4), SizedBox(width: defaultSize * 2,), IconText( title: '9:30 am - 12:30pm', icon: Icons.timer, - iconColor: kBlack70, + iconColor: Theme.of(context).canvasColor.withOpacity(.7), fontSize: defaultSize * 1.4), ], ), diff --git a/lib/components/cards/class_works_card.dart b/lib/components/cards/class_works_card.dart index e0464f3..51a6455 100644 --- a/lib/components/cards/class_works_card.dart +++ b/lib/components/cards/class_works_card.dart @@ -4,6 +4,7 @@ import 'package:neocloud_mobile/components/images.dart'; import 'package:neocloud_mobile/components/cards/components/tablets.dart'; import 'package:neocloud_mobile/components/texts.dart'; import 'package:neocloud_mobile/constraints.dart'; +import 'package:neocloud_mobile/core/constants/constants.dart'; import 'package:neocloud_mobile/graphql/models/ClassworkModel.dart'; import 'package:neocloud_mobile/screens/classwork/classwork_screen.dart'; @@ -33,7 +34,7 @@ class ClassWorkCard extends StatelessWidget { child: Container( // padding: screenPadding, decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: kBlack50, width: .2))), + border: Border(bottom: BorderSide(color: Theme.of(context).canvasColor.withOpacity(.5), width: .2))), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -43,14 +44,14 @@ class ClassWorkCard extends StatelessWidget { // Feedback SizedBox(height: defaultSize * 2), - showFeedback ? buildClassworkFeedbacks() : SizedBox(), + showFeedback ? buildClassworkFeedbacks(context) : SizedBox(), ], ), ), ); } - Column buildClassworkFeedbacks() { + Column buildClassworkFeedbacks(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -70,8 +71,8 @@ class ClassWorkCard extends StatelessWidget { TextBigSmall( bigText: '3', smallText: 'Submission', - bigTextColor: kBlack80, - smallTextColor: kBlack60, + bigTextColor: Theme.of(context).canvasColor.withOpacity(.8), + smallTextColor: Theme.of(context).canvasColor.withOpacity(.6), smallTextSize: defaultSize * 1.6, ), SizedBox( @@ -80,8 +81,8 @@ class ClassWorkCard extends StatelessWidget { TextBigSmall( bigText: '3', smallText: 'Feedbacks', - bigTextColor: kBlack80, - smallTextColor: kBlack60, + bigTextColor: Theme.of(context).canvasColor.withOpacity(.8), + smallTextColor: Theme.of(context).canvasColor.withOpacity(.6), smallTextSize: defaultSize * 1.6, ), SizedBox( @@ -90,8 +91,8 @@ class ClassWorkCard extends StatelessWidget { TextBigSmall( bigText: '1', smallText: 'Student Left', - bigTextColor: kBlack80, - smallTextColor: kBlack60, + bigTextColor: Theme.of(context).canvasColor.withOpacity(.8), + smallTextColor: Theme.of(context).canvasColor.withOpacity(.6), smallTextSize: defaultSize * 1.6, ) ], @@ -103,7 +104,7 @@ class ClassWorkCard extends StatelessWidget { padding: EdgeInsets.symmetric( vertical: defaultSize * 2, horizontal: defaultSize * 1.5), decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: kBlack50, width: .2))), + border: Border(bottom: BorderSide(color: Theme.of(context).canvasColor.withOpacity(.5), width: .2))), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -112,7 +113,7 @@ class ClassWorkCard extends StatelessWidget { padding: const EdgeInsets.only(top: 0), child: RoundBoxAvatar( size: defaultSize * 5, - image: classwork.clas!.educators![0].avatar ?? ''), + image: classwork.clas!.educators![0].avatar), ), // Notifications Info @@ -125,14 +126,14 @@ class ClassWorkCard extends StatelessWidget { children: [ // Users Full Name TextLarge( - title: classwork.clas!.educators![0].name ?? '', + title: classwork.clas!.educators![0].name, weight: FontWeight.w600, - color: kBlack90, + color: Theme.of(context).canvasColor.withOpacity(.9), ), // Notification Body SizedBox(height: defaultSize), - TextMedium(title: classwork.body, color: kBlack70), + TextMedium(title: classwork.body, color: Theme.of(context).canvasColor.withOpacity(.7)), ], ), ) @@ -154,20 +155,6 @@ class TheClassworkCard extends StatelessWidget { @override Widget build(BuildContext context) { - var faculty = classwork.faculty!; - var classSchedule = classwork.classSchedule!; - var module = classwork.classSchedule!.classModule!; - - print(faculty); - print(classSchedule); - print(module); - - // List tabletData = [ - // {'value': faculty.name, 'color': kOrange}, - // {'value': 'Module ${module.order} - C${classSchedule.order}' , 'color': kRed}, - // {'value': 'Due ${classwork.deadline}' , 'color': kBlue}, - // ]; - return Padding( padding: screenPadding, child: Column( @@ -175,7 +162,7 @@ class TheClassworkCard extends StatelessWidget { children: [ SizedBox(height: defaultSize), // TODO: use actual educators when a form that connects everything has been used to connect things up - buildAvatarAndName( + CircularAvartarAndName( // avatar: classwork.clas!.educators![0].avatar, // name: classwork.clas!.educators![0].name, avatar: defaultProfileAvatar, @@ -189,7 +176,7 @@ class TheClassworkCard extends StatelessWidget { // Description SizedBox(height: defaultSize), - TextMedium(title: classwork.body ?? '', color: kBlack70), + TextMedium(title: classwork.body, color: Theme.of(context).canvasColor.withOpacity(.7)), // Bottom Tablets SizedBox(height: defaultSize * 2.5), @@ -198,7 +185,7 @@ class TheClassworkCard extends StatelessWidget { IconText( title: 'Due August 12 - 3pm', icon: Icons.watch, - iconColor: kBlack70, + iconColor: Theme.of(context).canvasColor.withOpacity(.7), fontSize: defaultSize * 1.4, ), SizedBox( @@ -207,7 +194,7 @@ class TheClassworkCard extends StatelessWidget { IconText( title: '${classwork.clas!.name!}', icon: Icons.school, - iconColor: kBlack70, + iconColor: Theme.of(context).canvasColor.withOpacity(.7), fontSize: defaultSize * 1.4, ), ], diff --git a/lib/components/cards/components/card_description.dart b/lib/components/cards/components/card_description.dart index 9c6f234..67ce57a 100644 --- a/lib/components/cards/components/card_description.dart +++ b/lib/components/cards/components/card_description.dart @@ -19,14 +19,11 @@ class CardDescription extends StatelessWidget { children: [ // Label SizedBox(height: defaultSize * 1.5), - TextMedium(title: label, color: kBlack70), + Text(label, style: Theme.of(context).textTheme.bodyMedium,), // Content SizedBox(height: defaultSize * .5), - TextMedium( - title: content, - color: kBlack70, - ), + Text(content, style: Theme.of(context).textTheme.bodyMedium,), ], ); } diff --git a/lib/components/cards/components/card_sections.dart b/lib/components/cards/components/card_sections.dart index 4b33fed..afe3ea6 100644 --- a/lib/components/cards/components/card_sections.dart +++ b/lib/components/cards/components/card_sections.dart @@ -1,80 +1,82 @@ -import 'package:flutter/material.dart'; -import 'package:neocloud_mobile/components/cards/components/seperator.dart'; -import 'package:neocloud_mobile/components/texts.dart'; -import 'package:neocloud_mobile/constraints.dart'; -import 'package:neocloud_mobile/utils/utils.dart'; +// import 'package:flutter/material.dart'; +// import 'package:neocloud_mobile/components/cards/components/seperator.dart'; +// import 'package:neocloud_mobile/components/texts.dart'; +// import 'package:neocloud_mobile/constraints.dart'; +// import 'package:neocloud_mobile/utils/utils.dart'; -// This displays a