215 lines
9.4 KiB
Dart
215 lines
9.4 KiB
Dart
import 'package:citycards_partner_flutter/core/app_router.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:intl/intl.dart';
|
|
import '../models/booking_model.dart';
|
|
import '../blocs/booking_bloc.dart';
|
|
|
|
class BookingBottomSheet extends StatelessWidget {
|
|
final DateTime date;
|
|
final BookingDay booking;
|
|
|
|
const BookingBottomSheet({
|
|
super.key,
|
|
required this.date,
|
|
required this.booking,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final bloc = context.read<BookingBloc>();
|
|
final formattedDate = DateFormat('EEEE, MMMM d, yyyy').format(date);
|
|
return DraggableScrollableSheet(
|
|
expand: false,
|
|
initialChildSize: 0.6,
|
|
minChildSize: 0.6,
|
|
maxChildSize: 0.6,
|
|
builder: (context, scrollController) {
|
|
return BlocBuilder<BookingBloc, BookingState>(
|
|
builder: (context, state) {
|
|
return Container(
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
|
),
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
formattedDate,
|
|
style: GoogleFonts.poppins(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
Text(
|
|
"${booking.attractions.length} attractions available",
|
|
style: GoogleFonts.poppins(color: Colors.black54),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Expanded(
|
|
child: RawScrollbar(
|
|
thumbColor: Color(0xffF95F62),
|
|
trackColor: Color(0xffF9E7E1),
|
|
thumbVisibility: true,
|
|
trackVisibility: true,
|
|
thickness: 10,
|
|
radius: const Radius.circular(8),
|
|
interactive: true,
|
|
// thumbColor: const MaterialStatePropertyAll(Color(0xffF95F62)),
|
|
controller: scrollController,
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(right: 20),
|
|
child: ListView.builder(
|
|
controller: scrollController,
|
|
itemCount: booking.attractions.length,
|
|
itemBuilder: (context, index) {
|
|
final attraction = booking.attractions[index];
|
|
final isExpanded = state.expandedAttractions
|
|
.contains(index);
|
|
return InkWell(
|
|
onTap: (){
|
|
Navigator.pushNamed(context, AppRouter.selectedTimeSlotPage);
|
|
},
|
|
child: Container(
|
|
margin: const EdgeInsets.only(bottom: 12),
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Color(
|
|
int.parse(
|
|
"0x22${attraction.colorHex.substring(1)}",
|
|
),
|
|
),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Container(
|
|
width: 10,
|
|
height: 10,
|
|
decoration: BoxDecoration(
|
|
color: Color(
|
|
int.parse(
|
|
"0xff${attraction.colorHex.substring(1)}",
|
|
),
|
|
),
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
attraction.name,
|
|
style: GoogleFonts.poppins(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 13,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Icon(
|
|
Icons.arrow_forward_ios,
|
|
size: 14,
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Wrap(
|
|
spacing: 6,
|
|
runSpacing: 6,
|
|
children: List.generate(
|
|
isExpanded
|
|
? attraction.slots.length
|
|
: (attraction.slots.length > 2
|
|
? 2
|
|
: attraction.slots.length),
|
|
(i) => _slotCard(attraction.slots[i]),
|
|
),
|
|
),
|
|
if (attraction.slots.length > 2)
|
|
GestureDetector(
|
|
onTap: () =>
|
|
bloc.add(ToggleSlotExpand(index)),
|
|
child: Container(
|
|
margin: const EdgeInsets.only(top: 8),
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 12,
|
|
vertical: 4,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade200,
|
|
borderRadius: BorderRadius.circular(
|
|
8,
|
|
),
|
|
),
|
|
child: Text(
|
|
isExpanded
|
|
? "Show less"
|
|
: "+${attraction.slots.length - 2} more",
|
|
style: GoogleFonts.poppins(
|
|
color: Colors.black54,
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _slotCard(TimeSlot slot) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
slot.time,
|
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
|
|
),
|
|
const SizedBox(width: 6),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade200,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
child: Text(
|
|
"${slot.booked}/${slot.total}",
|
|
style: GoogleFonts.poppins(fontSize: 11, color: Colors.black87),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|