Created
March 18, 2022 17:04
-
-
Save mondoktamas/e24699d7bc30b4df0567f14798d2aa36 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:math'; | |
import 'package:auto_route/auto_route.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | |
import 'package:sas/application/di/injection.dart'; | |
import 'package:sas/application/domain/entity/initiate_api/passenger_entity.dart'; | |
import 'package:sas/application/domain/entity/traveler/selected_travelers_entity.dart'; | |
import 'package:sas/application/domain/entity/traveler/traveler_entity.dart'; | |
import 'package:sas/application/presentation/features/main/features/book/cubit/select_traveler_cubit/select_travelers_cubit.dart'; | |
import 'package:sas/application/presentation/features/main/features/book/widgets/user_icon_widget.dart'; | |
import 'package:sas/application/presentation/resources/colors.dart'; | |
import 'package:sas/application/presentation/router/router.gr.dart'; | |
import 'package:sas/application/presentation/widgets/button/close_button_for_bottom_sheet.dart'; | |
import 'package:sas/application/presentation/widgets/expansion_container.dart'; | |
import 'package:sas/application/presentation/widgets/ink_button_widget.dart'; | |
class SelectTravelersBottomSheet extends StatelessWidget with AutoRouteWrapper { | |
const SelectTravelersBottomSheet( | |
this._numberOfTravelersModel, { | |
final Key? key, | |
}) : super(key: key); | |
final SelectedTravelersEntity _numberOfTravelersModel; | |
@override | |
Widget wrappedRoute(final BuildContext context) => BlocProvider<SelectTravelersCubit>( | |
create: (_) => getIt<SelectTravelersCubit>()..initSelectTravelerBloc(_numberOfTravelersModel), | |
child: ClipRRect( | |
borderRadius: const BorderRadius.only( | |
topLeft: Radius.circular(18), | |
topRight: Radius.circular(18), | |
), | |
child: ColoredBox( | |
color: cffF8F6F6, | |
child: this, | |
), | |
), | |
); | |
@override | |
Widget build(final BuildContext context) => Stack( | |
children: [ | |
SingleChildScrollView( | |
physics: const ClampingScrollPhysics(), | |
padding: EdgeInsets.only(bottom: 64 + max(16, MediaQuery.of(context).viewPadding.bottom)), | |
child: Column( | |
children: [ | |
const _SelectTravelersHeader(), | |
Divider( | |
height: 1, | |
color: darkGrey.withOpacity(0.30), | |
), | |
const _SavedTravelers(), | |
Divider( | |
height: 1, | |
color: darkGrey.withOpacity(0.30), | |
), | |
Column( | |
children: const [ | |
SizedBox( | |
height: 36, | |
), | |
_AdultAndChildrenSelector(), | |
SizedBox( | |
height: 16, | |
), | |
_YouthSelector(), | |
SizedBox( | |
height: 32, | |
), | |
], | |
), | |
], | |
), | |
), | |
Positioned( | |
bottom: max(16.0, MediaQuery.of(context).viewPadding.bottom), | |
left: 20.0, | |
right: 20.0, | |
child: InkButtonWidget( | |
onTap: () => context.router.pop(context.read<SelectTravelersCubit>().state.getNumberOfTravelersModel), | |
backgroundColor: buttonColor, | |
borderRadius: 4, | |
padding: 18, | |
child: Text( | |
AppLocalizations.of(context)!.select, | |
textAlign: TextAlign.center, | |
style: Theme.of(context).textTheme.button!.copyWith( | |
color: accentColor, | |
fontSize: 18, | |
), | |
), | |
), | |
), | |
], | |
); | |
} | |
class _SelectTravelersHeader extends StatelessWidget { | |
const _SelectTravelersHeader({final Key? key}) : super(key: key); | |
@override | |
Widget build(final BuildContext context) => Container( | |
color: white, | |
padding: const EdgeInsets.fromLTRB(26, 30, 26, 26), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: [ | |
Text( | |
AppLocalizations.of(context)!.who_is_traveling, | |
style: Theme.of(context).textTheme.headline6!.copyWith( | |
color: dark, | |
fontSize: 18, | |
height: 24 / 18, | |
), | |
), | |
const CloseButtonForBottomSheet(), | |
], | |
), | |
); | |
} | |
class _AdultAndChildrenSelector extends StatelessWidget { | |
const _AdultAndChildrenSelector({final Key? key}) : super(key: key); | |
@override | |
Widget build(final BuildContext context) => Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 20), | |
child: BlocBuilder<SelectTravelersCubit, SelectTravelersState>( | |
builder: (context, state) => Container( | |
decoration: BoxDecoration( | |
color: white, | |
borderRadius: BorderRadius.circular(5), | |
boxShadow: const [ | |
tabBoxShadow, | |
], | |
), | |
child: ClipRRect( | |
borderRadius: BorderRadius.circular(5), | |
child: ExpansionContainer( | |
isExpanded: state.adultCategoryExpanded, | |
onExpansionChanged: context.read<SelectTravelersCubit>().onAdultCategoryExpanded, | |
showChildrenDivider: false, | |
childrenPadding: const EdgeInsets.only( | |
top: 21.5, | |
left: 21, | |
bottom: 16, | |
right: 14.5, | |
), | |
title: state.adultCategoryExpanded | |
? null | |
: Padding( | |
padding: const EdgeInsets.only( | |
top: 18, | |
bottom: 17, | |
left: 21, | |
), | |
child: Text( | |
AppLocalizations.of(context)!.adult_children_title, | |
style: Theme.of(context).textTheme.subtitle2!.copyWith(color: darkGrey), | |
), | |
), | |
children: [ | |
_TravelerItem( | |
title: AppLocalizations.of(context)!.adults, | |
bodyText: AppLocalizations.of(context)!.adults_conditions, | |
value: state.adults, | |
isIncrement: state.isIncrementAdults, | |
isDecrement: state.isDecrementAdults, | |
travelerType: TravelerType.ADT, | |
), | |
const SizedBox(height: 18), | |
_TravelerItem( | |
title: AppLocalizations.of(context)!.children, | |
bodyText: AppLocalizations.of(context)!.children_conditions, | |
value: state.children, | |
isIncrement: state.isIncrementChildren, | |
isDecrement: state.isDecrementChildren, | |
travelerType: TravelerType.CHD, | |
), | |
const SizedBox(height: 18), | |
_TravelerItem( | |
title: AppLocalizations.of(context)!.infants, | |
bodyText: AppLocalizations.of(context)!.infants_conditions, | |
value: state.infants, | |
isIncrement: state.isIncrementInfants, | |
isDecrement: state.isDecrementInfants, | |
travelerType: TravelerType.INF, | |
), | |
], | |
), | |
), | |
), | |
), | |
); | |
} | |
class _YouthSelector extends StatelessWidget { | |
const _YouthSelector({final Key? key}) : super(key: key); | |
@override | |
Widget build(final BuildContext context) => Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 20), | |
child: BlocBuilder<SelectTravelersCubit, SelectTravelersState>( | |
builder: (context, state) => Container( | |
decoration: BoxDecoration( | |
color: white, | |
borderRadius: BorderRadius.circular(5), | |
boxShadow: const [ | |
tabBoxShadow, | |
], | |
), | |
child: ClipRRect( | |
borderRadius: BorderRadius.circular(5), | |
child: ExpansionContainer( | |
childrenPadding: const EdgeInsets.only( | |
top: 21.5, | |
left: 21, | |
bottom: 16, | |
right: 14.5, | |
), | |
isExpanded: state.youthCategoryExpanded, | |
onExpansionChanged: context.read<SelectTravelersCubit>().onYouthCategoryExpanded, | |
showChildrenDivider: false, | |
title: state.youthCategoryExpanded | |
? null | |
: Padding( | |
padding: const EdgeInsets.only( | |
top: 18, | |
bottom: 17, | |
left: 21, | |
), | |
child: Text( | |
AppLocalizations.of(context)!.youth_tickets_title, | |
style: Theme.of(context).textTheme.subtitle2!.copyWith(color: darkGrey), | |
), | |
), | |
children: [ | |
_TravelerItem( | |
title: AppLocalizations.of(context)!.youths, | |
bodyText: AppLocalizations.of(context)!.youth_conditions, | |
value: state.youths, | |
isIncrement: state.isIncrementYouth, | |
isDecrement: state.isDecrementYouth, | |
travelerType: TravelerType.YTH, | |
), | |
const SizedBox( | |
height: 24, | |
), | |
Container( | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.circular(5), | |
color: lightBlue4, | |
), | |
padding: const EdgeInsets.symmetric( | |
vertical: 10.5, | |
horizontal: 24, | |
), | |
child: Text( | |
AppLocalizations.of(context)!.youth_ticket_booking_note, | |
style: Theme.of(context).textTheme.bodyText1!.copyWith( | |
height: 18 / 14, | |
), | |
), | |
), | |
], | |
), | |
), | |
), | |
), | |
); | |
} | |
class _SavedTravelers extends StatelessWidget { | |
const _SavedTravelers({ | |
final Key? key, | |
}) : super(key: key); | |
Future<void> _openNewTravelerBottomSheet(final BuildContext context) async { | |
final bloc = context.read<SelectTravelersCubit>(); | |
final result = await context.router.push(AddAndEditTravelerRoute()); | |
if (result != null && result is bool) { | |
if (result) await bloc.loadSavedTravelers(); | |
} | |
} | |
@override | |
Widget build(final BuildContext context) => Container( | |
color: white, | |
padding: const EdgeInsets.only(top: 17, bottom: 26), | |
child: Column( | |
children: [ | |
Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 27), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: [ | |
Text( | |
AppLocalizations.of(context)!.saved_travelers, | |
style: Theme.of(context).textTheme.headline5, | |
), | |
InkButtonWidget( | |
onTap: () => _openNewTravelerBottomSheet(context), | |
padding: 5, | |
child: Row( | |
children: [ | |
const Padding( | |
padding: EdgeInsets.only(top: 3), | |
child: Icon( | |
Icons.add_outlined, | |
color: dark, | |
size: 19, | |
), | |
), | |
Text( | |
AppLocalizations.of(context)!.add, | |
style: Theme.of(context).textTheme.subtitle1!.copyWith(height: 20 / 14), | |
), | |
], | |
), | |
), | |
], | |
), | |
), | |
BlocBuilder<SelectTravelersCubit, SelectTravelersState>( | |
builder: (context, state) => state.savedTravelers.isEmpty | |
? const SizedBox.shrink() | |
: Container( | |
margin: const EdgeInsets.only(top: 34), | |
height: 103, | |
child: ListView.builder( | |
scrollDirection: Axis.horizontal, | |
padding: const EdgeInsets.only(right: 21), | |
shrinkWrap: true, | |
itemCount: state.savedTravelers.length, | |
itemBuilder: (context, index) { | |
var isIncrement = state.isIncrementAdults; | |
var isDecrement = state.isDecrementAdults; | |
switch (state.savedTravelers[index].travelerType) { | |
case TravelerType.ADT: | |
isIncrement = state.isIncrementAdults; | |
isDecrement = state.isDecrementAdults; | |
break; | |
case TravelerType.CHD: | |
isIncrement = state.isIncrementChildren; | |
isDecrement = state.isDecrementChildren; | |
break; | |
case TravelerType.INF: | |
isIncrement = state.isIncrementInfants; | |
isDecrement = state.isDecrementInfants; | |
break; | |
case TravelerType.YTH: | |
isIncrement = state.isIncrementYouth; | |
isDecrement = state.isDecrementYouth; | |
break; | |
} | |
return _SavedTravelerItem( | |
traveler: state.savedTravelers[index], | |
isSelected: state.selectedSavedTravelers.contains(state.savedTravelers[index]), | |
isIncrement: isIncrement, | |
isDecrement: isDecrement, | |
); | |
}, | |
), | |
), | |
), | |
], | |
), | |
); | |
} | |
class _SavedTravelerItem extends StatelessWidget { | |
const _SavedTravelerItem({ | |
Key? key, | |
required this.traveler, | |
required this.isSelected, | |
required this.isIncrement, | |
required this.isDecrement, | |
}) : super(key: key); | |
final TravelerEntity traveler; | |
final bool isSelected; | |
final bool isIncrement; | |
final bool isDecrement; | |
@override | |
Widget build(BuildContext context) => Padding( | |
padding: const EdgeInsets.only(left: 27), | |
child: InkButtonWidget( | |
onTap: () { | |
if (isSelected) { | |
if (isDecrement) { | |
context.read<SelectTravelersCubit>().removeFromSelectedSavedTraveler(traveler); | |
} | |
} else { | |
if (isIncrement) { | |
context.read<SelectTravelersCubit>().addToSelectedSavedTraveler(traveler); | |
} | |
} | |
}, | |
borderRadius: 10, | |
width: 87, | |
child: Column( | |
children: [ | |
UserIconWidget( | |
isSelected: isSelected, | |
userInitials: traveler.initials, | |
), | |
Padding( | |
padding: const EdgeInsets.only(top: 7), | |
child: Text( | |
traveler.isMe | |
? AppLocalizations.of(context)!.me_capital_case_with_name(traveler.shortName) | |
: traveler.shortName, | |
maxLines: 1, | |
style: Theme.of(context).textTheme.subtitle2, | |
overflow: TextOverflow.ellipsis, | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
class _TravelerItem extends StatelessWidget { | |
const _TravelerItem({ | |
Key? key, | |
required this.title, | |
required this.bodyText, | |
required this.value, | |
required this.travelerType, | |
required this.isIncrement, | |
required this.isDecrement, | |
}) : super(key: key); | |
final String title; | |
final String bodyText; | |
final int value; | |
final bool isIncrement; | |
final bool isDecrement; | |
final TravelerType travelerType; | |
@override | |
Widget build(BuildContext context) => Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: [ | |
Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
title, | |
style: Theme.of(context).textTheme.headline6!.copyWith( | |
color: dark, | |
fontSize: 16, | |
height: 20 / 18, | |
), | |
), | |
const SizedBox(height: 4), | |
Text( | |
bodyText, | |
style: Theme.of(context).textTheme.subtitle1!.copyWith(height: 18 / 14), | |
), | |
], | |
), | |
Row( | |
children: [ | |
IconButton( | |
icon: Icon( | |
Icons.remove_circle, | |
color: !isDecrement ? grey4 : daysColor, | |
), | |
splashRadius: 20, | |
iconSize: 25, | |
onPressed: | |
!isDecrement ? null : () => context.read<SelectTravelersCubit>().removeTraveler(travelerType), | |
padding: EdgeInsets.zero, | |
constraints: const BoxConstraints(), | |
), | |
Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 17), | |
child: Text( | |
value.toString(), | |
style: Theme.of(context).textTheme.headline6!.copyWith( | |
color: dark, | |
fontSize: 16, | |
height: 20 / 16, | |
), | |
), | |
), | |
IconButton( | |
icon: Icon( | |
Icons.add_circle, | |
color: !isIncrement ? grey4 : daysColor, | |
), | |
splashRadius: 20, | |
iconSize: 25, | |
onPressed: !isIncrement ? null : () => context.read<SelectTravelersCubit>().addTraveler(travelerType), | |
padding: EdgeInsets.zero, | |
constraints: const BoxConstraints(), | |
), | |
], | |
), | |
], | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment