From 337a811717875ae2a959cd43ff484b3eedf41508 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Fri, 22 Dec 2023 22:58:51 +0530 Subject: [PATCH 01/13] ptch: updates padding of Profile text button --- .../profile/components/profile_button.dart | 8 ++- lib/presentation/profile/profile_view.dart | 56 +++++++++++++------ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/lib/presentation/profile/components/profile_button.dart b/lib/presentation/profile/components/profile_button.dart index 6f40ab43..c2c3b21d 100644 --- a/lib/presentation/profile/components/profile_button.dart +++ b/lib/presentation/profile/components/profile_button.dart @@ -5,21 +5,25 @@ class ProfileTextButton extends StatelessWidget { const ProfileTextButton({ required this.title, required this.onPressed, + required this.horizontalPadding, + required this.width, super.key, }); final String title; final VoidCallback onPressed; + final int horizontalPadding; + final int width; @override Widget build(BuildContext context) { return TextButton( onPressed: onPressed, child: Container( - width: 115.toAutoScaledWidth, + width: width.toAutoScaledWidth, height: 32.toAutoScaledHeight, padding: EdgeInsets.symmetric( - horizontal: 26.toAutoScaledWidth, + horizontal: horizontalPadding.toAutoScaledWidth, vertical: 6.toAutoScaledHeight, ), decoration: ShapeDecoration( diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 60349e78..678c7ec4 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -57,27 +57,45 @@ class ProfileScreen extends StatelessWidget { child: ProfileCard(data: state.user), ), Container( - padding: EdgeInsets.only( - top: 24.toAutoScaledHeight, - bottom: 24.toAutoScaledHeight), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + padding: EdgeInsets.symmetric( + vertical: 24.toAutoScaledHeight,), + child: Column( children: [ - ProfileTextButton( - title: 'Edit Profile', - onPressed: () { - const snackBar = SnackBar( - content: Text('Coming soon!'), - duration: Duration(milliseconds: 500), - ); - ScaffoldMessenger.of(context) - .showSnackBar(snackBar); - }, + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ProfileTextButton( + title: 'Edit Profile', + onPressed: () { + const snackBar = SnackBar( + content: Text('Coming soon!'), + duration: Duration(milliseconds: 500), + ); + ScaffoldMessenger.of(context) + .showSnackBar(snackBar); + }, + horizontalPadding: 26, + width: 115, + ), + ProfileTextButton( + title: 'Reset Password', + onPressed: () { + const snackBar = SnackBar( + content: Text('Coming soon!'), + duration: Duration(milliseconds: 500), + ); + ScaffoldMessenger.of(context) + .showSnackBar(snackBar); + }, + horizontalPadding: 10, + width: 115, + ), + ], ), - 10.toHorizontalSizedBox, + 10.toVerticalSizedBox, ProfileTextButton( - title: 'Reset Password', + title: 'Request for Hostel Change', onPressed: () { const snackBar = SnackBar( content: Text('Coming soon!'), @@ -86,6 +104,8 @@ class ProfileScreen extends StatelessWidget { ScaffoldMessenger.of(context) .showSnackBar(snackBar); }, + horizontalPadding: 50, + width: 248, ), ], ), From eb8ac36a6af3eba453c1b024e7fb872c0f3bf37c Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Fri, 22 Dec 2023 23:52:16 +0530 Subject: [PATCH 02/13] feat: adds Hostel Change screen route --- lib/data/core/router/registry/paths.dart | 1 + lib/data/core/router/registry/routes.dart | 4 +++ .../components/hostel_change_banner.dart | 31 +++++++++++++++++++ .../hostel_change/hostel_change_screen.dart | 20 ++++++++++++ lib/presentation/profile/profile_view.dart | 8 ++--- pubspec.lock | 26 ++++++++-------- 6 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 lib/presentation/hostel_change/components/hostel_change_banner.dart create mode 100644 lib/presentation/hostel_change/hostel_change_screen.dart diff --git a/lib/data/core/router/registry/paths.dart b/lib/data/core/router/registry/paths.dart index 07573dd2..743e4bd9 100644 --- a/lib/data/core/router/registry/paths.dart +++ b/lib/data/core/router/registry/paths.dart @@ -16,4 +16,5 @@ class AppPathsRegistry { static const String weekMenu = 'weekMenu'; static const String leavesAndRebate = 'leavesAndRebate'; static const String feedback = 'feedback'; + static const String hostelChange = 'hostelChange'; } diff --git a/lib/data/core/router/registry/routes.dart b/lib/data/core/router/registry/routes.dart index c9d949fc..f7f57aa9 100644 --- a/lib/data/core/router/registry/routes.dart +++ b/lib/data/core/router/registry/routes.dart @@ -55,6 +55,10 @@ class AppRoutesRegistry { path: AppPathsRegistry.feedback, page: FeedbackRoute.page, ), + CustomRoute( + path: AppPathsRegistry.hostelChange, + page: HostelChangeRoute.page, + ), ], ), ]; diff --git a/lib/presentation/hostel_change/components/hostel_change_banner.dart b/lib/presentation/hostel_change/components/hostel_change_banner.dart new file mode 100644 index 00000000..c1a309ee --- /dev/null +++ b/lib/presentation/hostel_change/components/hostel_change_banner.dart @@ -0,0 +1,31 @@ +import 'package:appetizer/app_theme.dart'; +import 'package:appetizer/data/core/theme/dimensional/dimensional.dart'; +import 'package:appetizer/presentation/components/app_banner.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +class HostelChangeBanner extends StatelessWidget { + const HostelChangeBanner({super.key}); + + @override + Widget build(BuildContext context) { + return AppBanner( + height: 140.toAutoScaledHeight, + child: Row( + children: [ + IconButton( + onPressed: context.router.pop, + icon: const Icon( + Icons.arrow_back, + color: Colors.white, + ), + ), + Text( + "Hostel Change", + style: AppTheme.headline1, + ), + ], + ), + ); + } +} diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart new file mode 100644 index 00000000..1ce97bb7 --- /dev/null +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -0,0 +1,20 @@ +import 'package:appetizer/presentation/hostel_change/components/hostel_change_banner.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class HostelChangeScreen extends StatelessWidget{ + const HostelChangeScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + HostelChangeBanner(), + Text("Hostel Change") + ], + ) + ); + } +} \ No newline at end of file diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 678c7ec4..90eb723e 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -97,12 +97,8 @@ class ProfileScreen extends StatelessWidget { ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { - const snackBar = SnackBar( - content: Text('Coming soon!'), - duration: Duration(milliseconds: 500), - ); - ScaffoldMessenger.of(context) - .showSnackBar(snackBar); + context.router.push( + const HostelChangeRoute()); }, horizontalPadding: 50, width: 248, diff --git a/pubspec.lock b/pubspec.lock index fd8ac614..12a85fb3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -681,10 +681,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -1006,18 +1006,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -1046,10 +1046,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" timing: dependency: transitive description: @@ -1198,10 +1198,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1243,5 +1243,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.13.0" From 3d995bc9745470322f524a33385b063d2d9f1ca8 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Sun, 24 Dec 2023 00:45:52 +0530 Subject: [PATCH 03/13] feat: adds Hostel Change Request Functionality --- lib/data/constants/api_endpoints.dart | 1 + lib/data/services/remote/api_service.dart | 5 + .../repositories/user/user_repository.dart | 12 + .../bloc/hostel_change_bloc.dart | 44 +++ .../bloc/hostel_change_event.dart | 17 ++ .../bloc/hostel_change_state.dart | 21 ++ .../hostel_change/hostel_change_screen.dart | 253 +++++++++++++++++- 7 files changed, 346 insertions(+), 7 deletions(-) create mode 100644 lib/presentation/hostel_change/bloc/hostel_change_bloc.dart create mode 100644 lib/presentation/hostel_change/bloc/hostel_change_event.dart create mode 100644 lib/presentation/hostel_change/bloc/hostel_change_state.dart diff --git a/lib/data/constants/api_endpoints.dart b/lib/data/constants/api_endpoints.dart index eafa2696..72b98747 100644 --- a/lib/data/constants/api_endpoints.dart +++ b/lib/data/constants/api_endpoints.dart @@ -40,4 +40,5 @@ class ApiEndpoints { static const String oAuthRedirect = '/api/user/oauth/omniport/redirect/'; static const String oAuthComplete = '/api/user/oauth/complete/'; static const String notifications = '/api/user/message/list/'; + static const String hostelChange = '/api/user/hostel-change/'; } diff --git a/lib/data/services/remote/api_service.dart b/lib/data/services/remote/api_service.dart index 68cb6e50..55792dde 100644 --- a/lib/data/services/remote/api_service.dart +++ b/lib/data/services/remote/api_service.dart @@ -181,4 +181,9 @@ abstract class ApiService { @GET(ApiEndpoints.notifications) Future getNotifications(); + + @POST(ApiEndpoints.hostelChange) + Future postChangeHostel( + @Body() Map map, + ); } diff --git a/lib/domain/repositories/user/user_repository.dart b/lib/domain/repositories/user/user_repository.dart index a56e2bcd..a5fb1a12 100644 --- a/lib/domain/repositories/user/user_repository.dart +++ b/lib/domain/repositories/user/user_repository.dart @@ -154,4 +154,16 @@ class UserRepository { throw Failure(AppConstants.GENERIC_FAILURE); } } + + Future postChangeHostel(String hostelCode) async { + Map map = { + 'new_hostel_id': hostelCode, + }; + try { + return await _apiService.postChangeHostel(map); + } catch (e) { + debugPrint(e.toString()); + throw Failure(AppConstants.GENERIC_FAILURE); + } + } } diff --git a/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart new file mode 100644 index 00000000..a6bf8a47 --- /dev/null +++ b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart @@ -0,0 +1,44 @@ +import 'dart:async'; + +import 'package:appetizer/data/constants/constants.dart'; +import 'package:appetizer/domain/models/user/user.dart'; +import 'package:appetizer/domain/repositories/user/user_repository.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'hostel_change_event.dart'; +part 'hostel_change_state.dart'; + +class HostelChangeBloc extends Bloc { + final UserRepository repo; + HostelChangeBloc({required this.repo}) : super(const HostelChangeInitial()) { + on(_onHostelChangePressed); + on(_onHostelSearchQueryChanged); + } + + FutureOr _onHostelChangePressed( + HostelChangePressed event, Emitter emit) async { + emit(Loading()); + User user = await repo.getCurrentUser(); + int enrollmentNo = user.enrNo; + print(enrollmentNo); + String hostel = event.hostel; + try { + await repo.postChangeHostel(hostel); + emit(HostelChangeSuccess()); + } catch (e) { + emit(const HostelChangeInitial(error: AppConstants.GENERIC_FAILURE)); + } + } + + FutureOr _onHostelSearchQueryChanged( + HostelSearchQueryChanged event, Emitter emit) async { + if (event.query == "" ) { + emit(const HostelChangeInitial()); + } else { + emit(Loading()); + emit(HostelQueryChanged(query: event.query)); + } + // emit(const HostelChangeInitial()); + } +} diff --git a/lib/presentation/hostel_change/bloc/hostel_change_event.dart b/lib/presentation/hostel_change/bloc/hostel_change_event.dart new file mode 100644 index 00000000..6c31af0e --- /dev/null +++ b/lib/presentation/hostel_change/bloc/hostel_change_event.dart @@ -0,0 +1,17 @@ +part of 'hostel_change_bloc.dart'; + +abstract class HostelChangeEvent {} + +class HostelChangePressed extends HostelChangeEvent { + final String hostel; + HostelChangePressed({ + required this.hostel, + }); +} + +class HostelSearchQueryChanged extends HostelChangeEvent { + final String query; + HostelSearchQueryChanged({ + required this.query, + }); +} diff --git a/lib/presentation/hostel_change/bloc/hostel_change_state.dart b/lib/presentation/hostel_change/bloc/hostel_change_state.dart new file mode 100644 index 00000000..84ef7999 --- /dev/null +++ b/lib/presentation/hostel_change/bloc/hostel_change_state.dart @@ -0,0 +1,21 @@ +part of 'hostel_change_bloc.dart'; + +abstract class HostelChangeState extends Equatable { + const HostelChangeState(); + + @override + List get props => []; +} + +class HostelChangeInitial extends HostelChangeState{ + final String? error; + const HostelChangeInitial({this.error}); +} +class Loading extends HostelChangeState{} + +class HostelChangeSuccess extends HostelChangeState{} + +class HostelQueryChanged extends HostelChangeState{ + final String query; + const HostelQueryChanged({required this.query}); +} diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart index 1ce97bb7..92787064 100644 --- a/lib/presentation/hostel_change/hostel_change_screen.dart +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -1,20 +1,259 @@ +import 'package:appetizer/data/core/theme/dimensional/dimensional.dart'; +import 'package:appetizer/domain/repositories/user/user_repository.dart'; +import 'package:appetizer/presentation/components/black_button.dart'; +import 'package:appetizer/presentation/components/loading_indicator.dart'; +import 'package:appetizer/presentation/hostel_change/bloc/hostel_change_bloc.dart'; import 'package:appetizer/presentation/hostel_change/components/hostel_change_banner.dart'; +import 'package:appetizer/presentation/login/login_screen.dart'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; @RoutePage() -class HostelChangeScreen extends StatelessWidget{ +class HostelChangeScreen extends StatelessWidget { const HostelChangeScreen({super.key}); @override Widget build(BuildContext context) { + TextEditingController _searchController = TextEditingController(); + Map hostelMap = { + 'ANK': 'A.N. Khosla House', + 'AW': 'Azad Wing', + 'AZ': 'Azad Bhawan', + 'CB': 'Cautley Bhawan', + 'GA': 'Ganga Bhawan', + 'GB': 'Govind Bhawan', + 'GP': 'Ghananand Pande Bhawan', + 'IB': 'Indira Bhawan', + 'JB': 'Jawahar Bhawan', + 'KB': 'Kasturba Bhawan', + 'KIH': 'Khosla International House', + 'MB': 'Malviya Bhawan', + 'MR': 'M.R. Chopra Bhawan', + 'RKB': 'Radhakrishnan Bhawan', + 'RJB': 'Rajendra Bhawan', + 'RB': 'Rajiv Bhawan', + 'RV': 'Ravindra Bhawan', + 'SB': 'Sarojini Bhawan', + 'VK': 'Vigyan Kunj', + 'VKJ': 'Vikash Kunj', + 'DVG': 'Development Government', + 'DVP': 'Development Private', + }; return Scaffold( - body: Column( + body: SingleChildScrollView( + physics: const ClampingScrollPhysics(), + child: Column( children: [ - HostelChangeBanner(), - Text("Hostel Change") + const HostelChangeBanner(), + ScrollConfiguration( + behavior: NoOverScroll(), + child: BlocProvider( + create: (context) => + HostelChangeBloc(repo: context.read()), + child: BlocConsumer( + listener: (BuildContext context, HostelChangeState state) { + if (state is HostelChangeSuccess) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: + Text('Hostel change request sent successfully'), + backgroundColor: Colors.green, + ), + ); + context.router.pop(); + } + if (state is HostelChangeInitial && state.error != null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.error!), + backgroundColor: Colors.red, + ), + ); + } + if (state is HostelQueryChanged) { + print("UMMMMM " + state.query); + } + }, + builder: (BuildContext context, HostelChangeState state) { + if (state is Loading) { + return const Center(child: LoadingIndicator()); + } + if (state is HostelChangeInitial || + state is HostelQueryChanged) { + return Container( + color: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 24.toAutoScaledWidth, + vertical: 32.toAutoScaledHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Select New Hostel', + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 20.toAutoScaledFont, + fontFamily: 'Noto Sans', + fontWeight: FontWeight.w600, + ), + ), + 12.toVerticalSizedBox, + Container( + width: double.infinity, + padding: EdgeInsets.symmetric( + horizontal: 16.toAutoScaledWidth, + vertical: 16.toAutoScaledHeight), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: const Color(0xFFEFEFEF), + width: 1, + ), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(24, 24, 28, 0.07), + offset: Offset(0, 2), + blurRadius: 3, + spreadRadius: 1.5, + ), + ], + ), + child: Column( + children: [ + TextField( + controller: _searchController, + onChanged: (value) { + BlocProvider.of(context) + .add(HostelSearchQueryChanged( + query: value)); + print(state); + }, + decoration: InputDecoration( + filled: true, + fillColor: const Color(0xFFF1F1F1), + contentPadding: EdgeInsets.symmetric( + horizontal: 0.toAutoScaledWidth, + vertical: 0.toAutoScaledHeight), + hintText: 'Search', + hintStyle: TextStyle( + color: const Color(0xFF5F5F61), + fontSize: 14.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular( + 8.toAutoScaledWidth), + borderSide: BorderSide.none, + ), + prefixIcon: const Icon( + Icons.search_sharp, + color: Color(0xFF5F5F61), + size: 20, + )), + ), + if (state is HostelChangeInitial) + ListView.builder( + shrinkWrap: true, + itemCount: hostelMap.length, + itemBuilder: (context, index) { + return ListTile( + title: Text( + hostelMap.values.elementAt(index), + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 14.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + _searchController.text = + hostelMap.values.elementAt(index); + BlocProvider.of( + context) + .add(HostelSearchQueryChanged( + query: hostelMap.values + .elementAt(index))); + }, + ); + }, + ), + if (state is HostelQueryChanged) + SingleChildScrollView( + child: ListView.builder( + shrinkWrap: true, + itemCount: hostelMap.length, + itemBuilder: (context, index) { + if (hostelMap.values + .elementAt(index) + .toLowerCase() + .contains(state.query + .toLowerCase()) || + hostelMap.keys + .elementAt(index) + .toLowerCase() + .contains(state.query + .toLowerCase())) { + return ListTile( + title: Text( + hostelMap.values.elementAt(index), + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 14.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + _searchController.text = hostelMap + .values + .elementAt(index); + BlocProvider.of( + context) + .add(HostelSearchQueryChanged( + query: hostelMap.values + .elementAt(index))); + }, + ); + } + return const SizedBox( + height: 0, + ); + }, + ), + ), + const Divider(), + 10.toVerticalSizedBox, + BlackButton( + title: 'Submit', + onTap: () { + int index = hostelMap.values.toList().indexOf(_searchController.text); + String hostelId = hostelMap.keys.elementAt(index); + context.read().add( + HostelChangePressed(hostel: hostelId)); + }, + width: 100, + ), + ], + ), + ), + ], + ), + ); + } + if (state is HostelSearchQueryChanged) { + return Container(); + } + return Container(); + }, + ), + ), + ) ], - ) - ); + ), + )); } -} \ No newline at end of file +} From c21a52df0d6fd8823377d82a05c0261a7de87842 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Sun, 24 Dec 2023 03:09:24 +0530 Subject: [PATCH 04/13] feat: adds Hostel Request Status functionality --- lib/data/services/remote/api_service.dart | 3 + .../repositories/user/user_repository.dart | 9 +++ .../bloc/hostel_change_bloc.dart | 6 +- .../bloc/hostel_change_state.dart | 11 +-- .../hostel_change/hostel_change_screen.dart | 15 ++--- .../profile/bloc/profile_page_bloc.dart | 4 +- .../profile/bloc/profile_page_state.dart | 4 +- lib/presentation/profile/profile_view.dart | 67 ++++++++++++++++--- 8 files changed, 89 insertions(+), 30 deletions(-) diff --git a/lib/data/services/remote/api_service.dart b/lib/data/services/remote/api_service.dart index 55792dde..1b5caaaf 100644 --- a/lib/data/services/remote/api_service.dart +++ b/lib/data/services/remote/api_service.dart @@ -186,4 +186,7 @@ abstract class ApiService { Future postChangeHostel( @Body() Map map, ); + + @GET(ApiEndpoints.hostelChange) + Future getHostelChangeStatus(); } diff --git a/lib/domain/repositories/user/user_repository.dart b/lib/domain/repositories/user/user_repository.dart index a5fb1a12..69a84179 100644 --- a/lib/domain/repositories/user/user_repository.dart +++ b/lib/domain/repositories/user/user_repository.dart @@ -166,4 +166,13 @@ class UserRepository { throw Failure(AppConstants.GENERIC_FAILURE); } } + + Future getHostelChangeStatus() async { + try { + return await _apiService.getHostelChangeStatus(); + } catch (e) { + debugPrint(e.toString()); + throw Failure(AppConstants.GENERIC_FAILURE); + } + } } diff --git a/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart index a6bf8a47..9f1e9015 100644 --- a/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart +++ b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:appetizer/data/constants/constants.dart'; -import 'package:appetizer/domain/models/user/user.dart'; import 'package:appetizer/domain/repositories/user/user_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; @@ -19,9 +18,6 @@ class HostelChangeBloc extends Bloc { FutureOr _onHostelChangePressed( HostelChangePressed event, Emitter emit) async { emit(Loading()); - User user = await repo.getCurrentUser(); - int enrollmentNo = user.enrNo; - print(enrollmentNo); String hostel = event.hostel; try { await repo.postChangeHostel(hostel); @@ -33,7 +29,7 @@ class HostelChangeBloc extends Bloc { FutureOr _onHostelSearchQueryChanged( HostelSearchQueryChanged event, Emitter emit) async { - if (event.query == "" ) { + if (event.query == "") { emit(const HostelChangeInitial()); } else { emit(Loading()); diff --git a/lib/presentation/hostel_change/bloc/hostel_change_state.dart b/lib/presentation/hostel_change/bloc/hostel_change_state.dart index 84ef7999..d019b038 100644 --- a/lib/presentation/hostel_change/bloc/hostel_change_state.dart +++ b/lib/presentation/hostel_change/bloc/hostel_change_state.dart @@ -7,15 +7,16 @@ abstract class HostelChangeState extends Equatable { List get props => []; } -class HostelChangeInitial extends HostelChangeState{ - final String? error; +class HostelChangeInitial extends HostelChangeState { + final String? error; const HostelChangeInitial({this.error}); } -class Loading extends HostelChangeState{} -class HostelChangeSuccess extends HostelChangeState{} +class Loading extends HostelChangeState {} -class HostelQueryChanged extends HostelChangeState{ +class HostelChangeSuccess extends HostelChangeState {} + +class HostelQueryChanged extends HostelChangeState { final String query; const HostelQueryChanged({required this.query}); } diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart index 92787064..21709e13 100644 --- a/lib/presentation/hostel_change/hostel_change_screen.dart +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -11,11 +11,11 @@ import 'package:flutter_bloc/flutter_bloc.dart'; @RoutePage() class HostelChangeScreen extends StatelessWidget { - const HostelChangeScreen({super.key}); + final TextEditingController _searchController = TextEditingController(); + HostelChangeScreen({super.key}); @override Widget build(BuildContext context) { - TextEditingController _searchController = TextEditingController(); Map hostelMap = { 'ANK': 'A.N. Khosla House', 'AW': 'Azad Wing', @@ -71,9 +71,6 @@ class HostelChangeScreen extends StatelessWidget { ), ); } - if (state is HostelQueryChanged) { - print("UMMMMM " + state.query); - } }, builder: (BuildContext context, HostelChangeState state) { if (state is Loading) { @@ -128,7 +125,6 @@ class HostelChangeScreen extends StatelessWidget { BlocProvider.of(context) .add(HostelSearchQueryChanged( query: value)); - print(state); }, decoration: InputDecoration( filled: true, @@ -230,8 +226,11 @@ class HostelChangeScreen extends StatelessWidget { BlackButton( title: 'Submit', onTap: () { - int index = hostelMap.values.toList().indexOf(_searchController.text); - String hostelId = hostelMap.keys.elementAt(index); + int index = hostelMap.values + .toList() + .indexOf(_searchController.text); + String hostelId = + hostelMap.keys.elementAt(index); context.read().add( HostelChangePressed(hostel: hostelId)); }, diff --git a/lib/presentation/profile/bloc/profile_page_bloc.dart b/lib/presentation/profile/bloc/profile_page_bloc.dart index acef94ea..2a401058 100644 --- a/lib/presentation/profile/bloc/profile_page_bloc.dart +++ b/lib/presentation/profile/bloc/profile_page_bloc.dart @@ -16,8 +16,10 @@ class ProfilePageBloc extends Bloc { void _onFetch(FetchProfile event, Emitter emit) async { // TODO: implement event handler User user = await repo.getCurrentUser(); + dynamic hostelChangeStatus = await repo.getHostelChangeStatus(); emit( - ProfilePageFetchedState(user: user), + ProfilePageFetchedState( + user: user, hostelChangeStatus: hostelChangeStatus), ); } } diff --git a/lib/presentation/profile/bloc/profile_page_state.dart b/lib/presentation/profile/bloc/profile_page_state.dart index c54f1356..6c20137a 100644 --- a/lib/presentation/profile/bloc/profile_page_state.dart +++ b/lib/presentation/profile/bloc/profile_page_state.dart @@ -16,11 +16,13 @@ class ProfilePageInitialState extends ProfilePageState { class ProfilePageFetchedState extends ProfilePageState { const ProfilePageFetchedState({ + required this.hostelChangeStatus, required this.user, }); final User user; + final dynamic hostelChangeStatus; @override - List get props => [user]; + List get props => [user, hostelChangeStatus]; } diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 90eb723e..6f11c930 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -29,6 +29,13 @@ class ProfileScreen extends StatelessWidget { BlocBuilder( builder: (context, state) { if (state is ProfilePageFetchedState) { + String hostelChangeStatus = + state.hostelChangeStatus['is_approved_by_supervisor'] == + null || + state + .hostelChangeStatus['is_approved_by_supervisor'] + ? 'Approved by Supervisor' + : 'Pending'; return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -58,7 +65,8 @@ class ProfileScreen extends StatelessWidget { ), Container( padding: EdgeInsets.symmetric( - vertical: 24.toAutoScaledHeight,), + vertical: 24.toAutoScaledHeight, + ), child: Column( children: [ Row( @@ -94,15 +102,54 @@ class ProfileScreen extends StatelessWidget { ], ), 10.toVerticalSizedBox, - ProfileTextButton( - title: 'Request for Hostel Change', - onPressed: () { - context.router.push( - const HostelChangeRoute()); - }, - horizontalPadding: 50, - width: 248, - ), + if (state.hostelChangeStatus['details'] != + null || + (state.hostelChangeStatus[ + 'is_approved_by_admin'])) + ProfileTextButton( + title: 'Request for Hostel Change', + onPressed: () { + context.router.push(HostelChangeRoute()); + }, + horizontalPadding: 50, + width: 248, + ), + if (state.hostelChangeStatus['details'] == null) + Container( + width: 248.toAutoScaledWidth, + padding: EdgeInsets.symmetric( + vertical: 6.toAutoScaledHeight, + horizontal: 22.toAutoScaledWidth, + ), + color: const Color(0xFFF6F6F6), + child: Column(children: [ + Align( + alignment: Alignment.centerLeft, + child: Text( + "Requested for hostel change to ${state.hostelChangeStatus['new_hostel']}", + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 13.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), + ), + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + "Status: $hostelChangeStatus", + textAlign: TextAlign.justify, + style: TextStyle( + color: const Color(0xFF2F2F2F), + fontSize: 12.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), + ), + ), + ]), + ) ], ), ), From 66448bbd473450d4f567c120c0c6bb5bef75fd15 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Sun, 24 Dec 2023 04:33:20 +0530 Subject: [PATCH 05/13] feat: adds delete Hostel Change request functionality --- lib/data/services/remote/api_service.dart | 3 + .../repositories/user/user_repository.dart | 11 +- .../components/hostel_change_banner.dart | 3 +- .../hostel_change/hostel_change_screen.dart | 3 +- .../profile/bloc/profile_page_bloc.dart | 23 +++- .../profile/bloc/profile_page_event.dart | 7 + lib/presentation/profile/profile_view.dart | 120 ++++++++++++------ 7 files changed, 125 insertions(+), 45 deletions(-) diff --git a/lib/data/services/remote/api_service.dart b/lib/data/services/remote/api_service.dart index 1b5caaaf..28c3379b 100644 --- a/lib/data/services/remote/api_service.dart +++ b/lib/data/services/remote/api_service.dart @@ -189,4 +189,7 @@ abstract class ApiService { @GET(ApiEndpoints.hostelChange) Future getHostelChangeStatus(); + + @DELETE(ApiEndpoints.hostelChange) + Future deleteChangeHostel(); } diff --git a/lib/domain/repositories/user/user_repository.dart b/lib/domain/repositories/user/user_repository.dart index 69a84179..27632f13 100644 --- a/lib/domain/repositories/user/user_repository.dart +++ b/lib/domain/repositories/user/user_repository.dart @@ -157,7 +157,7 @@ class UserRepository { Future postChangeHostel(String hostelCode) async { Map map = { - 'new_hostel_id': hostelCode, + 'new_hostel_code': hostelCode, }; try { return await _apiService.postChangeHostel(map); @@ -175,4 +175,13 @@ class UserRepository { throw Failure(AppConstants.GENERIC_FAILURE); } } + + Future deleteChangeHostel() async { + try { + return await _apiService.deleteChangeHostel(); + } catch (e) { + debugPrint(e.toString()); + throw Failure(AppConstants.GENERIC_FAILURE); + } + } } diff --git a/lib/presentation/hostel_change/components/hostel_change_banner.dart b/lib/presentation/hostel_change/components/hostel_change_banner.dart index c1a309ee..1c1dde87 100644 --- a/lib/presentation/hostel_change/components/hostel_change_banner.dart +++ b/lib/presentation/hostel_change/components/hostel_change_banner.dart @@ -1,4 +1,5 @@ import 'package:appetizer/app_theme.dart'; +import 'package:appetizer/data/core/router/intrinsic_router/intrinsic_router.gr.dart'; import 'package:appetizer/data/core/theme/dimensional/dimensional.dart'; import 'package:appetizer/presentation/components/app_banner.dart'; import 'package:auto_route/auto_route.dart'; @@ -14,7 +15,7 @@ class HostelChangeBanner extends StatelessWidget { child: Row( children: [ IconButton( - onPressed: context.router.pop, + onPressed: () => context.router.replace(const ProfileRoute()), icon: const Icon( Icons.arrow_back, color: Colors.white, diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart index 21709e13..a64843a5 100644 --- a/lib/presentation/hostel_change/hostel_change_screen.dart +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -1,3 +1,4 @@ +import 'package:appetizer/data/core/router/intrinsic_router/intrinsic_router.gr.dart'; import 'package:appetizer/data/core/theme/dimensional/dimensional.dart'; import 'package:appetizer/domain/repositories/user/user_repository.dart'; import 'package:appetizer/presentation/components/black_button.dart'; @@ -61,7 +62,7 @@ class HostelChangeScreen extends StatelessWidget { backgroundColor: Colors.green, ), ); - context.router.pop(); + context.router.replace(const ProfileRoute()); } if (state is HostelChangeInitial && state.error != null) { ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/presentation/profile/bloc/profile_page_bloc.dart b/lib/presentation/profile/bloc/profile_page_bloc.dart index 2a401058..b6762423 100644 --- a/lib/presentation/profile/bloc/profile_page_bloc.dart +++ b/lib/presentation/profile/bloc/profile_page_bloc.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:appetizer/domain/models/user/user.dart'; import 'package:appetizer/domain/repositories/user/user_repository.dart'; import 'package:bloc/bloc.dart'; @@ -11,12 +13,31 @@ class ProfilePageBloc extends Bloc { ProfilePageBloc({required this.repo}) : super(const ProfilePageInitialState()) { on(_onFetch); + on(_onDeleteHostelChangeRequest); } void _onFetch(FetchProfile event, Emitter emit) async { // TODO: implement event handler User user = await repo.getCurrentUser(); - dynamic hostelChangeStatus = await repo.getHostelChangeStatus(); + try { + dynamic hostelChangeStatus = await repo.getHostelChangeStatus(); + emit( + ProfilePageFetchedState( + user: user, hostelChangeStatus: hostelChangeStatus), + ); + } catch (e) { + emit( + ProfilePageFetchedState( + user: user, hostelChangeStatus: const {'detail': 'No Request'}), + ); + } + } + + FutureOr _onDeleteHostelChangeRequest( + DeleteHostelChangeRequest event, Emitter emit) async { + emit(const ProfilePageInitialState()); + User user = await repo.getCurrentUser(); + dynamic hostelChangeStatus = await repo.deleteChangeHostel(); emit( ProfilePageFetchedState( user: user, hostelChangeStatus: hostelChangeStatus), diff --git a/lib/presentation/profile/bloc/profile_page_event.dart b/lib/presentation/profile/bloc/profile_page_event.dart index f5d31c49..86d6d596 100644 --- a/lib/presentation/profile/bloc/profile_page_event.dart +++ b/lib/presentation/profile/bloc/profile_page_event.dart @@ -13,3 +13,10 @@ class FetchProfile extends ProfilePageEvent { @override List get props => []; } + +class DeleteHostelChangeRequest extends ProfilePageEvent { + const DeleteHostelChangeRequest(); + + @override + List get props => []; +} diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 6f11c930..d3e8243f 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -29,13 +29,15 @@ class ProfileScreen extends StatelessWidget { BlocBuilder( builder: (context, state) { if (state is ProfilePageFetchedState) { - String hostelChangeStatus = - state.hostelChangeStatus['is_approved_by_supervisor'] == - null || - state - .hostelChangeStatus['is_approved_by_supervisor'] - ? 'Approved by Supervisor' - : 'Pending'; + String hostelChangeStatus = ''; + if (state.hostelChangeStatus['is_approved_by_supervisor'] != + null) { + hostelChangeStatus = + state.hostelChangeStatus['is_approved_by_supervisor'] + ? 'Approved by Supervisor' + : 'Pending'; + } + return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -102,53 +104,89 @@ class ProfileScreen extends StatelessWidget { ], ), 10.toVerticalSizedBox, - if (state.hostelChangeStatus['details'] != + if (state.hostelChangeStatus['detail'] != null || (state.hostelChangeStatus[ - 'is_approved_by_admin'])) + 'is_approved_by_admin'] != + null && + state.hostelChangeStatus[ + 'is_approved_by_admin'])) ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { - context.router.push(HostelChangeRoute()); + context.router + .replace(HostelChangeRoute()); }, horizontalPadding: 50, width: 248, ), - if (state.hostelChangeStatus['details'] == null) - Container( - width: 248.toAutoScaledWidth, - padding: EdgeInsets.symmetric( - vertical: 6.toAutoScaledHeight, - horizontal: 22.toAutoScaledWidth, - ), - color: const Color(0xFFF6F6F6), - child: Column(children: [ - Align( - alignment: Alignment.centerLeft, - child: Text( - "Requested for hostel change to ${state.hostelChangeStatus['new_hostel']}", - style: TextStyle( - color: const Color(0xFF111111), - fontSize: 13.toAutoScaledFont, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, + if (state.hostelChangeStatus['detail'] == null) + TextButton( + onPressed: () => { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text( + 'Cancel Hostel Change Request'), + content: const Text( + 'You have already requested for a hostel change. Do you want to cancel it?', + textAlign: TextAlign.center, + ), + actions: [ + TextButton( + onPressed: () { + context + .read< + ProfilePageBloc>() + .add( + const DeleteHostelChangeRequest()); + Navigator.pop(ctx); + }, + child: const Text('Delete'), + ), + TextButton( + onPressed: () => + Navigator.pop(ctx), + child: const Text('Cancel'), + ) + ], + )) + }, + child: Container( + width: 248.toAutoScaledWidth, + padding: EdgeInsets.symmetric( + vertical: 6.toAutoScaledHeight, + horizontal: 22.toAutoScaledWidth, + ), + color: const Color(0xFFF6F6F6), + child: Column(children: [ + Align( + alignment: Alignment.centerLeft, + child: Text( + "Requested for hostel change to ${state.hostelChangeStatus['new_hostel']}", + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 13.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), ), ), - ), - Align( - alignment: Alignment.centerLeft, - child: Text( - "Status: $hostelChangeStatus", - textAlign: TextAlign.justify, - style: TextStyle( - color: const Color(0xFF2F2F2F), - fontSize: 12.toAutoScaledFont, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, + Align( + alignment: Alignment.centerLeft, + child: Text( + "Status: $hostelChangeStatus", + textAlign: TextAlign.justify, + style: TextStyle( + color: const Color(0xFF2F2F2F), + fontSize: 12.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), ), ), - ), - ]), + ]), + ), ) ], ), From e3de5264fa3b65317d3f732cf1116e4e762b08f7 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Tue, 2 Jan 2024 17:40:09 +0530 Subject: [PATCH 06/13] feat: adds Room No change request --- .../repositories/user/user_repository.dart | 3 +- .../bloc/hostel_change_bloc.dart | 12 +- .../bloc/hostel_change_event.dart | 2 + .../components/hostel_change_banner.dart | 3 +- .../hostel_change/hostel_change_screen.dart | 411 ++++++++++-------- lib/presentation/profile/profile_view.dart | 31 +- 6 files changed, 256 insertions(+), 206 deletions(-) diff --git a/lib/domain/repositories/user/user_repository.dart b/lib/domain/repositories/user/user_repository.dart index 27632f13..a68fd080 100644 --- a/lib/domain/repositories/user/user_repository.dart +++ b/lib/domain/repositories/user/user_repository.dart @@ -155,9 +155,10 @@ class UserRepository { } } - Future postChangeHostel(String hostelCode) async { + Future postChangeHostel(String hostelCode, String roomNo) async { Map map = { 'new_hostel_code': hostelCode, + 'new_room_no': roomNo }; try { return await _apiService.postChangeHostel(map); diff --git a/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart index 9f1e9015..b27376d1 100644 --- a/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart +++ b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart @@ -19,8 +19,18 @@ class HostelChangeBloc extends Bloc { HostelChangePressed event, Emitter emit) async { emit(Loading()); String hostel = event.hostel; + String roomNo = event.roomNo; + if (hostel == "") { + emit(const HostelChangeInitial(error: "Please select a hostel")); + return; + } + if (roomNo == "") { + emit(const HostelChangeInitial(error: "Please enter a room number")); + if (hostel != "") emit(HostelQueryChanged(query: hostel)); + return; + } try { - await repo.postChangeHostel(hostel); + await repo.postChangeHostel(hostel, roomNo); emit(HostelChangeSuccess()); } catch (e) { emit(const HostelChangeInitial(error: AppConstants.GENERIC_FAILURE)); diff --git a/lib/presentation/hostel_change/bloc/hostel_change_event.dart b/lib/presentation/hostel_change/bloc/hostel_change_event.dart index 6c31af0e..2c49513b 100644 --- a/lib/presentation/hostel_change/bloc/hostel_change_event.dart +++ b/lib/presentation/hostel_change/bloc/hostel_change_event.dart @@ -4,8 +4,10 @@ abstract class HostelChangeEvent {} class HostelChangePressed extends HostelChangeEvent { final String hostel; + final String roomNo; HostelChangePressed({ required this.hostel, + required this.roomNo, }); } diff --git a/lib/presentation/hostel_change/components/hostel_change_banner.dart b/lib/presentation/hostel_change/components/hostel_change_banner.dart index 1c1dde87..c8347410 100644 --- a/lib/presentation/hostel_change/components/hostel_change_banner.dart +++ b/lib/presentation/hostel_change/components/hostel_change_banner.dart @@ -1,5 +1,4 @@ import 'package:appetizer/app_theme.dart'; -import 'package:appetizer/data/core/router/intrinsic_router/intrinsic_router.gr.dart'; import 'package:appetizer/data/core/theme/dimensional/dimensional.dart'; import 'package:appetizer/presentation/components/app_banner.dart'; import 'package:auto_route/auto_route.dart'; @@ -15,7 +14,7 @@ class HostelChangeBanner extends StatelessWidget { child: Row( children: [ IconButton( - onPressed: () => context.router.replace(const ProfileRoute()), + onPressed: () => context.router.pop(), icon: const Icon( Icons.arrow_back, color: Colors.white, diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart index a64843a5..d44f92a5 100644 --- a/lib/presentation/hostel_change/hostel_change_screen.dart +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -5,14 +5,15 @@ import 'package:appetizer/presentation/components/black_button.dart'; import 'package:appetizer/presentation/components/loading_indicator.dart'; import 'package:appetizer/presentation/hostel_change/bloc/hostel_change_bloc.dart'; import 'package:appetizer/presentation/hostel_change/components/hostel_change_banner.dart'; -import 'package:appetizer/presentation/login/login_screen.dart'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; @RoutePage() class HostelChangeScreen extends StatelessWidget { final TextEditingController _searchController = TextEditingController(); + final TextEditingController _roomNoController = TextEditingController(); HostelChangeScreen({super.key}); @override @@ -43,213 +44,245 @@ class HostelChangeScreen extends StatelessWidget { }; return Scaffold( body: SingleChildScrollView( - physics: const ClampingScrollPhysics(), child: Column( children: [ const HostelChangeBanner(), - ScrollConfiguration( - behavior: NoOverScroll(), - child: BlocProvider( - create: (context) => - HostelChangeBloc(repo: context.read()), - child: BlocConsumer( - listener: (BuildContext context, HostelChangeState state) { - if (state is HostelChangeSuccess) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: - Text('Hostel change request sent successfully'), - backgroundColor: Colors.green, - ), - ); - context.router.replace(const ProfileRoute()); - } - if (state is HostelChangeInitial && state.error != null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(state.error!), - backgroundColor: Colors.red, - ), - ); - } - }, - builder: (BuildContext context, HostelChangeState state) { - if (state is Loading) { - return const Center(child: LoadingIndicator()); - } - if (state is HostelChangeInitial || - state is HostelQueryChanged) { - return Container( - color: Colors.white, - padding: EdgeInsets.symmetric( - horizontal: 24.toAutoScaledWidth, - vertical: 32.toAutoScaledHeight), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Select New Hostel', - style: TextStyle( - color: const Color(0xFF111111), - fontSize: 20.toAutoScaledFont, - fontFamily: 'Noto Sans', - fontWeight: FontWeight.w600, + BlocProvider( + create: (context) => + HostelChangeBloc(repo: context.read()), + child: BlocConsumer( + listener: (BuildContext context, HostelChangeState state) { + if (state is HostelChangeSuccess) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Hostel change request sent successfully'), + backgroundColor: Colors.green, + ), + ); + context.router.pushAndPopUntil(const ProfileRoute(), predicate: ModalRoute.withName(ProfileRoute.name)); + } + if (state is HostelChangeInitial && state.error != null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.error!), + backgroundColor: Colors.red, + ), + ); + } + }, + builder: (BuildContext context, HostelChangeState state) { + if (state is Loading) { + return const Center(child: LoadingIndicator()); + } + if (state is HostelChangeInitial || + state is HostelQueryChanged) { + return Container( + color: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 24.toAutoScaledWidth, + vertical: 32.toAutoScaledHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Select New Hostel', + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 20.toAutoScaledFont, + fontFamily: 'Noto Sans', + fontWeight: FontWeight.w600, + ), + ), + 12.toVerticalSizedBox, + Container( + width: double.infinity, + padding: EdgeInsets.symmetric( + horizontal: 16.toAutoScaledWidth, + vertical: 16.toAutoScaledHeight), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: const Color(0xFFEFEFEF), + width: 1, ), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(24, 24, 28, 0.07), + offset: Offset(0, 2), + blurRadius: 3, + spreadRadius: 1.5, + ), + ], ), - 12.toVerticalSizedBox, - Container( - width: double.infinity, - padding: EdgeInsets.symmetric( - horizontal: 16.toAutoScaledWidth, - vertical: 16.toAutoScaledHeight), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: const Color(0xFFEFEFEF), - width: 1, + child: Column( + children: [ + TextField( + controller: _searchController, + onChanged: (value) { + BlocProvider.of(context) + .add(HostelSearchQueryChanged( + query: value)); + }, + decoration: InputDecoration( + filled: true, + fillColor: const Color(0xFFF1F1F1), + contentPadding: EdgeInsets.symmetric( + horizontal: 0.toAutoScaledWidth, + vertical: 0.toAutoScaledHeight), + hintText: 'Search', + hintStyle: TextStyle( + color: const Color(0xFF5F5F61), + fontSize: 14.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular( + 8.toAutoScaledWidth), + borderSide: BorderSide.none, + ), + prefixIcon: const Icon( + Icons.search_sharp, + color: Color(0xFF5F5F61), + size: 20, + )), ), - boxShadow: const [ - BoxShadow( - color: Color.fromRGBO(24, 24, 28, 0.07), - offset: Offset(0, 2), - blurRadius: 3, - spreadRadius: 1.5, - ), - ], - ), - child: Column( - children: [ - TextField( - controller: _searchController, - onChanged: (value) { - BlocProvider.of(context) - .add(HostelSearchQueryChanged( - query: value)); - }, - decoration: InputDecoration( - filled: true, - fillColor: const Color(0xFFF1F1F1), - contentPadding: EdgeInsets.symmetric( - horizontal: 0.toAutoScaledWidth, - vertical: 0.toAutoScaledHeight), - hintText: 'Search', - hintStyle: TextStyle( - color: const Color(0xFF5F5F61), - fontSize: 14.toAutoScaledFont, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular( - 8.toAutoScaledWidth), - borderSide: BorderSide.none, + if (state is HostelChangeInitial) + ListView.builder( + shrinkWrap: true, + itemCount: hostelMap.length, + itemBuilder: (context, index) { + return ListTile( + title: Text( + hostelMap.values.elementAt(index), + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 14.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + ), ), - prefixIcon: const Icon( - Icons.search_sharp, - color: Color(0xFF5F5F61), - size: 20, - )), + onTap: () { + _searchController.text = + hostelMap.values.elementAt(index); + BlocProvider.of( + context) + .add(HostelSearchQueryChanged( + query: hostelMap.values + .elementAt(index))); + }, + ); + }, ), - if (state is HostelChangeInitial) - ListView.builder( + if (state is HostelQueryChanged) + SingleChildScrollView( + child: ListView.builder( shrinkWrap: true, itemCount: hostelMap.length, itemBuilder: (context, index) { - return ListTile( - title: Text( - hostelMap.values.elementAt(index), - style: TextStyle( - color: const Color(0xFF111111), - fontSize: 14.toAutoScaledFont, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, + if (hostelMap.values + .elementAt(index) + .toLowerCase() + .contains( + state.query.toLowerCase()) || + hostelMap.keys + .elementAt(index) + .toLowerCase() + .contains( + state.query.toLowerCase())) { + return ListTile( + title: Text( + hostelMap.values.elementAt(index), + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 14.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + ), ), - ), - onTap: () { - _searchController.text = - hostelMap.values.elementAt(index); - BlocProvider.of( - context) - .add(HostelSearchQueryChanged( - query: hostelMap.values - .elementAt(index))); - }, + onTap: () { + _searchController.text = hostelMap + .values + .elementAt(index); + BlocProvider.of( + context) + .add(HostelSearchQueryChanged( + query: hostelMap.values + .elementAt(index))); + }, + ); + } + return const SizedBox( + height: 0, ); }, ), - if (state is HostelQueryChanged) - SingleChildScrollView( - child: ListView.builder( - shrinkWrap: true, - itemCount: hostelMap.length, - itemBuilder: (context, index) { - if (hostelMap.values - .elementAt(index) - .toLowerCase() - .contains(state.query - .toLowerCase()) || - hostelMap.keys - .elementAt(index) - .toLowerCase() - .contains(state.query - .toLowerCase())) { - return ListTile( - title: Text( - hostelMap.values.elementAt(index), - style: TextStyle( - color: const Color(0xFF111111), - fontSize: 14.toAutoScaledFont, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - ), - ), - onTap: () { - _searchController.text = hostelMap - .values - .elementAt(index); - BlocProvider.of( - context) - .add(HostelSearchQueryChanged( - query: hostelMap.values - .elementAt(index))); - }, - ); - } - return const SizedBox( - height: 0, - ); - }, - ), + ), + const Divider(), + 10.toVerticalSizedBox, + Align( + alignment: Alignment.centerLeft, + child: Text( + 'New Room Number', + style: GoogleFonts.notoSans( + fontSize: 14.toAutoScaledFont, + fontWeight: FontWeight.w600, ), - const Divider(), - 10.toVerticalSizedBox, - BlackButton( - title: 'Submit', - onTap: () { - int index = hostelMap.values - .toList() - .indexOf(_searchController.text); - String hostelId = - hostelMap.keys.elementAt(index); - context.read().add( - HostelChangePressed(hostel: hostelId)); - }, - width: 100, + textAlign: TextAlign.start, ), - ], - ), + ), + 6.toVerticalSizedBox, + TextField( + controller: _roomNoController, + decoration: InputDecoration( + hintText: 'Enter new Room Number', + hintStyle: GoogleFonts.lato( + fontSize: 12, + color: const Color(0xFF111111), + fontWeight: FontWeight.w600, + ), + border: OutlineInputBorder( + borderSide: BorderSide( + color: const Color(0xFF111111) + .withOpacity(0.25)), + borderRadius: BorderRadius.circular(5), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 20.toAutoScaledWidth), + ), + ), + 20.toVerticalSizedBox, + const Divider(), + 10.toVerticalSizedBox, + BlackButton( + title: 'Submit', + onTap: () { + int index = hostelMap.values + .toList() + .indexOf(_searchController.text); + String hostelId = index != -1 + ? hostelMap.keys.elementAt(index) + : ""; + String roomNo = _roomNoController.text; + context.read().add( + HostelChangePressed( + hostel: hostelId, roomNo: roomNo)); + }, + width: 100, + ), + ], ), - ], - ), - ); - } - if (state is HostelSearchQueryChanged) { - return Container(); - } + ), + ], + ), + ); + } + if (state is HostelSearchQueryChanged) { return Container(); - }, - ), + } + return Container(); + }, ), ) ], diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index d3e8243f..caabea98 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -29,14 +29,6 @@ class ProfileScreen extends StatelessWidget { BlocBuilder( builder: (context, state) { if (state is ProfilePageFetchedState) { - String hostelChangeStatus = ''; - if (state.hostelChangeStatus['is_approved_by_supervisor'] != - null) { - hostelChangeStatus = - state.hostelChangeStatus['is_approved_by_supervisor'] - ? 'Approved by Supervisor' - : 'Pending'; - } return Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -107,15 +99,15 @@ class ProfileScreen extends StatelessWidget { if (state.hostelChangeStatus['detail'] != null || (state.hostelChangeStatus[ - 'is_approved_by_admin'] != + 'is_approved'] != null && state.hostelChangeStatus[ - 'is_approved_by_admin'])) + 'is_approved'])) ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { context.router - .replace(HostelChangeRoute()); + .push(HostelChangeRoute()); }, horizontalPadding: 50, width: 248, @@ -163,7 +155,7 @@ class ProfileScreen extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - "Requested for hostel change to ${state.hostelChangeStatus['new_hostel']}", + "Requested for hostel change to ${state.hostelChangeStatus['hostel_code']}", style: TextStyle( color: const Color(0xFF111111), fontSize: 13.toAutoScaledFont, @@ -175,7 +167,20 @@ class ProfileScreen extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - "Status: $hostelChangeStatus", + "New Room No: ${state.hostelChangeStatus['new_room_no']}", + textAlign: TextAlign.justify, + style: TextStyle( + color: const Color(0xFF2F2F2F), + fontSize: 12.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), + ), + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + "Status: Pending", textAlign: TextAlign.justify, style: TextStyle( color: const Color(0xFF2F2F2F), From 1bd2df51b00e16f91bf244c5e83be292f184ca9a Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Tue, 2 Jan 2024 17:43:52 +0530 Subject: [PATCH 07/13] chore: beautifies Code --- .../hostel_change/hostel_change_screen.dart | 3 ++- lib/presentation/profile/profile_view.dart | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart index d44f92a5..539a1c4c 100644 --- a/lib/presentation/hostel_change/hostel_change_screen.dart +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -59,7 +59,8 @@ class HostelChangeScreen extends StatelessWidget { backgroundColor: Colors.green, ), ); - context.router.pushAndPopUntil(const ProfileRoute(), predicate: ModalRoute.withName(ProfileRoute.name)); + context.router.pushAndPopUntil(const ProfileRoute(), + predicate: ModalRoute.withName(ProfileRoute.name)); } if (state is HostelChangeInitial && state.error != null) { ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index caabea98..a0319f1a 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -29,7 +29,6 @@ class ProfileScreen extends StatelessWidget { BlocBuilder( builder: (context, state) { if (state is ProfilePageFetchedState) { - return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -98,16 +97,14 @@ class ProfileScreen extends StatelessWidget { 10.toVerticalSizedBox, if (state.hostelChangeStatus['detail'] != null || - (state.hostelChangeStatus[ - 'is_approved'] != + (state.hostelChangeStatus['is_approved'] != null && - state.hostelChangeStatus[ - 'is_approved'])) + state + .hostelChangeStatus['is_approved'])) ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { - context.router - .push(HostelChangeRoute()); + context.router.push(HostelChangeRoute()); }, horizontalPadding: 50, width: 248, From babab58d102b50b732b4049786c3fe8fe6923088 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Wed, 3 Jan 2024 20:10:57 +0530 Subject: [PATCH 08/13] chore : creates HostelChangeRequest model --- lib/data/services/remote/api_service.dart | 3 +- .../hostel_change_request.dart | 20 ++++++++++++ .../profile/bloc/profile_page_bloc.dart | 32 ++++++++++++++++--- lib/presentation/profile/profile_view.dart | 14 +++----- 4 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 lib/domain/models/hostel_change_request/hostel_change_request.dart diff --git a/lib/data/services/remote/api_service.dart b/lib/data/services/remote/api_service.dart index 28c3379b..8f42a50d 100644 --- a/lib/data/services/remote/api_service.dart +++ b/lib/data/services/remote/api_service.dart @@ -3,6 +3,7 @@ import 'package:appetizer/domain/models/appetizer_version.dart'; import 'package:appetizer/domain/models/coupon/coupon.dart'; import 'package:appetizer/domain/models/feedback/appetizer_feedback.dart'; import 'package:appetizer/domain/models/feedback/feedback_response.dart'; +import 'package:appetizer/domain/models/hostel_change_request/hostel_change_request.dart'; import 'package:appetizer/domain/models/leaves/paginated_leaves.dart'; import 'package:appetizer/domain/models/menu/week_menu_tmp.dart'; import 'package:appetizer/domain/models/transaction/faq.dart'; @@ -188,7 +189,7 @@ abstract class ApiService { ); @GET(ApiEndpoints.hostelChange) - Future getHostelChangeStatus(); + Future getHostelChangeStatus(); @DELETE(ApiEndpoints.hostelChange) Future deleteChangeHostel(); diff --git a/lib/domain/models/hostel_change_request/hostel_change_request.dart b/lib/domain/models/hostel_change_request/hostel_change_request.dart new file mode 100644 index 00000000..faf7c62c --- /dev/null +++ b/lib/domain/models/hostel_change_request/hostel_change_request.dart @@ -0,0 +1,20 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'hostel_change_request.freezed.dart'; +part 'hostel_change_request.g.dart'; + +@freezed +class HostelChangeRequest with _$HostelChangeRequest { + @JsonSerializable(fieldRename: FieldRename.snake) + const factory HostelChangeRequest( + {required int user, + required int id, + required String hostelCode, + required String newRoomNo, + bool? isApproved, + required String timestamp, + required int newHostel}) = _HostelChangeRequest; + + factory HostelChangeRequest.fromJson(Map json) => + _$HostelChangeRequestFromJson(json); +} diff --git a/lib/presentation/profile/bloc/profile_page_bloc.dart b/lib/presentation/profile/bloc/profile_page_bloc.dart index b6762423..ca9efcf9 100644 --- a/lib/presentation/profile/bloc/profile_page_bloc.dart +++ b/lib/presentation/profile/bloc/profile_page_bloc.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:appetizer/domain/models/hostel_change_request/hostel_change_request.dart'; import 'package:appetizer/domain/models/user/user.dart'; import 'package:appetizer/domain/repositories/user/user_repository.dart'; import 'package:bloc/bloc.dart'; @@ -20,15 +21,27 @@ class ProfilePageBloc extends Bloc { // TODO: implement event handler User user = await repo.getCurrentUser(); try { - dynamic hostelChangeStatus = await repo.getHostelChangeStatus(); + HostelChangeRequest hostelChangeStatus = + await repo.getHostelChangeStatus(); emit( ProfilePageFetchedState( - user: user, hostelChangeStatus: hostelChangeStatus), + user: user, + hostelChangeStatus: hostelChangeStatus, + ), ); } catch (e) { emit( ProfilePageFetchedState( - user: user, hostelChangeStatus: const {'detail': 'No Request'}), + user: user, + hostelChangeStatus: const HostelChangeRequest( + user: 0, + id: 0, + hostelCode: "", + newRoomNo: "", + timestamp: "", + newHostel: 0, + isApproved: null), + ), ); } } @@ -37,10 +50,19 @@ class ProfilePageBloc extends Bloc { DeleteHostelChangeRequest event, Emitter emit) async { emit(const ProfilePageInitialState()); User user = await repo.getCurrentUser(); - dynamic hostelChangeStatus = await repo.deleteChangeHostel(); + await repo.deleteChangeHostel(); emit( ProfilePageFetchedState( - user: user, hostelChangeStatus: hostelChangeStatus), + user: user, + hostelChangeStatus: const HostelChangeRequest( + user: 0, + id: 0, + hostelCode: "", + newRoomNo: "", + timestamp: "", + newHostel: 0, + isApproved: null), + ), ); } } diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index a0319f1a..7e461d13 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -95,12 +95,7 @@ class ProfileScreen extends StatelessWidget { ], ), 10.toVerticalSizedBox, - if (state.hostelChangeStatus['detail'] != - null || - (state.hostelChangeStatus['is_approved'] != - null && - state - .hostelChangeStatus['is_approved'])) + if (state.hostelChangeStatus.isApproved == null) ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { @@ -109,7 +104,7 @@ class ProfileScreen extends StatelessWidget { horizontalPadding: 50, width: 248, ), - if (state.hostelChangeStatus['detail'] == null) + if (state.hostelChangeStatus.isApproved != null) TextButton( onPressed: () => { showDialog( @@ -152,7 +147,7 @@ class ProfileScreen extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - "Requested for hostel change to ${state.hostelChangeStatus['hostel_code']}", + "Requested for hostel change to ${state.hostelChangeStatus.hostelCode}", style: TextStyle( color: const Color(0xFF111111), fontSize: 13.toAutoScaledFont, @@ -164,7 +159,7 @@ class ProfileScreen extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - "New Room No: ${state.hostelChangeStatus['new_room_no']}", + "New Room No: ${state.hostelChangeStatus.newRoomNo}", textAlign: TextAlign.justify, style: TextStyle( color: const Color(0xFF2F2F2F), @@ -244,7 +239,6 @@ class ProfileScreen extends StatelessWidget { ], ); } - return SizedBox( height: 200.toAutoScaledHeight, child: const Align( From 44955d3da6266ce8de24dda0fdf5bec241ef65b9 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Wed, 3 Jan 2024 20:29:28 +0530 Subject: [PATCH 09/13] chore: changes all BlocProvider.of to context.read --- .../hostel_change/hostel_change_screen.dart | 14 ++++---- lib/presentation/login/login_screen.dart | 34 +++++++++---------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/lib/presentation/hostel_change/hostel_change_screen.dart b/lib/presentation/hostel_change/hostel_change_screen.dart index 539a1c4c..77e9c0bc 100644 --- a/lib/presentation/hostel_change/hostel_change_screen.dart +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -121,9 +121,8 @@ class HostelChangeScreen extends StatelessWidget { TextField( controller: _searchController, onChanged: (value) { - BlocProvider.of(context) - .add(HostelSearchQueryChanged( - query: value)); + context.read().add( + HostelSearchQueryChanged(query: value)); }, decoration: InputDecoration( filled: true, @@ -167,9 +166,8 @@ class HostelChangeScreen extends StatelessWidget { onTap: () { _searchController.text = hostelMap.values.elementAt(index); - BlocProvider.of( - context) - .add(HostelSearchQueryChanged( + context.read().add( + HostelSearchQueryChanged( query: hostelMap.values .elementAt(index))); }, @@ -206,8 +204,8 @@ class HostelChangeScreen extends StatelessWidget { _searchController.text = hostelMap .values .elementAt(index); - BlocProvider.of( - context) + context + .read() .add(HostelSearchQueryChanged( query: hostelMap.values .elementAt(index))); diff --git a/lib/presentation/login/login_screen.dart b/lib/presentation/login/login_screen.dart index aa7747c0..5ec247ef 100644 --- a/lib/presentation/login/login_screen.dart +++ b/lib/presentation/login/login_screen.dart @@ -118,13 +118,13 @@ class LoginScreen extends StatelessWidget { ), suffixIcon: IconButton( onPressed: () { - BlocProvider.of(context).add( - ToggleObscureCreatePassword( - showPassword: !state.showPassword, - showConfirmPassword: - state.showConfirmPassword, - ), - ); + context.read().add( + ToggleObscureCreatePassword( + showPassword: !state.showPassword, + showConfirmPassword: + state.showConfirmPassword, + ), + ); }, icon: state.showPassword ? const Icon(Icons.visibility, @@ -155,13 +155,13 @@ class LoginScreen extends StatelessWidget { ), suffixIcon: IconButton( onPressed: () { - BlocProvider.of(context).add( - ToggleObscureCreatePassword( - showPassword: state.showPassword, - showConfirmPassword: - !state.showConfirmPassword, - ), - ); + context.read().add( + ToggleObscureCreatePassword( + showPassword: state.showPassword, + showConfirmPassword: + !state.showConfirmPassword, + ), + ); }, icon: state.showConfirmPassword ? const Icon(Icons.visibility, @@ -235,9 +235,9 @@ class LoginScreen extends StatelessWidget { suffixIcon: state is EnterPassword ? IconButton( onPressed: () { - BlocProvider.of(context).add( - ShowPasswordPressed(), - ); + context.read().add( + ShowPasswordPressed(), + ); }, icon: state.showPassword ? const Icon(Icons.visibility, From ad5a7c171a5faa4e80dcaddeb38f4f3e581ecb68 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Wed, 3 Jan 2024 20:32:15 +0530 Subject: [PATCH 10/13] chore: changes Navigator.pop(ctx) to ctx.router.pop() --- lib/presentation/profile/profile_view.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 7e461d13..ecc3ee84 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -124,13 +124,13 @@ class ProfileScreen extends StatelessWidget { ProfilePageBloc>() .add( const DeleteHostelChangeRequest()); - Navigator.pop(ctx); + ctx.router.pop(); }, child: const Text('Delete'), ), TextButton( onPressed: () => - Navigator.pop(ctx), + ctx.router.pop(), child: const Text('Cancel'), ) ], From ed3d0a926dd8b0398819ae645f0b39820fdc3b4e Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Wed, 10 Apr 2024 23:00:50 +0530 Subject: [PATCH 11/13] conf: bump dependencies --- pubspec.lock | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index ce024ffd..77ea45e6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -701,6 +701,30 @@ packages: url: "https://pub.dev" source: hosted version: "6.7.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -721,26 +745,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: @@ -801,10 +825,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -1266,6 +1290,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: From a692060f241f27e2e2c6f7a5b972b30803ee4a5d Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Wed, 10 Apr 2024 23:03:59 +0530 Subject: [PATCH 12/13] rfac: links hostel change to backend --- .../models/hostel_change_request/hostel_change_request.dart | 2 +- lib/presentation/profile/bloc/profile_page_bloc.dart | 4 ++-- lib/presentation/profile/profile_view.dart | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/domain/models/hostel_change_request/hostel_change_request.dart b/lib/domain/models/hostel_change_request/hostel_change_request.dart index faf7c62c..bd21df7a 100644 --- a/lib/domain/models/hostel_change_request/hostel_change_request.dart +++ b/lib/domain/models/hostel_change_request/hostel_change_request.dart @@ -11,7 +11,7 @@ class HostelChangeRequest with _$HostelChangeRequest { required int id, required String hostelCode, required String newRoomNo, - bool? isApproved, + bool? isApprovedByAdmin, required String timestamp, required int newHostel}) = _HostelChangeRequest; diff --git a/lib/presentation/profile/bloc/profile_page_bloc.dart b/lib/presentation/profile/bloc/profile_page_bloc.dart index ca9efcf9..8f1a87ea 100644 --- a/lib/presentation/profile/bloc/profile_page_bloc.dart +++ b/lib/presentation/profile/bloc/profile_page_bloc.dart @@ -40,7 +40,7 @@ class ProfilePageBloc extends Bloc { newRoomNo: "", timestamp: "", newHostel: 0, - isApproved: null), + isApprovedByAdmin: null), ), ); } @@ -61,7 +61,7 @@ class ProfilePageBloc extends Bloc { newRoomNo: "", timestamp: "", newHostel: 0, - isApproved: null), + isApprovedByAdmin: null), ), ); } diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 854cbdac..59176ea3 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -93,7 +93,7 @@ class ProfileScreen extends StatelessWidget { ], ), 10.toVerticalSizedBox, - if (state.hostelChangeStatus.isApproved == null) + if (state.hostelChangeStatus.isApprovedByAdmin == null) ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { @@ -102,7 +102,7 @@ class ProfileScreen extends StatelessWidget { horizontalPadding: 50, width: 248, ), - if (state.hostelChangeStatus.isApproved != null) + if (state.hostelChangeStatus.isApprovedByAdmin != null) TextButton( onPressed: () => { showDialog( @@ -170,7 +170,7 @@ class ProfileScreen extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - "Status: Pending", + "Status: ${state.hostelChangeStatus.isApprovedByAdmin! ? 'Approved by Admin' : 'Pending'}", textAlign: TextAlign.justify, style: TextStyle( color: const Color(0xFF2F2F2F), From 2dc9e43d05273a03424c55dd2353fab2545d76c3 Mon Sep 17 00:00:00 2001 From: Aayushmaan Date: Wed, 10 Apr 2024 23:33:11 +0530 Subject: [PATCH 13/13] fix: fixes error handling for delete requests --- .../profile/bloc/profile_page_bloc.dart | 44 +++++++++++++------ .../profile/bloc/profile_page_state.dart | 2 +- lib/presentation/profile/profile_view.dart | 8 +++- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/lib/presentation/profile/bloc/profile_page_bloc.dart b/lib/presentation/profile/bloc/profile_page_bloc.dart index 8f1a87ea..5b1ba1fe 100644 --- a/lib/presentation/profile/bloc/profile_page_bloc.dart +++ b/lib/presentation/profile/bloc/profile_page_bloc.dart @@ -50,19 +50,35 @@ class ProfilePageBloc extends Bloc { DeleteHostelChangeRequest event, Emitter emit) async { emit(const ProfilePageInitialState()); User user = await repo.getCurrentUser(); - await repo.deleteChangeHostel(); - emit( - ProfilePageFetchedState( - user: user, - hostelChangeStatus: const HostelChangeRequest( - user: 0, - id: 0, - hostelCode: "", - newRoomNo: "", - timestamp: "", - newHostel: 0, - isApprovedByAdmin: null), - ), - ); + try { + await repo.deleteChangeHostel(); + emit( + ProfilePageFetchedState( + user: user, + hostelChangeStatus: const HostelChangeRequest( + user: 0, + id: 0, + hostelCode: "", + newRoomNo: "", + timestamp: "", + newHostel: 0, + isApprovedByAdmin: null), + ), + ); + } catch (e) { + emit( + ProfilePageFetchedState( + user: user, + hostelChangeStatus: const HostelChangeRequest( + user: 0, + id: 0, + hostelCode: "", + newRoomNo: "", + timestamp: "", + newHostel: 0, + isApprovedByAdmin: null), + ), + ); + } } } diff --git a/lib/presentation/profile/bloc/profile_page_state.dart b/lib/presentation/profile/bloc/profile_page_state.dart index 6c20137a..471b461f 100644 --- a/lib/presentation/profile/bloc/profile_page_state.dart +++ b/lib/presentation/profile/bloc/profile_page_state.dart @@ -21,7 +21,7 @@ class ProfilePageFetchedState extends ProfilePageState { }); final User user; - final dynamic hostelChangeStatus; + final HostelChangeRequest hostelChangeStatus; @override List get props => [user, hostelChangeStatus]; diff --git a/lib/presentation/profile/profile_view.dart b/lib/presentation/profile/profile_view.dart index 59176ea3..a36563d5 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -93,7 +93,9 @@ class ProfileScreen extends StatelessWidget { ], ), 10.toVerticalSizedBox, - if (state.hostelChangeStatus.isApprovedByAdmin == null) + if (state + .hostelChangeStatus.isApprovedByAdmin == + null) ProfileTextButton( title: 'Request for Hostel Change', onPressed: () { @@ -102,7 +104,9 @@ class ProfileScreen extends StatelessWidget { horizontalPadding: 50, width: 248, ), - if (state.hostelChangeStatus.isApprovedByAdmin != null) + if (state + .hostelChangeStatus.isApprovedByAdmin != + null) TextButton( onPressed: () => { showDialog(