Completed Itinerary Creation Model
BIN
assets/icons/active.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
assets/icons/adventure.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
assets/icons/balanced.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
assets/icons/calender.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/icons/halal.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/icons/hi_rate1.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
assets/icons/hi_rate2.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
assets/icons/hi_rate3.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
assets/icons/hi_rate4.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
assets/icons/kosher.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/icons/location.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/icons/magic_creation.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
assets/icons/no_restrictions_food.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
assets/icons/pesc.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/icons/relaxed.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
assets/icons/tr_rate1.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/icons/tr_rate2.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
assets/icons/tr_rate3.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
assets/icons/tr_rate4.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
assets/icons/veg.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/icons/vegan.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
assets/icons/wi_rate1.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
assets/icons/wi_rate2.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
assets/icons/wi_rate3.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
assets/icons/wi_rate4.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
51
lib/common_packages/custom_filled_button.dart
Normal file
@@ -0,0 +1,51 @@
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class CustomFilledButton extends StatelessWidget {
|
||||
final double? width;
|
||||
final String label;
|
||||
final bool? showArrow;
|
||||
final GestureTapCallback onTap;
|
||||
|
||||
CustomFilledButton({
|
||||
super.key,
|
||||
this.width = 266,
|
||||
required this.onTap,
|
||||
required this.label,
|
||||
this.showArrow = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
height: 42.h,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFF95F62),
|
||||
borderRadius: BorderRadius.circular(38.r),
|
||||
),
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CustomText(
|
||||
text: label,
|
||||
color: Colors.white,
|
||||
size: 16.sp ,
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
|
||||
if(showArrow!)
|
||||
SizedBox(width: 8,),
|
||||
if(showArrow!)
|
||||
Icon(Icons.arrow_forward_ios_rounded,size: 18.sp, color: Colors.white,)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class CustomText extends StatelessWidget {
|
||||
final FontWeight? weight;
|
||||
|
||||
@@ -3,6 +3,9 @@ import 'package:citycards_customer/common_bloc/language_selection_bloc.dart';
|
||||
import 'package:citycards_customer/contact_us/contact_us_view.dart';
|
||||
import 'package:citycards_customer/edit_profile/edit_profile_view.dart';
|
||||
import 'package:citycards_customer/faq/faq_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_start_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_view.dart';
|
||||
import 'package:citycards_customer/privacy/privacy_view.dart';
|
||||
import 'package:citycards_customer/terms_and_condition/terms_and_condition_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -65,6 +68,21 @@ class AppRouter {
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.itineraryCreationStart:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return ItineraryCreationStartPage();
|
||||
},
|
||||
);
|
||||
|
||||
case RouteConstants.itineraryCreation:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) {
|
||||
return BlocProvider(create: (_) => ItineraryStepNavigationBloc(),
|
||||
child: ItineraryCreationPage(),
|
||||
);
|
||||
},
|
||||
);
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) =>
|
||||
|
||||
@@ -9,4 +9,9 @@ class RouteConstants {
|
||||
static const String termsAndCondition = '/termsAndCondition';
|
||||
static const String privacyPolicy = '/privacyPolicy';
|
||||
static const String faq = '/faq';
|
||||
|
||||
/****************************** ITINERARY CREATION ************************************/
|
||||
|
||||
static const String itineraryCreationStart = '/itineraryCreationStart';
|
||||
static const String itineraryCreation = '/itineraryCreation';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
abstract class ItineraryStepNavigationEvent {}
|
||||
|
||||
class ItineraryStepNavigationNextEvent extends ItineraryStepNavigationEvent {}
|
||||
|
||||
class ItineraryStepNavigationPreviousEvent extends ItineraryStepNavigationEvent {}
|
||||
|
||||
class ItineraryStepNavigationState {
|
||||
final int selectedIndex;
|
||||
const ItineraryStepNavigationState(this.selectedIndex);
|
||||
}
|
||||
|
||||
class ItineraryStepNavigationBloc
|
||||
extends Bloc<ItineraryStepNavigationEvent, ItineraryStepNavigationState> {
|
||||
final int maxIndex; // maximum index allowed
|
||||
|
||||
ItineraryStepNavigationBloc({this.maxIndex = 2})
|
||||
: super(const ItineraryStepNavigationState(0)) {
|
||||
|
||||
|
||||
on<ItineraryStepNavigationNextEvent>((event, emit) {
|
||||
final nextIndex = state.selectedIndex + 1;
|
||||
if (nextIndex <= 10) {
|
||||
emit(ItineraryStepNavigationState(nextIndex));
|
||||
}
|
||||
});
|
||||
|
||||
on<ItineraryStepNavigationPreviousEvent>((event, emit) {
|
||||
final prevIndex = state.selectedIndex - 1;
|
||||
if (prevIndex >= 0) {
|
||||
emit(ItineraryStepNavigationState(prevIndex));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
90
lib/itinerary_creation/itinerary_creation_start_view.dart
Normal file
@@ -0,0 +1,90 @@
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.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';
|
||||
|
||||
class ItineraryCreationStartPage extends StatelessWidget {
|
||||
const ItineraryCreationStartPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xFFFFF5F5),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
height: 103.h,
|
||||
width: 103.w,
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(24.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12,
|
||||
offset: Offset(0, 4),
|
||||
blurRadius: 5,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Center(
|
||||
child: Image.asset("assets/icons/magic_creation.png", scale: 4),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 34.h),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "Create your",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " magic itinerary",
|
||||
style: TextStyle(
|
||||
color: Color(0xFFF95F62),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 13.h),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 25.w),
|
||||
child: Text(
|
||||
"Answer a few quick questions and we'll craft a personalized travel experience just for you ✨",
|
||||
style: TextStyle(fontSize: 14, color: Color(0xFF4A5565)),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 47.h),
|
||||
CustomFilledButton(
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, RouteConstants.itineraryCreation);
|
||||
},
|
||||
showArrow: true,
|
||||
label: "Let’s Get Started",
|
||||
),
|
||||
SizedBox(height: 38.h),
|
||||
CustomText(
|
||||
text: "Takes only 2 minutes ⏱️",
|
||||
color: Color(0xFF6A7282),
|
||||
size: 14.sp,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class ArtGallerySelectionView extends StatelessWidget {
|
||||
ArtGallerySelectionView({super.key});
|
||||
|
||||
final List<Map<String, String>> options = [
|
||||
{"icon": "😴", "name": "Not interested"},
|
||||
{"icon": "🤔", "name": "Maybe one or two"},
|
||||
{"icon": "😊", "name": "Yes, sounds good!"},
|
||||
{"icon": "🤩", "name": "Absolutely love them!"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. Do you enjoy visiting museums and art galleries?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
...List.generate(options.length, (index) {
|
||||
final item = options[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
height: 83.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(28.r),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
CustomText(
|
||||
text: item['icon'] ?? "",
|
||||
size: 36.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
SizedBox(width: 16.w,),
|
||||
CustomText(
|
||||
text: item['name'] ?? "",
|
||||
size: 16.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class CitySelectionView extends StatelessWidget {
|
||||
CitySelectionView({super.key});
|
||||
|
||||
final List<Map<String, String>> cityList = [
|
||||
{"flag": "🇫🇷", "city": "Paris"},
|
||||
{"flag": "🇯🇵", "city": "Tokyo"},
|
||||
{"flag": "🇺🇸", "city": "New York"},
|
||||
{"flag": "🇬🇧", "city": "London"},
|
||||
{"flag": "🇪🇸", "city": "Barcelona"},
|
||||
{"flag": "🇦🇪", "city": "Dubai"},
|
||||
{"flag": "🇮🇹", "city": "Rome"},
|
||||
{"flag": "🇹🇭", "city": "Bangkok"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. Which city are you visiting?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
Container(
|
||||
height: 56.h,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(left: 20.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(color: Color(0xFFF95F62)),
|
||||
borderRadius: BorderRadius.circular(28.r),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset("assets/icons/location.png", scale: 4),
|
||||
SizedBox(width: 12.w),
|
||||
CustomText(
|
||||
text: "Tokyo",
|
||||
color: Color(0xFF737373),
|
||||
size: 14.sp,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: CustomText(
|
||||
text: "Popular destinations",
|
||||
size: 16.sp,
|
||||
weight: FontWeight.w500,
|
||||
color: Color(0xFF6A7282),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
SizedBox(
|
||||
height: 175.h,
|
||||
child: GridView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
mainAxisSpacing: 16.h,
|
||||
crossAxisSpacing: 16.w,
|
||||
),
|
||||
itemCount: cityList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = cityList[index];
|
||||
return Container(
|
||||
height: 78.h,
|
||||
width: 76.w,
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CustomText(text: item['flag'] ?? ""),
|
||||
SizedBox(height: 4.h),
|
||||
CustomText(
|
||||
text: item['city'] ?? "",
|
||||
size: 12.sp,
|
||||
color: Color(0xFF364153),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40.h),
|
||||
CustomFilledButton(onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
}, label: "Continue", showArrow: true),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class DateSelectionView extends StatelessWidget {
|
||||
const DateSelectionView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. When are you visiting?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
|
||||
Container(
|
||||
height: 90.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
border: Border.all(color: Color(0xFFF95F62), width: 1.1.w),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Image.asset("assets/icons/calender.png", scale: 4),
|
||||
|
||||
CustomText(
|
||||
text: "Wednesday, October 15, 2025",
|
||||
size: 14.sp,
|
||||
color: Color(0xFF101828),
|
||||
),
|
||||
|
||||
Icon(Icons.check_circle, color: Color(0xFFF95F62)),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
CustomFilledButton(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
label: "Continue",
|
||||
showArrow: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class DietarySelectionView extends StatefulWidget {
|
||||
const DietarySelectionView({super.key});
|
||||
|
||||
@override
|
||||
State<DietarySelectionView> createState() => _DietarySelectionViewState();
|
||||
}
|
||||
|
||||
class _DietarySelectionViewState extends State<DietarySelectionView> {
|
||||
int selectedIndex = -1;
|
||||
|
||||
final List<Map<String, String>> options = [
|
||||
{
|
||||
"icon": "assets/icons/no_restrictions_food.png",
|
||||
"name": "No Restrictions",
|
||||
},
|
||||
{"icon": "assets/icons/veg.png", "name": "Vegetarian"},
|
||||
{"icon": "assets/icons/vegan.png", "name": "Vegan"},
|
||||
{"icon": "assets/icons/pesc.png", "name": "Pescatarian"},
|
||||
{"icon": "assets/icons/halal.png", "name": "Halal"},
|
||||
{"icon": "assets/icons/kosher.png", "name": "Kosher"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. Do you follow any dietary preferences?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
CustomText(
|
||||
text: "Select all that apply",
|
||||
size: 14.sp,
|
||||
color: const Color(0xFF6A7282),
|
||||
),
|
||||
SizedBox(height: 38.h),
|
||||
SizedBox(
|
||||
height: 350.h,
|
||||
child: GridView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
mainAxisSpacing: 12,
|
||||
crossAxisSpacing: 16,
|
||||
crossAxisCount: 2,
|
||||
childAspectRatio: 1.7,
|
||||
),
|
||||
itemCount: options.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final item = options[index];
|
||||
return GestureDetector(
|
||||
onTap: () {},
|
||||
child: Container(
|
||||
width: 168.w,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(item["icon"] ?? "", scale: 4),
|
||||
SizedBox(height: 8),
|
||||
CustomText(
|
||||
text: item["name"] ?? "",
|
||||
size: 16.sp,
|
||||
weight: FontWeight.w500,
|
||||
color: const Color(0xFF364153),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 41.h),
|
||||
CustomFilledButton(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
label: "Continue",
|
||||
showArrow: true,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class EnergySelectionView extends StatelessWidget {
|
||||
EnergySelectionView({super.key});
|
||||
|
||||
final List<Map<String, String>> options = [
|
||||
{"img": "assets/icons/relaxed.png", "name": "Relaxed & Chill"},
|
||||
{"img": "assets/icons/balanced.png", "name": "Balanced Mix"},
|
||||
{"img": "assets/icons/active.png", "name": "Active & Energetic"},
|
||||
{"img": "assets/icons/adventure.png", "name": "Full Adventure"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. What kind of energy are you after on this trip?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
...List.generate(options.length, (index) {
|
||||
|
||||
final item = options[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: (){
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
height: 86.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(28.r),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(item['img'] ?? "",scale: 4,),
|
||||
SizedBox(width: 15,),
|
||||
CustomText(
|
||||
text: item['name'] ?? "",
|
||||
size: 14.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class HistoricalSiteRatingView extends StatelessWidget {
|
||||
HistoricalSiteRatingView({super.key});
|
||||
|
||||
final List<Map<String, String>> historicalRatingOption = [
|
||||
{"icon": "assets/icons/hi_rate1.png", "option": "Not interested"},
|
||||
{"icon": "assets/icons/hi_rate2.png", "option": "A few key sites"},
|
||||
{"icon": "assets/icons/hi_rate3.png", "option": "Yes, I enjoy them!"},
|
||||
{"icon": "assets/icons/hi_rate4.png", "option": "Can't miss them!"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CustomText(text: "🏛️", size: 36.sp),
|
||||
SizedBox(height: 9.h),
|
||||
Text(
|
||||
"Do you enjoy cultural landmarks and historical sites?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 30.h),
|
||||
...List.generate(historicalRatingOption.length, (index) {
|
||||
final item = historicalRatingOption[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
height: 82.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
border: Border.all(
|
||||
color: Color(0xFFE5E7EB),
|
||||
width: 1.1
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12,
|
||||
offset: Offset(1,2),
|
||||
blurRadius: 1,
|
||||
)
|
||||
]
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(item['icon']?? "", scale: 4,),
|
||||
SizedBox(width: 16.w,),
|
||||
CustomText(
|
||||
text: item['option'] ?? "",
|
||||
size: 16.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import 'package:flutter/material.dart';
|
||||
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';
|
||||
|
||||
class ItineraryCompletionView extends StatelessWidget {
|
||||
const ItineraryCompletionView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFFFF5F5),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 26.h),
|
||||
CustomText(text: "🎉", size: 60.sp),
|
||||
SizedBox(height: 32.h),
|
||||
Text(
|
||||
"All set! Your travel profile is complete",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: const Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
"We’ve got everything we need to plan your perfect trip",
|
||||
style: TextStyle(color: Color(0xFF6A7282), fontSize: 14),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16.w,
|
||||
vertical: 20.h,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(24.r),
|
||||
border: Border.all(color: Color(0xFFF3F4F6), width: 1.1),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CustomText(
|
||||
text: "Your Profile:",
|
||||
size: 16.sp,
|
||||
weight: FontWeight.w500,
|
||||
color: const Color(0xFF364153),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
_buildProfileRow("Visit Date", "Oct 15, 2025"),
|
||||
_buildProfileRow("City", "Tokyo"),
|
||||
_buildProfileRow("Energy", "Relaxed"),
|
||||
_buildProfileRow("With kids", "Yes"),
|
||||
_buildProfileRow("Dietary", "Vegan"),
|
||||
_buildProfileRow("Museums", "⭐"),
|
||||
_buildProfileRow("Scenic", "⭐"),
|
||||
_buildProfileRow("Cultural", "⭐⭐⭐"),
|
||||
_buildProfileRow("Wildlife", "⭐⭐"),
|
||||
_buildProfileRow("Shopping", "⭐⭐⭐"),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: const BorderSide(
|
||||
color: Color(0xFFE5E7EB),
|
||||
width: 1.1,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
),
|
||||
minimumSize: Size(double.infinity, 42.h),
|
||||
),
|
||||
onPressed: () {
|
||||
// Reset or restart flow
|
||||
},
|
||||
child: CustomText(
|
||||
text: "Start Over",
|
||||
size: 16.sp,
|
||||
color: const Color(0xFF364153),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
CustomFilledButton(
|
||||
width: double.infinity,
|
||||
label: "Get My Trip Plan",
|
||||
showArrow: true,
|
||||
onTap: () {
|
||||
// Navigate to next step
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
|
||||
// Profile summary card
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProfileRow(String title, String value) {
|
||||
return Container(
|
||||
height: 44.h,
|
||||
margin: EdgeInsets.only(bottom: 8.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.w),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF9FAFB),
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
CustomText(text: title, size: 14.sp, color: const Color(0xFF4A5565)),
|
||||
CustomText(
|
||||
text: value,
|
||||
size: 14.sp,
|
||||
weight: FontWeight.w400,
|
||||
color: const Color(0xFF101828),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:citycards_customer/common_packages/custom_filled_button.dart';
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class KidsSelectionView extends StatelessWidget {
|
||||
KidsSelectionView({super.key});
|
||||
|
||||
final List<Map<String, String>> options = [
|
||||
{"icon": "🎈", "option": "Yes!"},
|
||||
{"icon": "🎒", "option": "No"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. Are you travelling with kids?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 40.h),
|
||||
...List.generate(options.length, (index) {
|
||||
final item = options[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
height: 82.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(28.r),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
CustomText(
|
||||
text: item["icon"] ?? "",
|
||||
size: 36.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
SizedBox(width: 16.w),
|
||||
CustomText(
|
||||
text: item["option"] ?? "",
|
||||
size: 14.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class ScenicViewpointsRatingView extends StatelessWidget {
|
||||
ScenicViewpointsRatingView({super.key});
|
||||
|
||||
final List<Map<String, String>> options = [
|
||||
{"icon": "😐", "name": "Not my thing"},
|
||||
{"icon": "📸", "name": "If we have time"},
|
||||
{"icon": "😍", "name": "Yes, definitely!"},
|
||||
{"icon": "🌄", "name": "Must-have!"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"👋 Hello! We'd love to know more about you. Do you enjoy visiting museums and art galleries?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
...List.generate(options.length, (index) {
|
||||
final item = options[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
height: 83.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(28.r),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
CustomText(
|
||||
text: item['icon'] ?? "",
|
||||
size: 36.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
SizedBox(width: 16.w,),
|
||||
CustomText(
|
||||
text: item['name'] ?? "",
|
||||
size: 16.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class ShoppingRatingView extends StatelessWidget {
|
||||
ShoppingRatingView({super.key});
|
||||
|
||||
final List<Map<String, String>> shoppingRatingOption = [
|
||||
{"icon": "assets/icons/tr_rate1.png", "option": "Not interested"},
|
||||
{"icon": "assets/icons/tr_rate2.png", "option": "Just for souvenirs"},
|
||||
{"icon": "assets/icons/tr_rate3.png", "option": "Love browsing!"},
|
||||
{"icon": "assets/icons/tr_rate4.png", "option": "Shopping is a must!"},
|
||||
];
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CustomText(text: "🛒", size: 36.sp),
|
||||
SizedBox(height: 9.h),
|
||||
Text(
|
||||
"How do you feel about shopping during your trip?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 30.h),
|
||||
...List.generate(shoppingRatingOption.length, (index) {
|
||||
final item = shoppingRatingOption[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
height: 82.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
border: Border.all(
|
||||
color: Color(0xFFE5E7EB),
|
||||
width: 1.1
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12,
|
||||
offset: Offset(1,2),
|
||||
blurRadius: 1,
|
||||
)
|
||||
]
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(item['icon']?? "", scale: 4,),
|
||||
SizedBox(width: 16.w,),
|
||||
CustomText(
|
||||
text: item['option'] ?? "",
|
||||
size: 16.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class WildlifeRatingView extends StatelessWidget {
|
||||
WildlifeRatingView({super.key});
|
||||
|
||||
|
||||
final List<Map<String, String>> wildlifeRatingOption = [
|
||||
{"icon": "assets/icons/wi_rate1.png", "option": "No thanks"},
|
||||
{"icon": "assets/icons/wi_rate2.png", "option": "If it happens naturally"},
|
||||
{"icon": "assets/icons/wi_rate3.png", "option": "Yes, would be nice!"},
|
||||
{"icon": "assets/icons/wi_rate4.png", "option": "Absolutely essential!"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CustomText(text: "🦒", size: 36.sp),
|
||||
SizedBox(height: 9.h),
|
||||
Text(
|
||||
"Would you like to include wildlife experiences?",
|
||||
style: TextStyle(
|
||||
color: Color(0xFF101828),
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 30.h),
|
||||
...List.generate(wildlifeRatingOption.length, (index) {
|
||||
final item = wildlifeRatingOption[index];
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationNextEvent(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
height: 82.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
border: Border.all(
|
||||
color: Color(0xFFE5E7EB),
|
||||
width: 1.1
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black12,
|
||||
offset: Offset(1,2),
|
||||
blurRadius: 1,
|
||||
)
|
||||
]
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(item['icon']?? "", scale: 4,),
|
||||
SizedBox(width: 16.w,),
|
||||
CustomText(
|
||||
text: item['option'] ?? "",
|
||||
size: 16.sp,
|
||||
color: const Color(0xFF101828),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
122
lib/itinerary_creation/itinerary_creation_view.dart
Normal file
@@ -0,0 +1,122 @@
|
||||
import 'package:citycards_customer/itinerary_creation/bloc/itinerary_steps_selection_bloc.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/art_gallery_selection_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/city_selection_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/date_selection_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/dietary_selection_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/energy_selection_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/historical_site_rating_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/itinerary_completion_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/kids_selection_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/scenic_viewpoints_rating_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/shopping_rating_view.dart';
|
||||
import 'package:citycards_customer/itinerary_creation/itinerary_creation_steps/wildlife_rating_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class ItineraryCreationPage extends StatefulWidget {
|
||||
const ItineraryCreationPage({super.key});
|
||||
|
||||
@override
|
||||
State<ItineraryCreationPage> createState() => _ItineraryCreationPageState();
|
||||
}
|
||||
|
||||
class _ItineraryCreationPageState extends State<ItineraryCreationPage> {
|
||||
final PageController _pageController = PageController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xFFFFF5F5),
|
||||
appBar: AppBar(
|
||||
backgroundColor: Color(0xFFFFF5F5),
|
||||
centerTitle: true,
|
||||
leading: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<ItineraryStepNavigationBloc>().add(
|
||||
ItineraryStepNavigationPreviousEvent(),
|
||||
);
|
||||
},
|
||||
child: Icon(Icons.arrow_back),
|
||||
),
|
||||
title:
|
||||
BlocBuilder<
|
||||
ItineraryStepNavigationBloc,
|
||||
ItineraryStepNavigationState
|
||||
>(
|
||||
builder: (context, state) {
|
||||
return Text(
|
||||
"${state.selectedIndex} / 10",
|
||||
style: TextStyle(color: Color(0xFF4A5565), fontSize: 14.sp),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
body:
|
||||
BlocListener<
|
||||
ItineraryStepNavigationBloc,
|
||||
ItineraryStepNavigationState
|
||||
>(
|
||||
listener: (context, state) {
|
||||
_pageController.animateToPage(
|
||||
state.selectedIndex,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 20.w,
|
||||
right: 20.w,
|
||||
bottom: 20.h,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child:
|
||||
BlocBuilder<
|
||||
ItineraryStepNavigationBloc,
|
||||
ItineraryStepNavigationState
|
||||
>(
|
||||
builder: (context, state) {
|
||||
return LinearProgressIndicator(
|
||||
value: state.selectedIndex / 10,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
backgroundColor: Colors.white,
|
||||
color: const Color(0xFFF95F62),
|
||||
minHeight: 6.h,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
child: PageView(
|
||||
controller: _pageController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
DateSelectionView(),
|
||||
CitySelectionView(),
|
||||
EnergySelectionView(),
|
||||
KidsSelectionView(),
|
||||
DietarySelectionView(),
|
||||
ArtGallerySelectionView(),
|
||||
ScenicViewpointsRatingView(),
|
||||
HistoricalSiteRatingView(),
|
||||
WildlifeRatingView(),
|
||||
ShoppingRatingView(),
|
||||
ItineraryCompletionView(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class MyApp extends StatelessWidget {
|
||||
builder: (context, child) {
|
||||
return MaterialApp(
|
||||
onGenerateRoute: _appRouter.onGenerateRoute,
|
||||
initialRoute: RouteConstants.home,
|
||||
initialRoute: RouteConstants.itineraryCreationStart,
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'City Cards',
|
||||
theme: ThemeData(
|
||||
|
||||