Files
CityCards_Customer_Flutter/lib/checkout/widget/pass_purchase_details_bottomsheet.dart

299 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../add_details/add_details_view.dart';
import '../../profile/repository/profile_repository.dart';
import '../../profile/view/edit_profile/edit_profile_view.dart';
import '../bloc/pass_purchase_details_bloc.dart';
import '../bloc/pass_purchase_details_event.dart';
import '../bloc/pass_purchase_details_state.dart';
class PassPurchaseBottomSheet {
static Future<String?> show(BuildContext context, {required int bookingId}) async {
return await showModalBottomSheet<String>(
context: context,
isScrollControlled: true,
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (_) {
return BlocProvider(
create: (_) => PurchaseDetailsBloc()..add(LoadProfileEvent()),
child: _PassPurchaseContent(bookingId: bookingId),
);
},
);
}
static void close(BuildContext context) {
Navigator.of(context).pop();
}
}
class _PassPurchaseContent extends StatelessWidget {
final int bookingId;
const _PassPurchaseContent({required this.bookingId});
@override
Widget build(BuildContext context) {
return BlocConsumer<PurchaseDetailsBloc, PurchaseDetailsState>(
listener: (context, state) {
// Handle API submission success
if (state is PurchaseDetailsSubmitted) {
// Close bottom sheet and return success
Navigator.of(context).pop('success');
// Show success message
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text('Details submitted successfully!'),
// backgroundColor: Color(0xffF95F62),
// ),
// );
}
// Handle API submission error
if (state is PurchaseDetailsError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMessage ?? 'Failed to submit details'),
backgroundColor: Colors.red,
),
);
}
},
builder: (context, state) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
top: 16,
left: 16,
right: 16,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 45,
height: 5,
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(10),
),
),
const SizedBox(height: 12),
Text(
"Purchase Details",
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
),
const SizedBox(height: 24),
/// BUY FOR MYSELF
GestureDetector(
onTap: () {
context.read<PurchaseDetailsBloc>().add(ToggleGiftModeEvent(false));
context.read<PurchaseDetailsBloc>().add(SetPurchaseDetailsEvent("self"));
},
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: !state.isGift
? Border.all(color: const Color(0xffF95F62), width: 1.5)
: null,
),
child: Row(
children: [
Radio<bool>(
value: false,
groupValue: state.isGift,
onChanged: (_) {},
activeColor: const Color(0xffF95F62),
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Buy Pass for Myself",
style: TextStyle(
fontWeight: FontWeight.w600,
color: !state.isGift
? const Color(0xffF95F62)
: const Color(0xff9E9E9E),
),
),
if (!state.isGift && state.profile != null) ...[
const SizedBox(height: 8),
Text(
"${state.profile!.firstName} ${state.profile!.lastName}",
style: const TextStyle(
fontWeight: FontWeight.w500,
),
),
Text(
"${state.profile!.address1 ?? ""}\n${state.profile!.address2 ?? ""}",
style: const TextStyle(
fontSize: 13,
color: Color(0xff5E5E5E),
),
),
],
if (!state.isGift && state.isLoadingProfile) ...[
const SizedBox(height: 8),
const SizedBox(
height: 16,
width: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Color(0xffF95F62),
),
),
],
],
),
),
if (!state.isGift)
ElevatedButton(
onPressed: () async {
PassPurchaseBottomSheet.close(context);
await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const EditProfilePage(),
),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xffF95F62),
padding: const EdgeInsets.symmetric(
horizontal: 14, vertical: 8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: const Text(
"Edit Details",
style: TextStyle(fontSize: 12, color: Colors.white),
),
),
],
),
),
),
const SizedBox(height: 20),
/// GIFT PASS
GestureDetector(
onTap: () {
context.read<PurchaseDetailsBloc>().add(ToggleGiftModeEvent(true));
context.read<PurchaseDetailsBloc>().add(SetPurchaseDetailsEvent("gift"));
},
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: state.isGift
? Border.all(color: const Color(0xffF95F62), width: 1.5)
: null,
),
child: Row(
children: [
Radio<bool>(
value: true,
groupValue: state.isGift,
onChanged: (_) {},
activeColor: const Color(0xffF95F62),
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
"Gift the pass",
style: TextStyle(fontWeight: FontWeight.w600),
),
SizedBox(height: 4),
Text(
"Gift the pass for someone else",
style: TextStyle(
fontSize: 13, color: Color(0xff9E9E9E)),
),
],
),
),
],
),
),
),
const SizedBox(height: 15),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: state.isSubmittingDetails
? null
: () {
if (state.isGift) {
// ✅ Just close bottom sheet and return 'gift'
// Let checkout view handle the navigation
Navigator.of(context).pop('gift');
} else {
// Submit user details for "Buy for Myself"
if (state.profile != null) {
context.read<PurchaseDetailsBloc>().add(
SubmitUserDetailsEvent(
bookingId: bookingId,
isForSelf: true,
recipientFirstName: state.profile!.firstName,
recipientLastName: state.profile!.lastName,
recipientEmail: state.profile!.emailAddress,
recipientPhone: state.profile!.mobileNumber,
city: '', // Empty for self
country: '', // Empty for self
),
);
}
}
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xffF95F62),
padding: EdgeInsets.symmetric(vertical: 16.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
),
child: state.isSubmittingDetails
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(color: Color(0xffF95F62),
strokeWidth: 2,
),
)
: Text(
"Proceed",
style: TextStyle(
color: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
),
),
),
const SizedBox(height: 15),
],
),
);
},
);
}
}