diff --git a/assets/images/green_coupon.png b/assets/images/green_coupon.png new file mode 100644 index 0000000..0104534 Binary files /dev/null and b/assets/images/green_coupon.png differ diff --git a/assets/images/orange_coupon.png b/assets/images/orange_coupon.png new file mode 100644 index 0000000..59970ca Binary files /dev/null and b/assets/images/orange_coupon.png differ diff --git a/assets/images/red_coupon.png b/assets/images/red_coupon.png new file mode 100644 index 0000000..d085818 Binary files /dev/null and b/assets/images/red_coupon.png differ diff --git a/lib/add_details/add_details_view.dart b/lib/add_details/add_details_view.dart new file mode 100644 index 0000000..3e43bb4 --- /dev/null +++ b/lib/add_details/add_details_view.dart @@ -0,0 +1,184 @@ +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:citycards_customer/core/route_constants.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class AddDetailsView extends StatelessWidget { + AddDetailsView({super.key}); + + final TextEditingController firstNameController = TextEditingController(); + final TextEditingController lastNameController = TextEditingController(); + final TextEditingController emailController = TextEditingController(); + final TextEditingController phoneController = TextEditingController(); + final TextEditingController addressController = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 20.w), + child: Column( + children: [ + CommonAppBar( + isWhiteLogo: false, + isProfilePage: false, + showCart: false, + ), + 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 yourself", + size: 18.sp, + weight: FontWeight.w500, + ), + ), + SizedBox(height: 12.h), + + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "First Name", + hint: "Enter your first name", + controller: firstNameController, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "Last Name", + hint: "Enter your last name", + controller: lastNameController, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "Email", + hint: "Enter your email address", + controller: emailController, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "Phone Number", + hint: "Enter your phone number", + controller: phoneController, + ), + ), + + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "City", + hint: "Enter the name of your city", + controller: phoneController, + ), + ), + + 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: StatefulBuilder( + builder: (context, setState) { + String? selectedCountry; + return DropdownButton( + value: selectedCountry, + isExpanded: true, + icon: const Icon( + Icons.keyboard_arrow_down, + color: Color(0xFF8E8E8E), + ), + hint: Text( + "Select your country", + style: TextStyle( + fontSize: 12.sp, + color: Color(0xFF8E8E8E), + ), + ), + style: TextStyle( + fontSize: 14.sp, + color: const Color(0xFF2D3134), + ), + onChanged: (value) { + setState(() { + selectedCountry = value; + }); + }, + items: ["India", "USA", "UK", "Canada"].map(( + value, + ) { + return DropdownMenuItem( + value: value, + child: Text( + value, + style: TextStyle(fontSize: 14.sp), + ), + ); + }).toList(), + ); + }, + ), + ), + ), + ], + ), + ), + + const Spacer(), + + CustomFilledButton( + onTap: () { + + }, + label: "Continue", + width: double.infinity, + ), + SizedBox(height: 50.h), + ], + ), + ), + ), + ); + } +} diff --git a/lib/buy_a_pass/view/buy_pass_view.dart b/lib/buy_a_pass/view/buy_pass_view.dart index d6aa0a9..f3a7bbe 100644 --- a/lib/buy_a_pass/view/buy_pass_view.dart +++ b/lib/buy_a_pass/view/buy_pass_view.dart @@ -1,9 +1,9 @@ import 'package:citycards_customer/buy_a_pass/widget/feature_table.dart'; -import 'package:citycards_customer/buy_a_pass/widget/offer_card_view.dart'; import 'package:citycards_customer/buy_a_pass/widget/pass_card_view.dart'; import 'package:citycards_customer/buy_a_pass/widget/payment_card_view.dart'; import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; +import 'package:citycards_customer/core/route_constants.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -17,6 +17,19 @@ class BuyPassView extends StatelessWidget { {"image": "assets/images/aa4.png", "name": "Serenity Cove"}, ]; + final offers = [ + { + "image": "assets/images/aa1.png", + "title": "Astor Hotels Ultra Deluxe", + "description": "15% Discount on all treatments for first-time clients", + }, + { + "image": "assets/images/aa2.png", + "title": "Green Valley Spa Lux", + "description": "20% off on spa memberships and treatments", + }, + ]; + @override Widget build(BuildContext context) { return Scaffold( @@ -35,7 +48,12 @@ class BuyPassView extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 20.0.w), child: Row( children: [ - Icon(Icons.arrow_back), + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Icon(Icons.arrow_back), + ), SizedBox(width: 8.w), CustomText(text: "Buy a Pass", size: 12.sp), ], @@ -128,55 +146,68 @@ class BuyPassView extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - CustomText(text: "Card Benefits", size: 18.sp), - CustomText( - text: "View All", - size: 14.sp, - color: Color(0xFFFF5757), + CustomText(text: "Card Offers", size: 18.sp), + GestureDetector( + onTap: (){ + Navigator.pushNamed(context,RouteConstants.searchOffer); + }, + child: CustomText( + text: "View All", + size: 14.sp, + color: Color(0xFFFF5757), + ), ), ], ), ), SizedBox(height: 16.h), - Padding( - padding: const EdgeInsets.all(16.0), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: const [ - OfferCard( - title: '50% OFF', - subtitle: 'on eSIM Data Plans', - tag: 'SPECIAL OFFER', - buttonText: 'Get Offer', - badgeText: 'NEW', - backgroundImage: 'assets/images/blue_card_bg.png', - tagIcon: "assets/icons/process_wifi.png", - themeColor: Color(0xFF4F46E5), - ), - SizedBox(width: 16), - OfferCard( - title: '60% OFF', - subtitle: 'Hotel Bookings', - tag: 'EXCLUSIVE DEAL', - buttonText: 'Book Now', - badgeText: 'Limited', - backgroundImage: 'assets/images/red_card_bg.png', - tagIcon: "assets/icons/exclusive.png", - themeColor: Color(0xFFFF5757), - ), - SizedBox(width: 16), - OfferCard( - title: 'Airport Transfer', - subtitle: 'With hotel booking', - tag: 'FREE PERK', - buttonText: 'Learn More', - backgroundImage: 'assets/images/green_card_bg.png', - tagIcon: "assets/icons/star.png", - opacity: 0.3, - ), - ], + Container( + height: 262.h, + padding: EdgeInsets.symmetric(horizontal: 20.w), + child: GridView.builder( + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 16.w, + childAspectRatio: 0.66, ), + itemCount: 2, + itemBuilder: (context, index) { + final offer = offers[index]; + return Container( + padding: EdgeInsets.symmetric( + horizontal: 6.w, + vertical: 6.h, + ), + decoration: BoxDecoration( + border: Border.all( + color: Color(0xFFF95F62).withOpacity(.24), + ), + borderRadius: BorderRadius.circular(12.sp), + ), + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8.sp), + child: Image.asset( + offer["image"] ?? "", + width: double.infinity, + height: 120.5.h, + fit: BoxFit.cover, + ), + ), + SizedBox(height: 8.h), + CustomText(text: offer["title"] ?? "", size: 18.sp), + SizedBox(height: 8.h), + CustomText( + text: offer["description"] ?? "", + color: Colors.black.withOpacity(.6), + size: 12.sp, + ), + ], + ), + ); + }, ), ), diff --git a/lib/buy_a_pass/widget/pass_card_view.dart b/lib/buy_a_pass/widget/pass_card_view.dart index 85e773b..4f9d5cb 100644 --- a/lib/buy_a_pass/widget/pass_card_view.dart +++ b/lib/buy_a_pass/widget/pass_card_view.dart @@ -23,7 +23,7 @@ class PassCardView extends StatelessWidget { return Container( decoration: BoxDecoration( color: Colors.white, - border: Border.all(color: themeColor ?? Color(0xFFF95FAF)), + border: Border.all(color:( themeColor ?? Color(0xFFF95FAF)).withOpacity(0.24)), borderRadius: BorderRadius.circular(8.r), ), child: Expanded( diff --git a/lib/buy_a_pass/widget/payment_card_view.dart b/lib/buy_a_pass/widget/payment_card_view.dart index 26e5980..05d5c1a 100644 --- a/lib/buy_a_pass/widget/payment_card_view.dart +++ b/lib/buy_a_pass/widget/payment_card_view.dart @@ -1,6 +1,7 @@ import 'package:citycards_customer/common_packages/custom_filled_button.dart'; import 'package:citycards_customer/core/route_constants.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; class PaymentCard extends StatefulWidget { final String city; @@ -139,7 +140,7 @@ class _PaymentCardState extends State { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(label, style: const TextStyle(fontSize: 15)), + Text(label, style: TextStyle(fontSize: 15.sp)), Row( children: [ _circleButton(Icons.remove, () { @@ -149,8 +150,8 @@ class _PaymentCardState extends State { padding: const EdgeInsets.symmetric(horizontal: 10), child: Text( "$value", - style: const TextStyle( - fontSize: 16, + style: TextStyle( + fontSize: 16.sp, fontWeight: FontWeight.bold, ), ), @@ -167,14 +168,14 @@ class _PaymentCardState extends State { Widget _circleButton(IconData icon, VoidCallback onTap) { return InkWell( onTap: onTap, - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(20.r), child: Container( decoration: const BoxDecoration( shape: BoxShape.circle, color: Color(0xFFF95F62), ), padding: const EdgeInsets.all(4), - child: Icon(icon, color: Colors.white, size: 18), + child: Icon(icon, color: Colors.white, size: 18.sp), ), ); } diff --git a/lib/checkout/bloc/purchase_details_bloc.dart b/lib/checkout/bloc/purchase_details_bloc.dart new file mode 100644 index 0000000..c22cc45 --- /dev/null +++ b/lib/checkout/bloc/purchase_details_bloc.dart @@ -0,0 +1,24 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; + +abstract class PurchaseDetails {} + +class SetPurchaseDetailsEvent extends PurchaseDetails { + final String buyPassValue; + + SetPurchaseDetailsEvent(this.buyPassValue); +} + +class PurchaseDetailsState { + final String buyPassState; + + PurchaseDetailsState(this.buyPassState); +} + +class PurchaseDetailsBloc + extends Bloc { + PurchaseDetailsBloc() : super(PurchaseDetailsState("")) { + on((event, emit){ + emit(PurchaseDetailsState(event.buyPassValue)); + }); + } +} diff --git a/lib/checkout/view/checkout_view.dart b/lib/checkout/view/checkout_view.dart index fc18b20..c308708 100644 --- a/lib/checkout/view/checkout_view.dart +++ b/lib/checkout/view/checkout_view.dart @@ -1,3 +1,4 @@ +import 'package:citycards_customer/checkout/widget/all_coupons_bottomsheet.dart'; import 'package:citycards_customer/checkout/widget/login_email_bottomsheet.dart'; import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_filled_button.dart'; @@ -26,7 +27,12 @@ class CheckoutView extends StatelessWidget { ), Row( children: [ - Icon(Icons.arrow_back), + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Icon(Icons.arrow_back), + ), SizedBox(width: 8.w), CustomText(text: "Checkout", size: 12.sp), ], @@ -53,8 +59,8 @@ class CheckoutView extends StatelessWidget { child: Image.asset( "assets/images/card_banner.png", scale: 4, - width: 103.w, - height: 160.h, + width: 105.w, + height: 123.h, fit: BoxFit.cover, ), ), @@ -67,13 +73,13 @@ class CheckoutView extends StatelessWidget { weight: FontWeight.w500, size: 16.sp, ), - SizedBox(height: 8.h), + SizedBox(height: 5.h), CustomText( text: "2 Days", color: Color(0xFF8E8E8E), size: 12.sp, ), - SizedBox(height: 12.h), + SizedBox(height: 5.h), SizedBox( width: MediaQuery.of(context).size.width * .5, @@ -103,10 +109,26 @@ class CheckoutView extends StatelessWidget { scale: 4, ), SizedBox(width: 4.w), - CustomText( - text: "Qty : 2", - color: Color(0xFF8E8E8E), - size: 12.sp, + Text.rich( + TextSpan( + children: [ + TextSpan( + text: "Qty:", + style: TextStyle( + color: Color(0xFF8E8E8E), + fontSize: 12.sp, + ), + ), + TextSpan( + text: " 2", + style: TextStyle( + color: Color(0xFF000000), + fontSize: 12.sp, + fontWeight: FontWeight.w500, + ), + ), + ], + ), ), ], ), @@ -114,7 +136,7 @@ class CheckoutView extends StatelessWidget { ), ), - SizedBox(height: 7.h), + SizedBox(height: 5.h), Row( children: [ Image.asset("assets/icons/kid.png", scale: 4), @@ -135,16 +157,6 @@ class CheckoutView extends StatelessWidget { ), ], ), - - SizedBox( - width: 193.w, - child: CustomText( - text: - "Dive into an extensive selection of thrilling destinations!", - color: Color(0xFF000000).withOpacity(0.6), - size: 11.sp, - ), - ), ], ), ], @@ -152,7 +164,7 @@ class CheckoutView extends StatelessWidget { Container( width: 35.w, - height: 160.h, + height: 123.h, decoration: BoxDecoration( color: Color(0xFFF95FAF), borderRadius: BorderRadius.only( @@ -217,10 +229,25 @@ class CheckoutView extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - CustomText( - text: "View all coupons", - color: Color(0xFFF95F62), - size: 12, + GestureDetector( + onTap: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(12.r), + ), + ), + builder: (_) => AllCouponsBottomsheet(), + ); + }, + child: CustomText( + text: "View all coupons", + color: Color(0xFFF95F62), + size: 12, + ), ), SizedBox(width: 3.w), Icon(Icons.arrow_right, color: Color(0xFFF95F62)), @@ -232,7 +259,7 @@ class CheckoutView extends StatelessWidget { const Spacer(), Container( padding: EdgeInsets.symmetric( - horizontal: 12.w, + horizontal: 20.w, vertical: 10.h, ), decoration: BoxDecoration( @@ -327,8 +354,8 @@ class CheckoutView extends StatelessWidget { ), builder: (_) => const LoginEmailBottomsheet(), ); - }, + width: double.infinity, label: "Login to Checkout", ), SizedBox(height: 25.h), diff --git a/lib/checkout/widget/all_coupons_bottomsheet.dart b/lib/checkout/widget/all_coupons_bottomsheet.dart new file mode 100644 index 0000000..bb54b92 --- /dev/null +++ b/lib/checkout/widget/all_coupons_bottomsheet.dart @@ -0,0 +1,109 @@ +import 'package:citycards_customer/checkout/widget/purchase_details_bottomsheet.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:citycards_customer/common_packages/custom_text.dart'; + +class AllCouponsBottomsheet extends StatelessWidget { + AllCouponsBottomsheet({super.key}); + + final List coupons = [ + "assets/images/red_coupon.png", + "assets/images/green_coupon.png", + "assets/images/orange_coupon.png", + "assets/images/orange_coupon.png", + ]; + + @override + Widget build(BuildContext context) { + return AnimatedPadding( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOut, + padding: EdgeInsets.only( + top: 24.h, + left: 20.w, + right: 20.w, + bottom: MediaQuery.of(context).viewInsets.bottom, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + /// --- Header --- + Container( + height: 4.h, + width: 40.w, + decoration: BoxDecoration( + color: Color(0xFF2D3134), + borderRadius: BorderRadius.circular(4.r), + ), + ), + SizedBox(height: 12.h), + CustomText(text: "All Coupons", size: 18.sp, weight: FontWeight.w500), + SizedBox(height: 22.h), + + /// --- Coupon list --- + Flexible( + child: ListView.separated( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + itemCount: coupons.length, + separatorBuilder: (_, __) => SizedBox(height: 12.h), + itemBuilder: (context, index) { + return Container( + alignment: Alignment.center, + padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 8.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.r), + border: Border.all( + color: const Color(0xFFF95F62).withOpacity(0.12), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + width: 183.9.w, + height: 72.82.h, + coupons[index], + fit: BoxFit.cover, + ), + GestureDetector( + onTap: (){ + Navigator.pop(context); + showModalBottomSheet(context: context, + isScrollControlled: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(12.r), + ), + ), + builder: (_) => const PurchaseDetailsBottomsheet()); + }, + child: Container( + width: 110.w, + height: 44.h, + decoration: BoxDecoration( + color: Color(0xFFF95F62), + borderRadius: BorderRadius.circular(12.r), + ), + child: Center( + child: CustomText( + text: "Apply Coupon", + size: 12.sp, + color: Colors.white, + ), + ), + ), + ), + ], + ), + ); + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/checkout/widget/purchase_details_bottomsheet.dart b/lib/checkout/widget/purchase_details_bottomsheet.dart new file mode 100644 index 0000000..0fa7376 --- /dev/null +++ b/lib/checkout/widget/purchase_details_bottomsheet.dart @@ -0,0 +1,215 @@ +import 'package:citycards_customer/checkout/bloc/purchase_details_bloc.dart'; +import 'package:citycards_customer/common_packages/custom_filled_button.dart'; +import 'package:citycards_customer/common_packages/custom_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class PurchaseDetailsBottomsheet extends StatelessWidget { + const PurchaseDetailsBottomsheet({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => PurchaseDetailsBloc(), + child: AnimatedPadding( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOut, + padding: EdgeInsets.only( + top: 24.h, + left: 20.w, + right: 20.w, + bottom: MediaQuery.of(context).viewInsets.bottom, + ), + child: BlocBuilder( + builder: (context, state) { + final selected = state.buyPassState; + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // --- Handle Bar --- + Container( + height: 4.h, + width: 40.w, + decoration: BoxDecoration( + color: const Color(0xFF2D3134), + borderRadius: BorderRadius.circular(4.r), + ), + ), + SizedBox(height: 12.h), + + CustomText( + text: "Purchase Details", + size: 18.sp, + weight: FontWeight.w600, + ), + SizedBox(height: 22.h), + + // --- Option 1: Buy for Myself --- + GestureDetector( + onTap: () { + context.read().add( + SetPurchaseDetailsEvent("myself"), + ); + }, + child: Container( + padding: EdgeInsets.all(6), + decoration: BoxDecoration( + border: Border.all( + color: selected == "myself" + ? const Color(0xFFF95F62) + : Colors.transparent, + ), + borderRadius: BorderRadius.circular(10.r), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + selected == "myself" + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: selected == "myself" + ? const Color(0xFFF95F62) + : Color(0xFF2B2929).withOpacity(.6), + size: 24.sp, + ), + SizedBox(width: 8.w), + CustomText( + text: "Buy Pass for Myself", + color: selected == "myself" + ? const Color(0xFFF95F62) + : Color(0xFF2B2929).withOpacity(.6), + size: 16.sp, + weight: FontWeight.w500, + ), + ], + ), + if (selected == "myself") ...[ + SizedBox(height: 6.h), + CustomText( + text: "Frank Adam", + size: 14.sp, + weight: FontWeight.w400, + color: Colors.black.withOpacity(0.6), + ), + SizedBox(height: 4.h), + CustomText( + text: "132 My Street, Kingston, NY 12401", + size: 12.sp, + color: const Color( + 0xFF000000, + ).withOpacity(0.4), + ), + ], + ], + ), + ), + if (selected == "myself") + Container( + padding: EdgeInsets.symmetric( + horizontal: 6.w, + vertical: 6.h, + ), + decoration: BoxDecoration( + color: Color(0xFFF95F62).withOpacity(0.12), + border: Border.all( + color: const Color(0xFFF95F62), + width: 1, + ), + borderRadius: BorderRadius.circular(12.r), + ), + child: CustomText( + text: "Edit Details", + size: 16.sp, + weight: FontWeight.w500, + color: const Color(0xFFF95F62), + ), + ), + ], + ), + ), + ), + SizedBox(height: 16.h), + + // --- Option 2: Gift the Pass --- + GestureDetector( + onTap: () { + context.read().add( + SetPurchaseDetailsEvent("gift"), + ); + }, + child: Container( + padding: EdgeInsets.all(12.w), + decoration: BoxDecoration( + border: Border.all( + color: selected == "gift" + ? const Color(0xFFF95F62) + : Colors.transparent, + ), + borderRadius: BorderRadius.circular(12.r), + ), + child: Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + selected == "gift" + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: selected == "gift" + ? const Color(0xFFF95F62) + : Color(0xFF2F2A2A).withOpacity(0.4), + size: 24.sp, + ), + SizedBox(width: 8.w), + CustomText( + text: "Gift the pass", + color: selected == "gift" + ? const Color(0xFFF95F62) + : Color(0xFF2F2A2A).withOpacity(0.4), + size: 16.sp, + weight: FontWeight.w500, + ), + ], + ), + SizedBox(height: 6.h), + if (selected == "gift") + CustomText( + text: "Gift the pass for someone else", + size: 12.sp, + color: const Color(0xFF000000).withOpacity(0.6), + ), + ], + ), + ), + ), + ), + + SizedBox(height: 24.h), + + // --- Proceed Button --- + CustomFilledButton( + onTap: () {}, + label: "Proceed", + width: double.infinity, + ), + SizedBox(height: 20.h), + ], + ); + }, + ), + ), + ); + } +} diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index 40ab0c2..06af037 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -1,9 +1,11 @@ import 'package:citycards_customer/Profile/profile_page_view.dart'; +import 'package:citycards_customer/add_details/add_details_view.dart'; import 'package:citycards_customer/attraction_details/attraction_details_view.dart'; import 'package:citycards_customer/buy_a_pass/view/buy_pass_view.dart'; import 'package:citycards_customer/checkout/view/checkout_view.dart'; import 'package:citycards_customer/common_bloc/language_selection_bloc.dart'; import 'package:citycards_customer/contact_us/contact_us_view.dart'; +import 'package:citycards_customer/create_account/create_account_view.dart'; import 'package:citycards_customer/edit_profile/edit_profile_view.dart'; import 'package:citycards_customer/esim_offer/esim_offer_view.dart'; import 'package:citycards_customer/faq/faq_view.dart'; @@ -12,9 +14,9 @@ import 'package:citycards_customer/itinerary_creation/bloc/itinerary_detail_bloc import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart'; import 'package:citycards_customer/itinerary_creation/views/itinerary_creation_start_view.dart'; import 'package:citycards_customer/itinerary_creation/views/itinerary_creation_view.dart'; -import 'package:citycards_customer/offer_section/bloc/search_offers_listing_bloc.dart'; -import 'package:citycards_customer/offer_section/view/search_offers_with_listing.dart'; import 'package:citycards_customer/privacy/privacy_view.dart'; +import 'package:citycards_customer/search_offers/bloc/search_offers_listing_bloc.dart'; +import 'package:citycards_customer/search_offers/view/search_offers_with_listing.dart'; import 'package:citycards_customer/terms_and_condition/terms_and_condition_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -145,6 +147,16 @@ class AppRouter { child: SearchOffersWithListing(), ); }); + + case RouteConstants.addDetails: + return MaterialPageRoute(builder: (_){ + return AddDetailsView(); + }); + + case RouteConstants.createAcct: + return MaterialPageRoute(builder: (_){ + return CreateAccountView(); + }); default: return MaterialPageRoute( builder: (_) => diff --git a/lib/core/route_constants.dart b/lib/core/route_constants.dart index b2472ed..111469e 100644 --- a/lib/core/route_constants.dart +++ b/lib/core/route_constants.dart @@ -35,6 +35,9 @@ class RouteConstants { static const String buyPass ='/buyPass'; static const String checkout ='/checkout'; static const String searchOffer = '/searchOffer'; + static const String createAcct = '/createAcct'; + static const String addDetails = '/addDetails'; + /************************** My card page ***************************************/ static const String cartPage = '/cartPage'; diff --git a/lib/create_account/create_account_view.dart b/lib/create_account/create_account_view.dart new file mode 100644 index 0000000..f45320e --- /dev/null +++ b/lib/create_account/create_account_view.dart @@ -0,0 +1,122 @@ +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'; + +class CreateAccountView extends StatelessWidget { + CreateAccountView({super.key}); + + final TextEditingController firstNameController = TextEditingController(); + final TextEditingController lastNameController = TextEditingController(); + final TextEditingController emailController = TextEditingController(); + final TextEditingController phoneController = TextEditingController(); + final TextEditingController addressController = TextEditingController(); + + @override + Widget build(BuildContext context) { + + + return Scaffold( + backgroundColor: Colors.white, + body: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 20.w), + child: Column( + children: [ + CommonAppBar( + isWhiteLogo: false, + isProfilePage: false, + showCart: false, + ), + Row( + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Icon(Icons.arrow_back), + ), + SizedBox(width: 8.w), + CustomText(text: "Create your account", size: 12.sp), + ], + ), + SizedBox(height: 26.h,), + + Align( + alignment: Alignment.centerLeft, + child: CustomText( + text: "Personal Information", + size: 18.sp, + weight: FontWeight.w500, + ), + ), + SizedBox(height: 12.h), + + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "First Name", + hint: "Enter your first name", + controller: firstNameController, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "Last Name", + hint: "Enter your last name", + controller: lastNameController, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "Email", + hint: "Enter your email address", + controller: emailController, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: CustomTextField( + label: "Phone Number", + hint: "Enter your phone number", + controller: phoneController, + ), + ), + + SizedBox(height: 2.h), + + // Location Details + Align( + alignment: Alignment.centerLeft, + child: CustomText( + text: "Location Details", + size: 18.sp, + weight: FontWeight.w500, + ), + ), + SizedBox(height: 16.h), + + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0.w), + child: CustomTextField( + label: "Address 1", + hint: "Enter address manually or tap to search", + controller: addressController, + ), + ), + + SizedBox(height: 36.h), + CustomFilledButton( + width: double.infinity, + onTap: (){}, label: "Create Account") + ], + ), + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 35341e4..be24e47 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -29,6 +29,7 @@ class MyApp extends StatelessWidget { builder: (context, child) { return MaterialApp( onGenerateRoute: _appRouter.onGenerateRoute, + initialRoute: RouteConstants.buyPass, debugShowCheckedModeBanner: false, title: 'City Cards', theme: ThemeData( diff --git a/lib/offer_section/bloc/search_offers_listing_bloc.dart b/lib/search_offers/bloc/search_offers_listing_bloc.dart similarity index 100% rename from lib/offer_section/bloc/search_offers_listing_bloc.dart rename to lib/search_offers/bloc/search_offers_listing_bloc.dart diff --git a/lib/offer_section/view/search_offers_with_listing.dart b/lib/search_offers/view/search_offers_with_listing.dart similarity index 95% rename from lib/offer_section/view/search_offers_with_listing.dart rename to lib/search_offers/view/search_offers_with_listing.dart index 99cad29..f4d9ac0 100644 --- a/lib/offer_section/view/search_offers_with_listing.dart +++ b/lib/search_offers/view/search_offers_with_listing.dart @@ -1,7 +1,7 @@ import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_search_field.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; -import 'package:citycards_customer/offer_section/bloc/search_offers_listing_bloc.dart'; +import 'package:citycards_customer/search_offers/bloc/search_offers_listing_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -25,7 +25,11 @@ class SearchOffersWithListing extends StatelessWidget { CommonAppBar(isWhiteLogo: false, isProfilePage: false,showCart: false,), Row( children: [ - Icon(Icons.arrow_back), + GestureDetector( + onTap: (){ + Navigator.pop(context); + }, + child: Icon(Icons.arrow_back)), SizedBox(width: 8.w), CustomText(text: "Offers with Flexi Card", size: 12.sp), ],