Files
CityCards_Customer_Flutter/lib/add_details/add_details_view.dart

317 lines
12 KiB
Dart

import 'package:citycards_customer/common_packages/app_bar.dart';
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
import 'package:citycards_customer/common_packages/custom_text.dart';
import 'package:citycards_customer/common_packages/custom_textfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../checkout/bloc/pass_purchase_details_bloc.dart';
import '../checkout/bloc/pass_purchase_details_event.dart';
import '../checkout/bloc/pass_purchase_details_state.dart';
class AddDetailsView extends StatefulWidget {
final int bookingId;
const AddDetailsView({super.key, required this.bookingId});
@override
State<AddDetailsView> createState() => _AddDetailsViewState();
}
class _AddDetailsViewState extends State<AddDetailsView> {
final TextEditingController firstNameController = TextEditingController();
final TextEditingController lastNameController = TextEditingController();
final TextEditingController emailController = TextEditingController();
final TextEditingController phoneController = TextEditingController();
final TextEditingController cityController = TextEditingController();
String? selectedCountry;
@override
void dispose() {
firstNameController.dispose();
lastNameController.dispose();
emailController.dispose();
phoneController.dispose();
cityController.dispose();
super.dispose();
}
bool _isValidEmail(String email) {
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
return emailRegex.hasMatch(email);
}
bool _isValidPhone(String phone) {
final phoneRegex = RegExp(r'^[0-9]{10}$');
return phoneRegex.hasMatch(phone);
}
void _handleSubmit(BuildContext context, bool isSubmitting) {
// If already submitting, do nothing
if (isSubmitting) return;
// Validate inputs
if (firstNameController.text.isEmpty ||
lastNameController.text.isEmpty ||
emailController.text.isEmpty ||
phoneController.text.isEmpty ||
cityController.text.isEmpty ||
selectedCountry == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please fill all fields'),
backgroundColor: Colors.red,
),
);
return;
}
// Validate email
if (!_isValidEmail(emailController.text)) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please enter a valid email address'),
backgroundColor: Colors.red,
),
);
return;
}
// Validate phone number
if (!_isValidPhone(phoneController.text)) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please enter a valid 10-digit phone number'),
backgroundColor: Colors.red,
),
);
return;
}
// Submit gift details
context.read<PurchaseDetailsBloc>().add(
SubmitUserDetailsEvent(
bookingId: widget.bookingId,
isForSelf: false,
recipientFirstName: firstNameController.text,
recipientLastName: lastNameController.text,
recipientEmail: emailController.text,
recipientPhone: phoneController.text,
city: cityController.text,
country: selectedCountry!,
),
);
}
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => PurchaseDetailsBloc(),
child: BlocConsumer<PurchaseDetailsBloc, PurchaseDetailsState>(
listener: (context, state) {
// Handle API submission success
if (state is PurchaseDetailsSubmitted) {
// Show success message
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text('Gift details submitted successfully!'),
// backgroundColor: Color(0xffF95F62),
// ),
// );
// Navigate back
Navigator.of(context).pop('success');
}
// 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) {
final isSubmitting = state.isSubmittingDetails;
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w),
child: Column(
children: [
CommonAppBar(
isWhiteLogo: false,
isProfilePage: false,
showCart: false,
showDivider: true,
),
Row(
children: [
GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, size: 24.sp),
),
SizedBox(width: 8.w),
Text(
"Add details",
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
),
),
],
),
SizedBox(height: 42.h),
Align(
alignment: Alignment.centerLeft,
child: CustomText(
text: "Tell us about the recipient",
size: 18.sp,
weight: FontWeight.w500,
),
),
SizedBox(height: 12.h),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: CustomTextField(
label: "First Name *",
hint: "Enter recipient's first name",
controller: firstNameController,
onlyLetters: true,
maxLength: 50,
noSpace: true,
isFirstLetterCapital: true,
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: CustomTextField(
label: "Last Name *",
hint: "Enter recipient's last name",
controller: lastNameController,
onlyLetters: true,
maxLength: 50,
noSpace: true,
isFirstLetterCapital: true,
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: CustomTextField(
label: "Email *",
hint: "Enter recipient's email address",
controller: emailController,
keyboardType: TextInputType.emailAddress,
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: CustomTextField(
label: "Phone Number *",
hint: "Enter recipient's phone number",
controller: phoneController,
maxLength: 10,
keyboardType: TextInputType.number,
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: CustomTextField(
label: "City *",
hint: "Enter the name of the city",
controller: cityController,
maxLength: 50,
onlyLetters: true,
isFirstLetterCapital: true,
),
),
Padding(
padding: EdgeInsets.only(bottom: 12.h, left: 12.w, right: 12.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomText(text: "Country *", size: 14.sp),
SizedBox(height: 6.h),
Container(
height: 42.h,
padding: EdgeInsets.symmetric(horizontal: 24.w),
decoration: BoxDecoration(
color: const Color(0xFFFFF5F5),
borderRadius: BorderRadius.circular(8.r),
border: Border.all(
color: const Color(0xBBC83B61).withOpacity(0.4),
width: 0.4.w,
),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: selectedCountry,
isExpanded: true,
icon: const Icon(
Icons.keyboard_arrow_down,
color: Color(0xFF8E8E8E),
),
hint: Text(
"Select country",
style: TextStyle(
fontSize: 12.sp,
color: const Color(0xFF8E8E8E),
),
),
style: TextStyle(
fontSize: 14.sp,
color: const Color(0xFF2D3134),
),
onChanged: (value) {
setState(() {
selectedCountry = value;
});
},
items: ["Australia"]
.map((value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(fontSize: 14.sp),
),
);
}).toList(),
),
),
),
],
),
),
SizedBox(height: 24.h),
// Option 1: Pass empty function when disabled (doesn't change button appearance)
CustomFilledButton(
onTap: () => _handleSubmit(context, isSubmitting),
label: isSubmitting ? "Submitting..." : "Continue",
width: double.infinity,
),
SizedBox(height: 50.h),
],
),
),
),
),
);
},
),
);
}
}