import 'package:comwell_key_app/presentation/screens/booking_details/bloc/booking_details_cubit.dart';
import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/overview/models/guest.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/presentation/screens/booking_details/components/guest_list.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:comwell_key_app/utils/l10n_utils.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:comwell_key_app/utils/share_button_utils.dart';
import 'package:comwell_key_app/share/cubit/share_booking_cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
class ShareButton extends StatelessWidget {
final List<Guest> guests;
final Color? buttonColor;
final double userButtonSize;
final double userButtonOverlap;
final bool isMyBooking;
const ShareButton({
super.key,
required this.guests,
this.buttonColor,
this.userButtonSize = 45,
this.userButtonOverlap = 10,
this.isMyBooking = false,
});
@override
Widget build(BuildContext context) {
final cubit = context.read<BookingDetailsCubit>();
final booking = cubit.booking;
final numberOfUsers = guests.length;
final allInitials = generateInitials(guests);
return Stack(
key: Key(guests.length.toString()),
children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: EdgeInsets.only(left: isMyBooking ? 40 : 16.0, top: isMyBooking ? 24 : 16),
child: Stack(
children: [
Positioned(
left:
(numberOfUsers - 1) * (userButtonSize - userButtonOverlap) +
userButtonSize -
userButtonOverlap,
child: SizedBox(
width: userButtonSize,
height: userButtonSize,
child: ElevatedButton(
onPressed: () {
context.push(AppRoutes.shareBooking, extra: booking);
},
style: ElevatedButton.styleFrom(
backgroundColor: buttonColor ?? sandColor[10],
elevation: 0,
shape: const CircleBorder(),
padding: EdgeInsets.zero,
),
child: Center(
child: Icon(
Icons.add,
color: colorHeadlineText,
size: isMyBooking ? 20 : 30,
),
),
),
),
),
...List.generate(
numberOfUsers,
(index) => Positioned(
left: (numberOfUsers - 1 - index) * (userButtonSize - userButtonOverlap),
child: SizedBox(
width: userButtonSize,
height: userButtonSize,
child: ElevatedButton(
onPressed: () async {
if (isMyBooking) {
return;
}
final results = await _showGuestList(
context,
index,
guests,
booking,
);
if (results is List<String>) {
final updatedBooking = booking.updateGuests(results);
cubit.updateBooking(updatedBooking);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: index % 2 == 0 ? sandColor : colorTertiary,
elevation: 0,
shape: const CircleBorder(),
padding: EdgeInsets.zero,
),
child: Center(
child: Text(
allInitials.elementAt(index),
style: TextStyle(
color: colorBackground,
fontWeight: FontWeight.w400,
fontSize: isMyBooking ? 14 : 18,
),
),
),
),
),
),
),
],
),
),
),
],
);
}
Future<dynamic> _showGuestList(
BuildContext context,
int index,
List<Guest> guests,
Booking booking,
) async {
final theme = Theme.of(context);
final selectedGuests = guests.map((e) => e.id.toString()).toList();
return showModalBottomSheet<dynamic>(
context: context,
backgroundColor: colorBackground,
isScrollControlled: false,
builder: (BuildContext bottomSheetContext) {
return BlocProvider(
create: (context) => ShareBookingCubit(locator(), booking: booking),
child: BlocConsumer<ShareBookingCubit, ShareBookingState>(
listener: (context, state) {},
builder: (context, state) {
final cubit = context.read<ShareBookingCubit>();
return ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
child: Scaffold(
body: SizedBox(
width: double.infinity,
height: 450,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
context.strings.handle_guests_title,
style: theme.textTheme.titleLarge?.copyWith(
color: colorTertiary,
fontWeight: FontWeight.w600,
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: sandColor[40],
shape: const CircleBorder(),
elevation: 0,
minimumSize: const Size(40, 40),
),
child: const Icon(Icons.close, color: colorTertiary),
onPressed: () {
Navigator.pop(bottomSheetContext);
},
),
],
),
),
Builder(
builder: (context) {
if (state.isLoading) {
return const CircularProgressIndicator();
}
if (state.error != null) {
return ComwellErrorWidget(
title: context.strings.share_booking_error_title,
subtitle: context.strings.share_booking_error_subtitle,
border: true,
);
}
return Expanded(
child: GuestList(
guests: guests,
selectedGuests: selectedGuests,
onGuestSelected: (Iterable<String> newSelection) {
cubit.updateSelectedGuests(
newSelection.map(
(e) => Guest(
id: int.parse(e),
firstName: e.split(' ')[0],
lastName: e.split(' ')[1],
),
),
);
},
onGuestRemoved: (int guestId) {
cubit.removeGuests([guestId]);
},
),
);
},
),
],
),
),
bottomNavigationBar: state.error != null
? null
: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Divider(
height: 1,
color: Colors.grey.shade300,
),
Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
onPressed: state.selectedGuests.isNotEmpty
? () async {
final shouldRemove = await showDialog<bool>(
context: bottomSheetContext,
builder: (context) => _buildRemoveGuestDialog(
context,
cubit,
bottomSheetContext,
selectedGuests,
),
);
if (shouldRemove == true && context.mounted) {
context.pop(state.selectedGuests);
}
}
: null,
style: ElevatedButton.styleFrom(
backgroundColor: state.selectedGuests.isNotEmpty
? colorTertiary
: const Color(0xffE0E0E0),
minimumSize: const Size.fromHeight(50),
elevation: 0,
),
child: Text(
context.strings.cancel_sharing,
style: TextStyle(
color: state.selectedGuests.isNotEmpty
? colorBackground
: Colors.grey[500],
),
),
),
),
],
),
),
),
);
},
),
);
},
);
}
Widget _buildRemoveGuestDialog(
BuildContext context,
ShareBookingCubit cubit,
BuildContext bottomSheetContext,
Iterable<String> selectedGuests,
) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
contentPadding: const EdgeInsets.all(24.0),
backgroundColor: colorBackground,
title: Center(
child: Text(
context.strings.are_you_sure,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.strings.guest_removal_responsibility,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.grey[500],
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
Navigator.pop(bottomSheetContext, true);
},
style: ElevatedButton.styleFrom(
backgroundColor: colorBackground,
side: BorderSide(color: Colors.grey[300]!, width: 1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
elevation: 0,
padding: const EdgeInsets.symmetric(vertical: 16),
minimumSize: const Size.fromHeight(50),
),
child: Text(
selectedGuests.length > 1 ? context.strings.remove_guests : context.strings.remove_guest,
style: const TextStyle(
color: colorTertiary,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () {
Navigator.pop(bottomSheetContext, false);
},
style: ElevatedButton.styleFrom(
backgroundColor: sandColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
padding: const EdgeInsets.symmetric(vertical: 16),
minimumSize: const Size.fromHeight(50),
),
child: Text(
context.strings.cancel,
style: const TextStyle(
color: colorBackground,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
],
),
actions: const [],
);
}
}