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/core/router/registry/paths.dart b/lib/data/core/router/registry/paths.dart index 945c7173..76a232ca 100644 --- a/lib/data/core/router/registry/paths.dart +++ b/lib/data/core/router/registry/paths.dart @@ -16,6 +16,7 @@ class AppPathsRegistry { static const String weekMenu = 'weekMenu'; static const String leavesAndRebate = 'leavesAndRebate'; static const String feedback = 'feedback'; + static const String hostelChange = 'hostelChange'; static const String resetPassword = 'resetPassword'; static const String noInternetWrapper = '/noInternetWrapper'; diff --git a/lib/data/core/router/registry/routes.dart b/lib/data/core/router/registry/routes.dart index 28650b51..bbb81936 100644 --- a/lib/data/core/router/registry/routes.dart +++ b/lib/data/core/router/registry/routes.dart @@ -59,6 +59,10 @@ class AppRoutesRegistry { path: AppPathsRegistry.resetPassword, page: ResetPasswordRoute.page, ), + CustomRoute( + path: AppPathsRegistry.hostelChange, + page: HostelChangeRoute.page, + ), ], ), CustomRoute( diff --git a/lib/data/services/remote/api_service.dart b/lib/data/services/remote/api_service.dart index e3e1f262..99762b5e 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'; @@ -181,4 +182,15 @@ abstract class ApiService { @GET(ApiEndpoints.notifications) Future getNotifications(); + + @POST(ApiEndpoints.hostelChange) + Future postChangeHostel( + @Body() Map map, + ); + + @GET(ApiEndpoints.hostelChange) + 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..bd21df7a --- /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? isApprovedByAdmin, + required String timestamp, + required int newHostel}) = _HostelChangeRequest; + + factory HostelChangeRequest.fromJson(Map json) => + _$HostelChangeRequestFromJson(json); +} diff --git a/lib/domain/repositories/user/user_repository.dart b/lib/domain/repositories/user/user_repository.dart index a56e2bcd..a68fd080 100644 --- a/lib/domain/repositories/user/user_repository.dart +++ b/lib/domain/repositories/user/user_repository.dart @@ -154,4 +154,35 @@ class UserRepository { throw Failure(AppConstants.GENERIC_FAILURE); } } + + Future postChangeHostel(String hostelCode, String roomNo) async { + Map map = { + 'new_hostel_code': hostelCode, + 'new_room_no': roomNo + }; + try { + return await _apiService.postChangeHostel(map); + } catch (e) { + debugPrint(e.toString()); + throw Failure(AppConstants.GENERIC_FAILURE); + } + } + + Future getHostelChangeStatus() async { + try { + return await _apiService.getHostelChangeStatus(); + } catch (e) { + debugPrint(e.toString()); + 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/bloc/hostel_change_bloc.dart b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart new file mode 100644 index 00000000..b27376d1 --- /dev/null +++ b/lib/presentation/hostel_change/bloc/hostel_change_bloc.dart @@ -0,0 +1,50 @@ +import 'dart:async'; + +import 'package:appetizer/data/constants/constants.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()); + 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, roomNo); + 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..2c49513b --- /dev/null +++ b/lib/presentation/hostel_change/bloc/hostel_change_event.dart @@ -0,0 +1,19 @@ +part of 'hostel_change_bloc.dart'; + +abstract class HostelChangeEvent {} + +class HostelChangePressed extends HostelChangeEvent { + final String hostel; + final String roomNo; + HostelChangePressed({ + required this.hostel, + required this.roomNo, + }); +} + +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..d019b038 --- /dev/null +++ b/lib/presentation/hostel_change/bloc/hostel_change_state.dart @@ -0,0 +1,22 @@ +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/components/hostel_change_banner.dart b/lib/presentation/hostel_change/components/hostel_change_banner.dart new file mode 100644 index 00000000..c8347410 --- /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..77e9c0bc --- /dev/null +++ b/lib/presentation/hostel_change/hostel_change_screen.dart @@ -0,0 +1,291 @@ +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'; +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: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 + Widget build(BuildContext context) { + 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: SingleChildScrollView( + child: Column( + children: [ + const HostelChangeBanner(), + 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, + ), + ], + ), + child: Column( + children: [ + TextField( + controller: _searchController, + onChanged: (value) { + context.read().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, + )), + ), + 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); + context.read().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); + context + .read() + .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, + ), + 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(); + } + return Container(); + }, + ), + ) + ], + ), + )); + } +} diff --git a/lib/presentation/profile/bloc/profile_page_bloc.dart b/lib/presentation/profile/bloc/profile_page_bloc.dart index acef94ea..5b1ba1fe 100644 --- a/lib/presentation/profile/bloc/profile_page_bloc.dart +++ b/lib/presentation/profile/bloc/profile_page_bloc.dart @@ -1,3 +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'; @@ -11,13 +14,71 @@ 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(); - emit( - ProfilePageFetchedState(user: user), - ); + try { + HostelChangeRequest hostelChangeStatus = + await repo.getHostelChangeStatus(); + emit( + ProfilePageFetchedState( + user: user, + hostelChangeStatus: hostelChangeStatus, + ), + ); + } catch (e) { + emit( + ProfilePageFetchedState( + user: user, + hostelChangeStatus: const HostelChangeRequest( + user: 0, + id: 0, + hostelCode: "", + newRoomNo: "", + timestamp: "", + newHostel: 0, + isApprovedByAdmin: null), + ), + ); + } + } + + FutureOr _onDeleteHostelChangeRequest( + DeleteHostelChangeRequest event, Emitter emit) async { + emit(const ProfilePageInitialState()); + User user = await repo.getCurrentUser(); + 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_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/bloc/profile_page_state.dart b/lib/presentation/profile/bloc/profile_page_state.dart index c54f1356..471b461f 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 HostelChangeRequest hostelChangeStatus; @override - List get props => [user]; + List get props => [user, hostelChangeStatus]; } 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 8b825e90..a36563d5 100644 --- a/lib/presentation/profile/profile_view.dart +++ b/lib/presentation/profile/profile_view.dart @@ -57,31 +57,136 @@ 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, + // horizontal: 43.toAutoScaledWidth, + ), + child: Column( children: [ - ProfileTextButton( - title: 'Edit Profile', - onPressed: () { - const snackBar = SnackBar( - content: Text('Coming soon!'), - duration: Duration(milliseconds: 500), - ); - ScaffoldMessenger.of(context) - .showSnackBar(snackBar); - }, - ), - 10.toHorizontalSizedBox, - ProfileTextButton( - title: 'Reset Password', - onPressed: () { - context.router.push(ResetPasswordRoute()); - }, + 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: 10, + width: 115, + ), + // 5.toHorizontalSizedBox, + ProfileTextButton( + title: 'Reset Password', + onPressed: () { + context.router + .push(ResetPasswordRoute()); + }, + horizontalPadding: 10, + width: 115, + ), + ], ), + 10.toVerticalSizedBox, + if (state + .hostelChangeStatus.isApprovedByAdmin == + null) + ProfileTextButton( + title: 'Request for Hostel Change', + onPressed: () { + context.router.push(HostelChangeRoute()); + }, + horizontalPadding: 50, + width: 248, + ), + if (state + .hostelChangeStatus.isApprovedByAdmin != + 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()); + ctx.router.pop(); + }, + child: const Text('Delete'), + ), + TextButton( + onPressed: () => + ctx.router.pop(), + 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.hostelCode}", + style: TextStyle( + color: const Color(0xFF111111), + fontSize: 13.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), + ), + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + "New Room No: ${state.hostelChangeStatus.newRoomNo}", + textAlign: TextAlign.justify, + style: TextStyle( + color: const Color(0xFF2F2F2F), + fontSize: 12.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), + ), + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + "Status: ${state.hostelChangeStatus.isApprovedByAdmin! ? 'Approved by Admin' : 'Pending'}", + textAlign: TextAlign.justify, + style: TextStyle( + color: const Color(0xFF2F2F2F), + fontSize: 12.toAutoScaledFont, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + ), + ), + ), + ]), + ), + ) ], ), ), @@ -136,7 +241,6 @@ class ProfileScreen extends StatelessWidget { ], ); } - return SizedBox( height: 200.toAutoScaledHeight, child: const Align(