Files
CityCards_Partner_Flutter/lib/booking/views/booking_bottom_sheet.dart
2025-10-29 18:55:48 +05:30

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),
),
),
],
),
);
}
}