routing magic itenary
This commit is contained in:
BIN
assets/images/booking_successful.png
Normal file
BIN
assets/images/booking_successful.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/images/profile_default_img.png
Normal file
BIN
assets/images/profile_default_img.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/logo/melbourne_logo.png
Normal file
BIN
assets/logo/melbourne_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.3 KiB |
BIN
assets/logo/melbourne_white.png
Normal file
BIN
assets/logo/melbourne_white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
@@ -24,8 +24,8 @@ class CommonAppBar extends StatelessWidget {
|
||||
children: [
|
||||
Image.asset(
|
||||
isWhiteLogo
|
||||
? "assets/logo/logo_city_cards_white.png"
|
||||
: "assets/logo/logo_city_cards.png",
|
||||
? "assets/logo/melbourne_white.png"
|
||||
: "assets/logo/melbourne_logo.png",
|
||||
scale: 4,
|
||||
),
|
||||
Row(
|
||||
@@ -61,9 +61,7 @@ class CommonAppBar extends StatelessWidget {
|
||||
},
|
||||
child: CircleAvatar(
|
||||
backgroundColor: Color(0xffFFDFDF),
|
||||
backgroundImage: AssetImage(
|
||||
"assets/images/profile_img.png",
|
||||
),
|
||||
child: Image.asset( "assets/images/profile_default_img.png",),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -6,19 +6,25 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../attraction_details/attraction_details_view.dart';
|
||||
import '../attractions/views/attractions_page_view.dart';
|
||||
import '../itinerary_creation/bloc/itinerary_detail_bloc.dart';
|
||||
import '../itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import '../itinerary_creation/views/itinerary_creation_view.dart';
|
||||
import '../itinerary_creation/views/magic_itinerary_filled_view.dart';
|
||||
import '../my_pass/views/booking_page_view.dart';
|
||||
import '../my_pass/views/booking_successful_page_view.dart';
|
||||
import '../my_pass/views/qr_pass_page_view.dart';
|
||||
import '../postcard/blocs/postcard_creation_bloc.dart';
|
||||
import '../postcard/views/postcard_creation_page_view.dart';
|
||||
import '../search_offers/bloc/search_offers_listing_bloc.dart';
|
||||
import '../search_offers/view/search_offers_with_listing.dart';
|
||||
import '../your_itinerary/view/your_itinerary_view.dart';
|
||||
|
||||
Widget buildOffstageNavigator(
|
||||
int index,
|
||||
int currentIndex,
|
||||
Widget child,
|
||||
Key key,
|
||||
) {
|
||||
int index,
|
||||
int currentIndex,
|
||||
Widget child,
|
||||
Key key,
|
||||
) {
|
||||
return Offstage(
|
||||
offstage: currentIndex != index,
|
||||
child: Navigator(
|
||||
@@ -28,22 +34,37 @@ Widget buildOffstageNavigator(
|
||||
case '/':
|
||||
return MaterialPageRoute(builder: (_) => child);
|
||||
|
||||
// 🔹 Attractions Page
|
||||
// 🔹 Attractions Page
|
||||
case RouteConstants.attractionsPage:
|
||||
final args = settings.arguments as String;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => AttractionsPage(source: args,),
|
||||
builder: (_) => AttractionsPage(source: args),
|
||||
);
|
||||
|
||||
case RouteConstants.attractionDetails:
|
||||
return MaterialPageRoute(builder: (_) {
|
||||
return AttractionDetailsView();
|
||||
});
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return AttractionDetailsView();
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.makeBooking:
|
||||
return MaterialPageRoute(builder: (_) {
|
||||
return MakeBookingView(title: 'asffdsf', description: 'afdsfadsfasdfads',);
|
||||
});
|
||||
case RouteConstants.makeBooking:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return MakeBookingView(
|
||||
title: 'Koh Rong Samloem',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Convallis condimentum morbi non egestas enim amet sagittis.ß',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.bookingSuccessful:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return BookingSuccessfulPageView();
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.searchOffer:
|
||||
return MaterialPageRoute(
|
||||
@@ -55,7 +76,7 @@ Widget buildOffstageNavigator(
|
||||
},
|
||||
);
|
||||
|
||||
// 🔹 Upload Photo Page (start of postcard creation flow)
|
||||
// 🔹 Upload Photo Page (start of postcard creation flow)
|
||||
case RouteConstants.uploadPhotoPage:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => BlocProvider(
|
||||
@@ -64,11 +85,13 @@ Widget buildOffstageNavigator(
|
||||
),
|
||||
);
|
||||
|
||||
// 🔹 Add Filter Page (uses same bloc instance)
|
||||
// 🔹 Add Filter Page (uses same bloc instance)
|
||||
case RouteConstants.addFilterPage:
|
||||
return MaterialPageRoute(
|
||||
builder: (context) {
|
||||
final previousBloc = BlocProvider.of<PostcardCreationBloc>(context);
|
||||
final previousBloc = BlocProvider.of<PostcardCreationBloc>(
|
||||
context,
|
||||
);
|
||||
return BlocProvider.value(
|
||||
value: previousBloc,
|
||||
child: const AddFilterStepPageView(),
|
||||
@@ -76,7 +99,6 @@ Widget buildOffstageNavigator(
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
case RouteConstants.qrPage:
|
||||
return MaterialPageRoute(
|
||||
builder: (context) {
|
||||
@@ -88,11 +110,40 @@ Widget buildOffstageNavigator(
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.itineraryCreation:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<ItineraryStepNavigationBloc>(
|
||||
create: (_) => ItineraryStepNavigationBloc(),
|
||||
),
|
||||
|
||||
BlocProvider<AddItineraryDetailBloc>(
|
||||
create: (_) => AddItineraryDetailBloc(),
|
||||
),
|
||||
],
|
||||
child: const ItineraryCreationPage(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.yourItinerary:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return YourItineraryView();
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.magicItineraryFilledScreen:
|
||||
return MaterialPageRoute(builder: (_){
|
||||
return MagicItineraryFilledView();
|
||||
});
|
||||
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const Scaffold(
|
||||
body: Center(child: Text('Page not found')),
|
||||
),
|
||||
builder: (_) =>
|
||||
const Scaffold(body: Center(child: Text('Page not found'))),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -49,4 +49,5 @@ class RouteConstants {
|
||||
|
||||
static const String qrPage = '/qrPage';
|
||||
static const String makeBooking = '/makeBooking';
|
||||
static const String bookingSuccessful = '/bookingSuccessful';
|
||||
}
|
||||
|
||||
@@ -57,9 +57,7 @@ class ItineraryCreationStartPage extends StatelessWidget {
|
||||
onTap: () {
|
||||
Navigator.of(
|
||||
context,
|
||||
rootNavigator: true,
|
||||
).pushNamed(RouteConstants.itineraryCreation);
|
||||
// Navigator.pushNamed(context, RouteConstants.itineraryCreation);
|
||||
).pushReplacementNamed(RouteConstants.itineraryCreation);
|
||||
},
|
||||
showArrow: true,
|
||||
label: "Let’s Get Started",
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
|
||||
|
||||
import '../../../core/route_constants.dart';
|
||||
|
||||
class ItineraryCompletionView extends StatelessWidget {
|
||||
const ItineraryCompletionView({super.key});
|
||||
|
||||
@@ -135,7 +137,9 @@ class ItineraryCompletionView extends StatelessWidget {
|
||||
label: "Get My Trip Plan",
|
||||
showArrow: true,
|
||||
onTap: () {
|
||||
// Navigate to next step
|
||||
Navigator.of(
|
||||
context,
|
||||
).pushReplacementNamed((RouteConstants.yourItinerary));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -147,18 +147,23 @@ class ItineraryFilledCard extends StatelessWidget {
|
||||
|
||||
SizedBox(height: 12.h),
|
||||
|
||||
Container(
|
||||
height: 43.h,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
border: Border.all(color: Color(0xFFF95F62)),
|
||||
),
|
||||
child: Center(
|
||||
child: CustomText(
|
||||
text: "View Itinerary",
|
||||
size: 16.sp,
|
||||
color: Color(0xFFF95F62),
|
||||
weight: FontWeight.w500,
|
||||
InkWell(
|
||||
onTap: (){
|
||||
Navigator.of(context).pushReplacementNamed(RouteConstants.yourItinerary);
|
||||
},
|
||||
child: Container(
|
||||
height: 43.h,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
border: Border.all(color: Color(0xFFF95F62)),
|
||||
),
|
||||
child: Center(
|
||||
child: CustomText(
|
||||
text: "View Itinerary",
|
||||
size: 16.sp,
|
||||
color: Color(0xFFF95F62),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'package:citycards_customer/common_packages/app_bar.dart';
|
||||
import 'package:citycards_customer/common_packages/back_widget.dart';
|
||||
import 'package:citycards_customer/core/route_constants.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
|
||||
|
||||
import '../blocs/make_booking_bloc.dart';
|
||||
import '../blocs/make_booking_events.dart';
|
||||
@@ -32,209 +35,180 @@ class MakeBookingView extends StatelessWidget {
|
||||
final now = DateTime.now();
|
||||
|
||||
return SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 20.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 🔙 Back + Title
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.pop(context),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.arrow_back, size: 20),
|
||||
SizedBox(width: 6.w),
|
||||
Text(
|
||||
"Make Booking",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 20.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
||||
CommonAppBar(isWhiteLogo: false, isProfilePage: false),
|
||||
backWidget(context, "Make Booking", Colors.black),
|
||||
SizedBox(
|
||||
height: 20.h,
|
||||
),
|
||||
|
||||
// 🏝 Title
|
||||
Text(
|
||||
title,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
|
||||
// 📄 Description
|
||||
Text(
|
||||
description,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12.sp,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
|
||||
// 📅 Calendar Container
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 10.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12.withOpacity(0.06),
|
||||
blurRadius: 12,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"When are you visiting?",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
|
||||
// 🗓 SfDateRangePicker
|
||||
SfDateRangePicker(
|
||||
view: DateRangePickerView.month,
|
||||
selectionMode: DateRangePickerSelectionMode.range,
|
||||
minDate: now,
|
||||
maxDate: now.add(const Duration(days: 365)),
|
||||
enablePastDates: false,
|
||||
backgroundColor: Colors.white,
|
||||
showNavigationArrow: true,
|
||||
|
||||
// ✅ Put the background color here
|
||||
headerStyle: DateRangePickerHeaderStyle(
|
||||
backgroundColor: Colors.white, // <-- removes the purple strip
|
||||
textAlign: TextAlign.center,
|
||||
textStyle: GoogleFonts.poppins(
|
||||
fontSize: 13.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
|
||||
// 🏝 Attraction title
|
||||
Text(
|
||||
title,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
|
||||
// Description
|
||||
Text(
|
||||
description,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12.sp,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
|
||||
// 📅 Calendar
|
||||
Container(
|
||||
padding: EdgeInsets.all(12.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12.withOpacity(0.05),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"When are you visiting?",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
monthViewSettings: DateRangePickerMonthViewSettings(
|
||||
firstDayOfWeek: 7,
|
||||
viewHeaderStyle: DateRangePickerViewHeaderStyle(
|
||||
textStyle: GoogleFonts.poppins(
|
||||
color: Colors.grey.shade600,
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
blackoutDates: _getUnavailableDates(state.availableDates, now),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
|
||||
TableCalendar(
|
||||
focusedDay: now,
|
||||
firstDay: now,
|
||||
lastDay: now.add(const Duration(days: 365)),
|
||||
calendarFormat: CalendarFormat.month,
|
||||
availableCalendarFormats: const {
|
||||
CalendarFormat.month: 'Month'
|
||||
},
|
||||
rangeStartDay: state.startDate,
|
||||
rangeEndDay: state.endDate,
|
||||
rangeSelectionMode: RangeSelectionMode.toggledOn,
|
||||
onRangeSelected: (start, end, focusedDay) {
|
||||
monthCellStyle: DateRangePickerMonthCellStyle(
|
||||
textStyle: GoogleFonts.poppins(fontSize: 12.sp, color: Colors.black87),
|
||||
todayTextStyle: GoogleFonts.poppins(
|
||||
fontSize: 12.sp, color: Colors.black, fontWeight: FontWeight.w500),
|
||||
blackoutDateTextStyle: GoogleFonts.poppins(
|
||||
fontSize: 12.sp, color: Colors.grey.shade400,
|
||||
decoration: TextDecoration.lineThrough),
|
||||
),
|
||||
|
||||
rangeTextStyle: GoogleFonts.poppins(
|
||||
fontSize: 12.sp, color: Colors.white, fontWeight: FontWeight.w500),
|
||||
startRangeSelectionColor: const Color(0xffFF5A5F),
|
||||
endRangeSelectionColor: const Color(0xffFF5A5F),
|
||||
rangeSelectionColor: const Color(0xffFF5A5F).withOpacity(0.15),
|
||||
selectionTextStyle: GoogleFonts.poppins(
|
||||
fontSize: 12.sp, color: Colors.white, fontWeight: FontWeight.w500),
|
||||
|
||||
initialSelectedRange: state.startDate != null && state.endDate != null
|
||||
? PickerDateRange(state.startDate, state.endDate)
|
||||
: null,
|
||||
onSelectionChanged: (DateRangePickerSelectionChangedArgs args) {
|
||||
if (args.value is PickerDateRange) {
|
||||
final start = args.value.startDate;
|
||||
final end = args.value.endDate;
|
||||
if (start != null && end != null) {
|
||||
bloc.add(SelectDate(start, end));
|
||||
}
|
||||
},
|
||||
headerStyle: HeaderStyle(
|
||||
titleCentered: true,
|
||||
formatButtonVisible: false,
|
||||
titleTextStyle: GoogleFonts.poppins(
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 40.h),
|
||||
|
||||
// ✅ Confirm button
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state.startDate != null && state.endDate != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"Booking confirmed from "
|
||||
"${state.startDate!.toLocal().toString().split(' ')[0]} "
|
||||
"to ${state.endDate!.toLocal().toString().split(' ')[0]}",
|
||||
),
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pushNamed(RouteConstants.bookingSuccessful);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text("Please select a valid date range"),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xffFF5A5F),
|
||||
borderRadius: BorderRadius.circular(30.r),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Confirm Booking",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.white,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
calendarStyle: CalendarStyle(
|
||||
rangeHighlightColor:
|
||||
const Color(0xffFF5A5F).withOpacity(0.2),
|
||||
rangeStartDecoration: const BoxDecoration(
|
||||
color: Color(0xffFF5A5F),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
rangeEndDecoration: const BoxDecoration(
|
||||
color: Color(0xffFF5A5F),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
todayDecoration: const BoxDecoration(
|
||||
color: Color(0xffFFEAEA),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
outsideDaysVisible: false,
|
||||
),
|
||||
|
||||
// Custom day builder for unavailable days
|
||||
calendarBuilders: CalendarBuilders(
|
||||
defaultBuilder: (context, day, focusedDay) {
|
||||
final isAvailable = state.availableDates
|
||||
.any((d) => isSameDay(d, day));
|
||||
|
||||
if (!isAvailable) {
|
||||
// ❌ Strike-through unavailable date
|
||||
return Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'${day.day}',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12.sp,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 12.h,
|
||||
child: Container(
|
||||
width: 14.w,
|
||||
height: 1.2.h,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ Normal available day
|
||||
return Center(
|
||||
child: Text(
|
||||
'${day.day}',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12.sp,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 40.h),
|
||||
|
||||
// ✅ Confirm Booking button
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state.startDate != null && state.endDate != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"Booking confirmed from "
|
||||
"${state.startDate!.toLocal().toString().split(' ')[0]} "
|
||||
"to ${state.endDate!.toLocal().toString().split(' ')[0]}",
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text("Please select a valid date range"),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xffFF5A5F),
|
||||
borderRadius: BorderRadius.circular(30.r),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Confirm Booking",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.white,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -242,4 +216,18 @@ class MakeBookingView extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Marks unavailable days (those not in availableDates) as blackout
|
||||
List<DateTime> _getUnavailableDates(List<DateTime> available, DateTime start) {
|
||||
final end = start.add(const Duration(days: 365));
|
||||
final allDays = List.generate(
|
||||
end.difference(start).inDays,
|
||||
(i) => DateTime(start.year, start.month, start.day + i),
|
||||
);
|
||||
|
||||
return allDays
|
||||
.where((day) => !available.any((a) =>
|
||||
a.year == day.year && a.month == day.month && a.day == day.day))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
82
lib/my_pass/views/booking_successful_page_view.dart
Normal file
82
lib/my_pass/views/booking_successful_page_view.dart
Normal file
@@ -0,0 +1,82 @@
|
||||
import 'package:citycards_customer/common_packages/app_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../common_packages/back_widget.dart';
|
||||
|
||||
class BookingSuccessfulPageView extends StatelessWidget {
|
||||
const BookingSuccessfulPageView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CommonAppBar(isWhiteLogo: false, isProfilePage: false),
|
||||
backWidget(context, "Make Booking", Colors.black),
|
||||
SizedBox(height: 40.h),
|
||||
|
||||
Image.asset("assets/images/booking_successful.png", scale: 4,),
|
||||
|
||||
SizedBox(height: 20.h),
|
||||
|
||||
Text(
|
||||
"Booking Completed\nSuccessfully!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xff0A0D13),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 20.h),
|
||||
|
||||
Text(
|
||||
"Your booking has been Confirmed on 08/01/2025",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xff2D3134),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 100.h),
|
||||
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xffFF5A5F),
|
||||
borderRadius: BorderRadius.circular(30.r),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Go Back",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.white,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
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:citycards_customer/your_itinerary/bloc/itinerary_days_tabs_bloc.dart';
|
||||
import 'package:citycards_customer/your_itinerary/bloc/your_itinerary_tab_bloc.dart';
|
||||
import 'package:citycards_customer/your_itinerary/widgets/itinerary_card_widget.dart';
|
||||
@@ -54,7 +55,7 @@ class YourItineraryView extends StatelessWidget {
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.of(context).pushReplacementNamed(RouteConstants.magicItineraryFilledScreen);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.arrow_back,
|
||||
|
||||
47
pubspec.lock
47
pubspec.lock
@@ -190,6 +190,11 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_localizations:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_otp_text_field:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -709,6 +714,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
syncfusion_flutter_calendar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: syncfusion_flutter_calendar
|
||||
sha256: "632de42a4cc82dfb1fbc9b40e7097477069aab516a842ca50b187052ab091180"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "31.2.4"
|
||||
syncfusion_flutter_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_flutter_core
|
||||
sha256: a24e9ec04e03c2c14b7b41b1afe60e455adef09b244ab4c425ce6c5b8f58c9ce
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "31.2.4"
|
||||
syncfusion_flutter_datepicker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_flutter_datepicker
|
||||
sha256: "554544875e7fcff8c244aa9e9e77c7b72f75808ebaa30f9f7af3fc9700d6ba18"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "31.2.4"
|
||||
syncfusion_localizations:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_localizations
|
||||
sha256: "4df6e5e1404f8e9c8c1affc38d476158b889c5e1b529514976181e49a7ba3944"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "31.2.4"
|
||||
table_calendar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -733,6 +770,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timezone
|
||||
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -799,4 +844,4 @@ packages:
|
||||
version: "6.6.1"
|
||||
sdks:
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: ">=3.35.0"
|
||||
flutter: ">=3.35.1"
|
||||
|
||||
@@ -45,6 +45,7 @@ dependencies:
|
||||
geolocator: ^14.0.2
|
||||
equatable: ^2.0.7
|
||||
table_calendar: ^3.2.0
|
||||
syncfusion_flutter_calendar: ^31.2.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user