worked on bu fix
This commit is contained in:
1
assets/intro/animm.json
Normal file
1
assets/intro/animm.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -24,6 +24,11 @@ PODS:
|
|||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- url_launcher_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- video_player_avfoundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
@@ -34,6 +39,8 @@ DEPENDENCIES:
|
|||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
@@ -57,6 +64,10 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
|
url_launcher_ios:
|
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
video_player_avfoundation:
|
||||||
|
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
@@ -69,6 +80,8 @@ SPEC CHECKSUMS:
|
|||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
|
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
||||||
|
|
||||||
PODFILE CHECKSUM: 1857a7cdb7dfafe45f2b0e9a9af44644190f7506
|
PODFILE CHECKSUM: 1857a7cdb7dfafe45f2b0e9a9af44644190f7506
|
||||||
|
|
||||||
|
|||||||
@@ -316,14 +316,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
@@ -374,14 +370,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
|||||||
15
lib/attraction_details/bloc/attraction_details_bloc.dart
Normal file
15
lib/attraction_details/bloc/attraction_details_bloc.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:citycards_customer/attraction_details/bloc/attraction_details_event.dart';
|
||||||
|
import 'package:citycards_customer/attraction_details/bloc/attraction_details_state.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class AttractionDetailsBloc
|
||||||
|
extends Bloc<AttractionDetailsEvent, AttractionDetailsState> {
|
||||||
|
AttractionDetailsBloc() : super(AttractionDetailsState()) {
|
||||||
|
on<SetFlowFromPass>(_setFlowFromPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setFlowFromPass(SetFlowFromPass event, Emitter<AttractionDetailsState> emit) {
|
||||||
|
print("Setting the flow from pass ${event.fromByPass}");
|
||||||
|
emit(state.copyWith(fromByPass: event.fromByPass));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class AttractionDetailsEvent {
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetFlowFromPass extends AttractionDetailsEvent{
|
||||||
|
final bool fromByPass;
|
||||||
|
SetFlowFromPass(this.fromByPass);
|
||||||
|
}
|
||||||
14
lib/attraction_details/bloc/attraction_details_state.dart
Normal file
14
lib/attraction_details/bloc/attraction_details_state.dart
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
class AttractionDetailsState extends Equatable {
|
||||||
|
bool fromByPass;
|
||||||
|
|
||||||
|
AttractionDetailsState({this.fromByPass = false});
|
||||||
|
|
||||||
|
AttractionDetailsState copyWith({required bool fromByPass}) {
|
||||||
|
return AttractionDetailsState(fromByPass: fromByPass ?? this.fromByPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [fromByPass];
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import 'package:citycards_customer/attraction_details/bloc/attraction_details_bloc.dart';
|
||||||
|
import 'package:citycards_customer/attraction_details/bloc/attraction_details_state.dart';
|
||||||
import 'package:citycards_customer/attraction_details/view_model/attraction_details_view_model.dart';
|
import 'package:citycards_customer/attraction_details/view_model/attraction_details_view_model.dart';
|
||||||
import 'package:citycards_customer/attraction_details/widgets/share_bottomsheet.dart';
|
import 'package:citycards_customer/attraction_details/widgets/share_bottomsheet.dart';
|
||||||
import 'package:citycards_customer/common_packages/app_bar.dart';
|
import 'package:citycards_customer/common_packages/app_bar.dart';
|
||||||
import 'package:citycards_customer/common_packages/custom_text.dart';
|
import 'package:citycards_customer/common_packages/custom_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import '../../core/route_constants.dart';
|
import '../../core/route_constants.dart';
|
||||||
|
|
||||||
@@ -152,287 +155,319 @@ class AttractionDetailsView extends StatelessWidget {
|
|||||||
// Booking Section
|
// Booking Section
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||||
child: Column(
|
child: BlocBuilder<AttractionDetailsBloc, AttractionDetailsState>(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
builder: (context, state) {
|
||||||
children: [
|
print("fajfasfasjfjas======= ${state.fromByPass}");
|
||||||
Text(
|
return Column(
|
||||||
"How to make a booking?",
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18.sp,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 16.h),
|
|
||||||
InkWell(
|
|
||||||
onTap: () =>
|
|
||||||
viewModel.makePhoneCall('+10123456789', context),
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 12.w,
|
|
||||||
vertical: 12.h,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
border: Border.all(color: Color(0xFFF95F62)),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.call,
|
|
||||||
color: Color(0xFFF95F62),
|
|
||||||
size: 32.w,
|
|
||||||
),
|
|
||||||
SizedBox(width: 16.w),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
CustomText(
|
|
||||||
text: "Contact Number",
|
|
||||||
color: Colors.black.withOpacity(.6),
|
|
||||||
size: 12.sp,
|
|
||||||
weight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
SizedBox(height: 6.h),
|
|
||||||
CustomText(
|
|
||||||
text: "+1012 3456 789",
|
|
||||||
color: Colors.black,
|
|
||||||
size: 14.sp,
|
|
||||||
weight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 6.h),
|
|
||||||
CustomText(
|
|
||||||
text: "Tap to call",
|
|
||||||
color: Colors.black.withOpacity(.4),
|
|
||||||
size: 12.sp,
|
|
||||||
weight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 16.h),
|
|
||||||
InkWell(
|
|
||||||
onTap: () =>
|
|
||||||
viewModel.sendEmail('CityCards24@gmail.com', context),
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 12.w,
|
|
||||||
vertical: 12.h,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
border: Border.all(color: Color(0xFFF95F62)),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.email_sharp,
|
|
||||||
color: Color(0xFFF95F62),
|
|
||||||
size: 32.w,
|
|
||||||
),
|
|
||||||
SizedBox(width: 16.w),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
CustomText(
|
|
||||||
text: "Email",
|
|
||||||
color: Colors.black.withOpacity(.6),
|
|
||||||
size: 12.sp,
|
|
||||||
weight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
SizedBox(height: 6.h),
|
|
||||||
CustomText(
|
|
||||||
text: "CityCards24@gmail.com",
|
|
||||||
color: Colors.black,
|
|
||||||
size: 14.sp,
|
|
||||||
weight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 6.h),
|
|
||||||
CustomText(
|
|
||||||
text: "Tap to email",
|
|
||||||
color: Colors.black.withOpacity(.4),
|
|
||||||
size: 12.sp,
|
|
||||||
weight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 16.h),
|
|
||||||
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(
|
|
||||||
context,
|
|
||||||
).pushNamed(RouteConstants.makeBooking);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 24.w,
|
|
||||||
vertical: 18.h,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Color(0xFFF95F62),
|
|
||||||
borderRadius: BorderRadius.circular(10.r),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
CustomText(
|
|
||||||
text: "Via CityCards",
|
|
||||||
size: 16.sp,
|
|
||||||
weight: FontWeight.w500,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
SizedBox(height: 8.h),
|
|
||||||
CustomText(
|
|
||||||
text: "Create a booking via app",
|
|
||||||
size: 11.sp,
|
|
||||||
weight: FontWeight.w400,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Icon(
|
|
||||||
Icons.arrow_forward_ios_outlined,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 30.h),
|
|
||||||
|
|
||||||
Divider(color: Colors.black.withOpacity(0.2)),
|
|
||||||
SizedBox(height: 30.h),
|
|
||||||
Text(
|
|
||||||
"What is included",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 24.sp,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 4.h),
|
|
||||||
|
|
||||||
Wrap(
|
|
||||||
runSpacing: 16.h,
|
|
||||||
spacing: 16.w,
|
|
||||||
children: [
|
children: [
|
||||||
includedBox(
|
if (state.fromByPass)
|
||||||
"assets/icons/bus.png",
|
Column(
|
||||||
"Bus",
|
children: [
|
||||||
"Transportation",
|
Text(
|
||||||
|
"How to make a booking?",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.sp,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => viewModel.makePhoneCall(
|
||||||
|
'+10123456789',
|
||||||
|
context,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 12.w,
|
||||||
|
vertical: 12.h,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
border: Border.all(
|
||||||
|
color: Color(0xFFF95F62),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.call,
|
||||||
|
color: Color(0xFFF95F62),
|
||||||
|
size: 32.w,
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.w),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
CustomText(
|
||||||
|
text: "Contact Number",
|
||||||
|
color: Colors.black.withOpacity(
|
||||||
|
.6,
|
||||||
|
),
|
||||||
|
size: 12.sp,
|
||||||
|
weight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
SizedBox(height: 6.h),
|
||||||
|
CustomText(
|
||||||
|
text: "+1012 3456 789",
|
||||||
|
color: Colors.black,
|
||||||
|
size: 14.sp,
|
||||||
|
weight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 6.h),
|
||||||
|
CustomText(
|
||||||
|
text: "Tap to call",
|
||||||
|
color: Colors.black.withOpacity(
|
||||||
|
.4,
|
||||||
|
),
|
||||||
|
size: 12.sp,
|
||||||
|
weight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => viewModel.sendEmail(
|
||||||
|
'CityCards24@gmail.com',
|
||||||
|
context,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 12.w,
|
||||||
|
vertical: 12.h,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
border: Border.all(
|
||||||
|
color: Color(0xFFF95F62),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.email_sharp,
|
||||||
|
color: Color(0xFFF95F62),
|
||||||
|
size: 32.w,
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.w),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
CustomText(
|
||||||
|
text: "Email",
|
||||||
|
color: Colors.black.withOpacity(
|
||||||
|
.6,
|
||||||
|
),
|
||||||
|
size: 12.sp,
|
||||||
|
weight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
SizedBox(height: 6.h),
|
||||||
|
CustomText(
|
||||||
|
text: "CityCards24@gmail.com",
|
||||||
|
color: Colors.black,
|
||||||
|
size: 14.sp,
|
||||||
|
weight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 6.h),
|
||||||
|
CustomText(
|
||||||
|
text: "Tap to email",
|
||||||
|
color: Colors.black.withOpacity(
|
||||||
|
.4,
|
||||||
|
),
|
||||||
|
size: 12.sp,
|
||||||
|
weight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pushNamed(RouteConstants.makeBooking);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24.w,
|
||||||
|
vertical: 18.h,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(0xFFF95F62),
|
||||||
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
CustomText(
|
||||||
|
text: "Via CityCards",
|
||||||
|
size: 16.sp,
|
||||||
|
weight: FontWeight.w500,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
SizedBox(height: 8.h),
|
||||||
|
CustomText(
|
||||||
|
text:
|
||||||
|
"Create a booking via app",
|
||||||
|
size: 11.sp,
|
||||||
|
weight: FontWeight.w400,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
Icons.arrow_forward_ios_outlined,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 30.h),
|
||||||
|
|
||||||
|
Divider(color: Colors.black.withOpacity(0.2)),
|
||||||
|
SizedBox(height: 30.h),
|
||||||
|
Text(
|
||||||
|
"What is included",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24.sp,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
includedBox(
|
SizedBox(height: 4.h),
|
||||||
"assets/icons/clock.png",
|
|
||||||
"2 day 1 night",
|
Wrap(
|
||||||
"Duration",
|
runSpacing: 16.h,
|
||||||
|
spacing: 16.w,
|
||||||
|
children: [
|
||||||
|
includedBox(
|
||||||
|
"assets/icons/bus.png",
|
||||||
|
"Bus",
|
||||||
|
"Transportation",
|
||||||
|
),
|
||||||
|
includedBox(
|
||||||
|
"assets/icons/clock.png",
|
||||||
|
"2 day 1 night",
|
||||||
|
"Duration",
|
||||||
|
),
|
||||||
|
includedBox(
|
||||||
|
"assets/icons/bx_qr.png",
|
||||||
|
"TAC200812695",
|
||||||
|
"Product code",
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
includedBox(
|
SizedBox(height: 30.h),
|
||||||
"assets/icons/bx_qr.png",
|
|
||||||
"TAC200812695",
|
Divider(color: Colors.black.withOpacity(0.2)),
|
||||||
"Product code",
|
SizedBox(height: 30.h),
|
||||||
|
Text(
|
||||||
|
"Exact Location",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.sp,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8.h),
|
||||||
|
|
||||||
|
CustomText(
|
||||||
|
text: "View the location on map",
|
||||||
|
size: 12.sp,
|
||||||
|
color: Colors.black.withOpacity(.6),
|
||||||
|
),
|
||||||
|
SizedBox(height: 17.h),
|
||||||
|
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(13.54.r),
|
||||||
|
child: Image.asset(
|
||||||
|
height: 178.7.h,
|
||||||
|
width: double.infinity,
|
||||||
|
"assets/images/attra_detail_map.png",
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 17.h),
|
||||||
|
|
||||||
|
CustomText(
|
||||||
|
text:
|
||||||
|
"Angkor Mails Hotel \nNR6, Krong Siem Reap Cambodia",
|
||||||
|
size: 12.sp,
|
||||||
|
color: Colors.black.withOpacity(0.6),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 30.h),
|
||||||
|
|
||||||
|
Divider(color: Colors.black.withOpacity(0.2)),
|
||||||
|
SizedBox(height: 30.h),
|
||||||
|
Text(
|
||||||
|
"People frequently ask",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.sp,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 15.h),
|
||||||
|
|
||||||
|
faqBox(
|
||||||
|
"About this place",
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. A id diam nisl, non justo, in odio...",
|
||||||
|
() {},
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 15.h),
|
||||||
|
|
||||||
|
faqBox(
|
||||||
|
"Term and condition",
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. A id diam nisl, non justo, in odio...",
|
||||||
|
() {
|
||||||
|
Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
RouteConstants.termsAndCondition,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(height: 15.h),
|
||||||
|
|
||||||
|
faqBox(
|
||||||
|
"Cancellation Policy",
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. A id diam nisl, non justo, in odio...",
|
||||||
|
() {},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
SizedBox(height: 30.h),
|
},
|
||||||
|
|
||||||
Divider(color: Colors.black.withOpacity(0.2)),
|
|
||||||
SizedBox(height: 30.h),
|
|
||||||
Text(
|
|
||||||
"Exact Location",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18.sp,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 8.h),
|
|
||||||
|
|
||||||
CustomText(
|
|
||||||
text: "View the location on map",
|
|
||||||
size: 12.sp,
|
|
||||||
color: Colors.black.withOpacity(.6),
|
|
||||||
),
|
|
||||||
SizedBox(height: 17.h),
|
|
||||||
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(13.54.r),
|
|
||||||
child: Image.asset(
|
|
||||||
height: 178.7.h,
|
|
||||||
width: double.infinity,
|
|
||||||
"assets/images/attra_detail_map.png",
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 17.h),
|
|
||||||
|
|
||||||
CustomText(
|
|
||||||
text:
|
|
||||||
"Angkor Mails Hotel \nNR6, Krong Siem Reap Cambodia",
|
|
||||||
size: 12.sp,
|
|
||||||
color: Colors.black.withOpacity(0.6),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 30.h),
|
|
||||||
|
|
||||||
Divider(color: Colors.black.withOpacity(0.2)),
|
|
||||||
SizedBox(height: 30.h),
|
|
||||||
Text(
|
|
||||||
"People frequently ask",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18.sp,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 15.h),
|
|
||||||
|
|
||||||
faqBox(
|
|
||||||
"About this place",
|
|
||||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. A id diam nisl, non justo, in odio...",
|
|
||||||
() {},
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 15.h),
|
|
||||||
|
|
||||||
faqBox(
|
|
||||||
"Term and condition",
|
|
||||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. A id diam nisl, non justo, in odio...",
|
|
||||||
() {
|
|
||||||
Navigator.pushNamed(
|
|
||||||
context,
|
|
||||||
RouteConstants.termsAndCondition,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SizedBox(height: 15.h),
|
|
||||||
|
|
||||||
faqBox(
|
|
||||||
"Cancellation Policy",
|
|
||||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. A id diam nisl, non justo, in odio...",
|
|
||||||
() {},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import 'package:citycards_customer/attraction_details/bloc/attraction_details_bloc.dart';
|
||||||
import 'package:citycards_customer/common_packages/app_bar.dart';
|
import 'package:citycards_customer/common_packages/app_bar.dart';
|
||||||
import 'package:citycards_customer/common_packages/back_widget.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/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import '../../attraction_details/bloc/attraction_details_event.dart';
|
||||||
import '../../common_packages/custom_search_field.dart';
|
import '../../common_packages/custom_search_field.dart';
|
||||||
import '../blocs/attractions_bloc.dart';
|
import '../blocs/attractions_bloc.dart';
|
||||||
import '../repository/attractions_repository.dart';
|
import '../repository/attractions_repository.dart';
|
||||||
@@ -15,22 +18,27 @@ class AttractionsPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return MultiBlocProvider(
|
||||||
|
providers: [
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) {
|
||||||
|
final bloc = AttractionsBloc(AttractionsRepository());
|
||||||
|
// 🔥 Trigger event based on source
|
||||||
|
if (source == "home") {
|
||||||
|
bloc.add(LoadAttractions());
|
||||||
|
} else {
|
||||||
|
print("QR Passss -=------------------");
|
||||||
|
context.read<AttractionDetailsBloc>().add(SetFlowFromPass(true));
|
||||||
|
bloc.add(LoadMyPassAttraction());
|
||||||
|
}
|
||||||
|
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
BlocProvider(create: (_) => AttractionDetailsBloc(),
|
||||||
|
|
||||||
|
)
|
||||||
return BlocProvider(
|
],
|
||||||
create: (_) {
|
|
||||||
final bloc = AttractionsBloc(AttractionsRepository());
|
|
||||||
|
|
||||||
// 🔥 Trigger event based on source
|
|
||||||
if (source == "home") {
|
|
||||||
bloc.add(LoadAttractions());
|
|
||||||
} else if (source == "qrPass") {
|
|
||||||
bloc.add(LoadMyPassAttraction());
|
|
||||||
}
|
|
||||||
|
|
||||||
return bloc;
|
|
||||||
},
|
|
||||||
child: BlocBuilder<AttractionsBloc, AttractionsState>(
|
child: BlocBuilder<AttractionsBloc, AttractionsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final bloc = context.read<AttractionsBloc>();
|
final bloc = context.read<AttractionsBloc>();
|
||||||
|
|||||||
@@ -11,7 +11,12 @@ class AttractionCard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: (){
|
onTap: (){
|
||||||
Navigator.of(context).pushNamed(RouteConstants.attractionDetails);
|
print("the value of from page this pushed ${ModalRoute.of(context)?.settings.arguments}");
|
||||||
|
Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
RouteConstants.attractionDetails,
|
||||||
|
arguments: ModalRoute.of(context)?.settings.arguments, // FORWARD
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
||||||
|
|||||||
63
lib/checkout/bloc/email_verify_bloc.dart
Normal file
63
lib/checkout/bloc/email_verify_bloc.dart
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
/// EVENTS
|
||||||
|
abstract class EmailVerify {}
|
||||||
|
|
||||||
|
class SetEmailEvent extends EmailVerify {
|
||||||
|
final String email;
|
||||||
|
SetEmailEvent(this.email);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CheckOtpFilled extends EmailVerify {
|
||||||
|
final bool isOtpFilled;
|
||||||
|
CheckOtpFilled(this.isOtpFilled);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CheckIsLoggedIn extends EmailVerify{}
|
||||||
|
|
||||||
|
/// STATE
|
||||||
|
class EmailVerifyState {
|
||||||
|
final String email;
|
||||||
|
final bool isOtpFilled;
|
||||||
|
final bool loggedIn;
|
||||||
|
|
||||||
|
EmailVerifyState({
|
||||||
|
required this.email,
|
||||||
|
required this.isOtpFilled,
|
||||||
|
required this.loggedIn
|
||||||
|
});
|
||||||
|
|
||||||
|
EmailVerifyState copyWith({
|
||||||
|
String? email,
|
||||||
|
bool? isOtpFilled,
|
||||||
|
bool? loggedIn
|
||||||
|
}) {
|
||||||
|
return EmailVerifyState(
|
||||||
|
email: email ?? this.email,
|
||||||
|
isOtpFilled: isOtpFilled ?? this.isOtpFilled,
|
||||||
|
loggedIn: loggedIn ?? this.loggedIn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// BLOC
|
||||||
|
class EmailVerifyBloc extends Bloc<EmailVerify, EmailVerifyState> {
|
||||||
|
EmailVerifyBloc()
|
||||||
|
: super(EmailVerifyState(email: "", isOtpFilled: false,
|
||||||
|
loggedIn: false
|
||||||
|
)) {
|
||||||
|
|
||||||
|
on<SetEmailEvent>((event, emit) {
|
||||||
|
emit(state.copyWith(email: event.email));
|
||||||
|
});
|
||||||
|
|
||||||
|
on<CheckOtpFilled>((event, emit) {
|
||||||
|
emit(state.copyWith(isOtpFilled: event.isOtpFilled));
|
||||||
|
});
|
||||||
|
|
||||||
|
on<CheckIsLoggedIn>((event,emit){
|
||||||
|
emit(state.copyWith(loggedIn: true));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
15
lib/checkout/repository/auth_local_repository.dart
Normal file
15
lib/checkout/repository/auth_local_repository.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class LocalAuth {
|
||||||
|
Future<void> setloggedIn(bool islogged)async{
|
||||||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setBool('islogged', islogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> getloggedIn()async{
|
||||||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getBool('islogged') ?? false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:citycards_customer/checkout/bloc/email_verify_bloc.dart';
|
||||||
|
import 'package:citycards_customer/checkout/repository/auth_local_repository.dart';
|
||||||
import 'package:citycards_customer/checkout/widget/all_coupons_bottomsheet.dart';
|
import 'package:citycards_customer/checkout/widget/all_coupons_bottomsheet.dart';
|
||||||
import 'package:citycards_customer/checkout/widget/login_email_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/app_bar.dart';
|
||||||
@@ -5,6 +7,7 @@ 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_text.dart';
|
||||||
import 'package:citycards_customer/common_packages/custom_dashed_line.dart';
|
import 'package:citycards_customer/common_packages/custom_dashed_line.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
class CheckoutView extends StatelessWidget {
|
class CheckoutView extends StatelessWidget {
|
||||||
@@ -12,356 +15,383 @@ class CheckoutView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return BlocProvider(
|
||||||
resizeToAvoidBottomInset: true,
|
create: (context) => EmailVerifyBloc(),
|
||||||
backgroundColor: Colors.white,
|
child: Scaffold(
|
||||||
body: SafeArea(
|
resizeToAvoidBottomInset: true,
|
||||||
child: Padding(
|
backgroundColor: Colors.white,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
body: SafeArea(
|
||||||
child: Column(
|
child: Padding(
|
||||||
children: [
|
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||||
CommonAppBar(
|
child: Column(
|
||||||
isWhiteLogo: false,
|
children: [
|
||||||
isProfilePage: false,
|
CommonAppBar(
|
||||||
showCart: false,
|
isWhiteLogo: false,
|
||||||
showDivider: true,
|
isProfilePage: false,
|
||||||
),
|
showCart: false,
|
||||||
Row(
|
showDivider: true,
|
||||||
children: [
|
),
|
||||||
GestureDetector(
|
Row(
|
||||||
onTap: () {
|
children: [
|
||||||
Navigator.pop(context);
|
GestureDetector(
|
||||||
},
|
onTap: () {
|
||||||
child: Icon(Icons.arrow_back),
|
Navigator.pop(context);
|
||||||
),
|
},
|
||||||
SizedBox(width: 8.w),
|
child: Icon(Icons.arrow_back),
|
||||||
CustomText(text: "Checkout", size: 12.sp),
|
),
|
||||||
],
|
SizedBox(width: 8.w),
|
||||||
),
|
CustomText(text: "Checkout", size: 12.sp),
|
||||||
|
],
|
||||||
SizedBox(height: 22.h),
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
border: Border.all(color: Color(0xFFF95FAF).withOpacity(0.2)),
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
),
|
),
|
||||||
child: Expanded(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(8.r),
|
|
||||||
bottomLeft: Radius.circular(8.r),
|
|
||||||
),
|
|
||||||
child: Image.asset(
|
|
||||||
"assets/images/card_banner.png",
|
|
||||||
scale: 4,
|
|
||||||
width: 105.w,
|
|
||||||
height: 123.h,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 6.66.w),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
CustomText(
|
|
||||||
text: "Melbourne",
|
|
||||||
weight: FontWeight.w500,
|
|
||||||
size: 16.sp,
|
|
||||||
),
|
|
||||||
SizedBox(height: 5.h),
|
|
||||||
CustomText(
|
|
||||||
text: "2 Days",
|
|
||||||
color: Color(0xFF8E8E8E),
|
|
||||||
size: 12.sp,
|
|
||||||
),
|
|
||||||
SizedBox(height: 5.h),
|
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(height: 22.h),
|
||||||
width: MediaQuery.of(context).size.width * .5,
|
Container(
|
||||||
child: Row(
|
decoration: BoxDecoration(
|
||||||
mainAxisAlignment:
|
color: Colors.white,
|
||||||
MainAxisAlignment.spaceBetween,
|
border: Border.all(
|
||||||
|
color: Color(0xFFF95FAF).withOpacity(0.2),
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(8.r),
|
||||||
|
bottomLeft: Radius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
"assets/images/card_banner.png",
|
||||||
|
scale: 4,
|
||||||
|
width: 105.w,
|
||||||
|
height: 123.h,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 6.66.w),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
CustomText(
|
||||||
|
text: "Melbourne",
|
||||||
|
weight: FontWeight.w500,
|
||||||
|
size: 16.sp,
|
||||||
|
),
|
||||||
|
SizedBox(height: 5.h),
|
||||||
|
CustomText(
|
||||||
|
text: "2 Days",
|
||||||
|
color: Color(0xFF8E8E8E),
|
||||||
|
size: 12.sp,
|
||||||
|
),
|
||||||
|
SizedBox(height: 5.h),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width * .5,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/icons/adult.png',
|
||||||
|
scale: 4,
|
||||||
|
),
|
||||||
|
SizedBox(width: 4.w),
|
||||||
|
CustomText(
|
||||||
|
text: "3 adults",
|
||||||
|
color: Color(0xFF8E8E8E),
|
||||||
|
size: 12.sp,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/icons/qty.png',
|
||||||
|
scale: 4,
|
||||||
|
),
|
||||||
|
SizedBox(width: 4.w),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 5.h),
|
||||||
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Image.asset(
|
||||||
children: [
|
"assets/icons/kid.png",
|
||||||
Image.asset(
|
scale: 4,
|
||||||
'assets/icons/adult.png',
|
),
|
||||||
scale: 4,
|
SizedBox(width: 4.w),
|
||||||
),
|
CustomText(
|
||||||
SizedBox(width: 4.w),
|
text: "3 Kids",
|
||||||
CustomText(
|
color: Color(0xFF8E8E8E),
|
||||||
text: "3 adults",
|
size: 12.sp,
|
||||||
color: Color(0xFF8E8E8E),
|
|
||||||
size: 12.sp,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
|
||||||
Row(
|
SizedBox(width: 53.w),
|
||||||
children: [
|
|
||||||
Image.asset(
|
CustomText(
|
||||||
'assets/icons/qty.png',
|
text: "\$49.50",
|
||||||
scale: 4,
|
size: 24.sp,
|
||||||
),
|
weight: FontWeight.w500,
|
||||||
SizedBox(width: 4.w),
|
color: Color(0xFFF95F62),
|
||||||
Text.rich(
|
),
|
||||||
TextSpan(
|
],
|
||||||
children: [
|
),
|
||||||
TextSpan(
|
],
|
||||||
text: "Qty:",
|
),
|
||||||
style: TextStyle(
|
],
|
||||||
color: Color(0xFF8E8E8E),
|
),
|
||||||
fontSize: 12.sp,
|
|
||||||
),
|
Container(
|
||||||
),
|
width: 35.w,
|
||||||
TextSpan(
|
height: 123.h,
|
||||||
text: " 2",
|
decoration: BoxDecoration(
|
||||||
style: TextStyle(
|
color: Color(0xFFF95FAF),
|
||||||
color: Color(0xFF000000),
|
borderRadius: BorderRadius.only(
|
||||||
fontSize: 12.sp,
|
bottomRight: Radius.circular(8.r),
|
||||||
fontWeight: FontWeight.w500,
|
topRight: Radius.circular(8.r),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
child: RotatedBox(
|
||||||
),
|
quarterTurns: -1,
|
||||||
),
|
child: Center(
|
||||||
],
|
child: RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: "Flexi ",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: "Card",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 12.sp,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
SizedBox(height: 5.h),
|
SizedBox(height: 15.h),
|
||||||
Row(
|
Container(
|
||||||
children: [
|
padding: EdgeInsets.symmetric(
|
||||||
Image.asset("assets/icons/kid.png", scale: 4),
|
horizontal: 12.w,
|
||||||
SizedBox(width: 4.w),
|
vertical: 12.h,
|
||||||
CustomText(
|
),
|
||||||
text: "3 Kids",
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF8E8E8E),
|
color: Color(0xFFFFF5F5),
|
||||||
size: 12.sp,
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
),
|
border: Border.all(
|
||||||
|
color: Color(0xFFBB474A).withOpacity(0.4),
|
||||||
SizedBox(width: 53.w),
|
width: 0.8,
|
||||||
|
),
|
||||||
CustomText(
|
),
|
||||||
text: "\$49.50",
|
child: Row(
|
||||||
size: 24.sp,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
weight: FontWeight.w500,
|
children: [
|
||||||
color: Color(0xFFF95F62),
|
Column(
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
],
|
children: [
|
||||||
|
CustomText(
|
||||||
|
text: "Get 10% off on your first trip",
|
||||||
|
color: Color(0xFF262626),
|
||||||
|
size: 14.sp,
|
||||||
|
),
|
||||||
|
SizedBox(height: 7.h),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
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)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
const Spacer(),
|
||||||
Container(
|
Container(
|
||||||
width: 35.w,
|
padding: EdgeInsets.symmetric(
|
||||||
height: 123.h,
|
horizontal: 20.w,
|
||||||
decoration: BoxDecoration(
|
vertical: 10.h,
|
||||||
color: Color(0xFFF95FAF),
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
bottomRight: Radius.circular(8.r),
|
|
||||||
topRight: Radius.circular(8.r),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: RotatedBox(
|
decoration: BoxDecoration(
|
||||||
quarterTurns: -1,
|
border: Border.all(color: Color(0xFFF95F62)),
|
||||||
child: Center(
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
child: RichText(
|
),
|
||||||
text: TextSpan(
|
child: CustomText(
|
||||||
children: [
|
text: "Apply",
|
||||||
TextSpan(
|
color: Color(0xFFF95F62),
|
||||||
text: "Flexi ",
|
size: 14.sp,
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16.sp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: "Card",
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12.sp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 15.h),
|
SizedBox(height: 15.h),
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h),
|
DashedDivider(
|
||||||
decoration: BoxDecoration(
|
color: Color(0xFFACACAC),
|
||||||
color: Color(0xFFFFF5F5),
|
thickness: 1.h,
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
dashLength: 4,
|
||||||
border: Border.all(
|
dashSpace: 4,
|
||||||
color: Color(0xFFBB474A).withOpacity(0.4),
|
|
||||||
width: 0.8,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Row(
|
SizedBox(height: 10.h),
|
||||||
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
CustomText(text: "Subtotal", size: 14.sp),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
CustomText(
|
||||||
children: [
|
text: "\$49.50",
|
||||||
CustomText(
|
size: 14.sp,
|
||||||
text: "Get 10% off on your first trip",
|
weight: FontWeight.w500,
|
||||||
color: Color(0xFF262626),
|
|
||||||
size: 14.sp,
|
|
||||||
),
|
|
||||||
SizedBox(height: 7.h),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
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)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
const Spacer(),
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 20.w,
|
|
||||||
vertical: 10.h,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(color: Color(0xFFF95F62)),
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
),
|
|
||||||
child: CustomText(
|
|
||||||
text: "Apply",
|
|
||||||
color: Color(0xFFF95F62),
|
|
||||||
size: 14.sp,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: 14.h),
|
||||||
|
Row(
|
||||||
SizedBox(height: 15.h),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
DashedDivider(
|
CustomText(text: "Discount", size: 14.sp),
|
||||||
color: Color(0xFFACACAC),
|
CustomText(
|
||||||
thickness: 1.h,
|
text: "-7.20%",
|
||||||
dashLength: 4,
|
size: 14.sp,
|
||||||
dashSpace: 4,
|
weight: FontWeight.w500,
|
||||||
),
|
|
||||||
SizedBox(height: 10.h),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
CustomText(text: "Subtotal", size: 14.sp),
|
|
||||||
CustomText(
|
|
||||||
text: "\$49.50",
|
|
||||||
size: 14.sp,
|
|
||||||
weight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 14.h),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
CustomText(text: "Discount", size: 14.sp),
|
|
||||||
CustomText(
|
|
||||||
text: "-7.20%",
|
|
||||||
size: 14.sp,
|
|
||||||
weight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 10.h),
|
|
||||||
DashedDivider(
|
|
||||||
color: Color(0xFFACACAC),
|
|
||||||
thickness: 1.h,
|
|
||||||
dashLength: 4,
|
|
||||||
dashSpace: 4,
|
|
||||||
),
|
|
||||||
SizedBox(height: 10.h),
|
|
||||||
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
CustomText(text: 'Total', size: 14.sp),
|
|
||||||
SizedBox(height: 4.h),
|
|
||||||
CustomText(
|
|
||||||
text: "Including \$2.24 in taxes",
|
|
||||||
size: 12.sp,
|
|
||||||
color: Colors.black.withOpacity(0.6),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
CustomText(
|
),
|
||||||
text: "\$42.60",
|
SizedBox(height: 10.h),
|
||||||
size: 24.sp,
|
DashedDivider(
|
||||||
weight: FontWeight.w500,
|
color: Color(0xFFACACAC),
|
||||||
),
|
thickness: 1.h,
|
||||||
],
|
dashLength: 4,
|
||||||
),
|
dashSpace: 4,
|
||||||
const Spacer(),
|
),
|
||||||
CustomFilledButton(
|
SizedBox(height: 10.h),
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
Row(
|
||||||
backgroundColor: Colors.white,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
context: context,
|
children: [
|
||||||
isScrollControlled: true,
|
Expanded(
|
||||||
shape: RoundedRectangleBorder(
|
child: Column(
|
||||||
borderRadius: BorderRadius.vertical(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
top: Radius.circular(12.r),
|
children: [
|
||||||
|
CustomText(text: 'Total', size: 14.sp),
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
CustomText(
|
||||||
|
text: "Including \$2.24 in taxes",
|
||||||
|
size: 12.sp,
|
||||||
|
color: Colors.black.withOpacity(0.6),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
builder: (_) => const LoginEmailBottomsheet(),
|
CustomText(
|
||||||
);
|
text: "\$42.60",
|
||||||
},
|
size: 24.sp,
|
||||||
width: double.infinity,
|
weight: FontWeight.w500,
|
||||||
label: "Login to Checkout",
|
),
|
||||||
),
|
],
|
||||||
SizedBox(height: 25.h),
|
),
|
||||||
],
|
const Spacer(),
|
||||||
|
FutureBuilder(
|
||||||
|
future: LocalAuth().getloggedIn(),
|
||||||
|
builder: (context, snap) {
|
||||||
|
final isLoggedIn = snap.data ?? false;
|
||||||
|
return BlocBuilder<EmailVerifyBloc, EmailVerifyState>(
|
||||||
|
builder: (context, state){
|
||||||
|
return CustomFilledButton(
|
||||||
|
onTap: () async {
|
||||||
|
final rootContext = context;
|
||||||
|
showModalBottomSheet(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.circular(12.r),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
builder: (_) => BlocProvider(
|
||||||
|
create: (rootContext) => EmailVerifyBloc(),
|
||||||
|
child: LoginEmailBottomsheet(
|
||||||
|
rootContext: rootContext,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
width: double.infinity,
|
||||||
|
label: isLoggedIn || state.loggedIn ? "Proceed to Checkouts" :"Login to Checkout",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(height: 25.h),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,12 +1,35 @@
|
|||||||
|
import 'package:citycards_customer/checkout/bloc/email_verify_bloc.dart';
|
||||||
import 'package:citycards_customer/checkout/widget/verify_otp_bottomsheet.dart';
|
import 'package:citycards_customer/checkout/widget/verify_otp_bottomsheet.dart';
|
||||||
import 'package:citycards_customer/common_packages/custom_filled_button.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_text.dart';
|
||||||
import 'package:citycards_customer/core/route_constants.dart';
|
import 'package:citycards_customer/core/route_constants.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
class LoginEmailBottomsheet extends StatelessWidget {
|
class LoginEmailBottomsheet extends StatefulWidget {
|
||||||
const LoginEmailBottomsheet({super.key});
|
final BuildContext rootContext;
|
||||||
|
LoginEmailBottomsheet({super.key, required this.rootContext});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LoginEmailBottomsheet> createState() => _LoginEmailBottomsheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginEmailBottomsheetState extends State<LoginEmailBottomsheet> {
|
||||||
|
TextEditingController emailController = TextEditingController();
|
||||||
|
String? emailError;
|
||||||
|
|
||||||
|
bool emailValidate() {
|
||||||
|
final emailRegex = RegExp(r'^[\w\.-]+@[\w\.-]+\.\w+$');
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
emailError = !emailRegex.hasMatch(emailController.text.trim())
|
||||||
|
? "Invalid email format"
|
||||||
|
: null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return emailError == null;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -25,7 +48,11 @@ class LoginEmailBottomsheet extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Image.asset("assets/logo/logo_city_cards_orange.png", scale: 4),
|
Image.asset("assets/logo/logo_city_cards_orange.png", scale: 4),
|
||||||
SizedBox(height: 8.h),
|
SizedBox(height: 8.h),
|
||||||
CustomText(text: "Get Started", size: 18.sp, weight: FontWeight.w500),
|
CustomText(
|
||||||
|
text: "Get Started",
|
||||||
|
size: 18.sp,
|
||||||
|
weight: FontWeight.w500,
|
||||||
|
),
|
||||||
SizedBox(height: 42.h),
|
SizedBox(height: 42.h),
|
||||||
CustomText(
|
CustomText(
|
||||||
text: "Enter your email to begin your CityCards journey",
|
text: "Enter your email to begin your CityCards journey",
|
||||||
@@ -35,19 +62,49 @@ class LoginEmailBottomsheet extends StatelessWidget {
|
|||||||
SizedBox(height: 12.h),
|
SizedBox(height: 12.h),
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
|
controller: emailController,
|
||||||
|
onChanged: (val) {
|
||||||
|
final bloc = context.read<EmailVerifyBloc>();
|
||||||
|
setState(() => emailValidate());
|
||||||
|
bloc.add(SetEmailEvent(val));
|
||||||
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
errorText: emailError,
|
||||||
filled: true,
|
filled: true,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 6.h),
|
contentPadding: EdgeInsets.symmetric(vertical: 6.h),
|
||||||
fillColor: const Color(0xFFFFF5F5),
|
fillColor: const Color(0xFFFFF5F5),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: const Color(0xFFBB474A), width: 0.4.w),
|
borderSide: BorderSide(
|
||||||
|
color: const Color(0xFFBB474A),
|
||||||
|
width: 0.4.w,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.sp),
|
||||||
|
),
|
||||||
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: const Color(0xFFBB474A),
|
||||||
|
width: 0.4.w,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.sp),
|
||||||
|
),
|
||||||
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: const Color(0xFFBB474A),
|
||||||
|
width: 0.4.w,
|
||||||
|
),
|
||||||
borderRadius: BorderRadius.circular(8.sp),
|
borderRadius: BorderRadius.circular(8.sp),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: const Color(0xFFBB474A), width: 0.4.w),
|
borderSide: BorderSide(
|
||||||
|
color: const Color(0xFFBB474A),
|
||||||
|
width: 0.4.w,
|
||||||
|
),
|
||||||
borderRadius: BorderRadius.circular(8.sp),
|
borderRadius: BorderRadius.circular(8.sp),
|
||||||
),
|
),
|
||||||
prefixIcon: const Icon(Icons.email_outlined, color: Color(0xFFF95F62)),
|
prefixIcon: const Icon(
|
||||||
|
Icons.email_outlined,
|
||||||
|
color: Color(0xFFF95F62),
|
||||||
|
),
|
||||||
hintText: "john.doe@gmail.com",
|
hintText: "john.doe@gmail.com",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
color: const Color(0xFF000000).withOpacity(0.6),
|
color: const Color(0xFF000000).withOpacity(0.6),
|
||||||
@@ -59,18 +116,23 @@ class LoginEmailBottomsheet extends StatelessWidget {
|
|||||||
SizedBox(height: 38.h),
|
SizedBox(height: 38.h),
|
||||||
CustomFilledButton(
|
CustomFilledButton(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
if (emailValidate()) {
|
||||||
showModalBottomSheet(
|
Navigator.pop(context);
|
||||||
context: context,
|
showModalBottomSheet(
|
||||||
backgroundColor: Colors.white,
|
context: context,
|
||||||
isScrollControlled: true,
|
backgroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(
|
isScrollControlled: true,
|
||||||
borderRadius: BorderRadius.vertical(
|
shape: RoundedRectangleBorder(
|
||||||
top: Radius.circular(12.r),
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.circular(12.r),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
builder: (_) => BlocProvider(
|
||||||
builder: (_) => VerifyOtpBottomsheet(),
|
create: (rootcontext) => EmailVerifyBloc(),
|
||||||
);
|
child: VerifyOtpBottomsheet(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
label: "Continue",
|
label: "Continue",
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@@ -78,7 +140,7 @@ class LoginEmailBottomsheet extends StatelessWidget {
|
|||||||
|
|
||||||
SizedBox(height: 20.h),
|
SizedBox(height: 20.h),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: (){
|
onTap: () {
|
||||||
Navigator.of(context).pushNamed(RouteConstants.createAcct);
|
Navigator.of(context).pushNamed(RouteConstants.createAcct);
|
||||||
},
|
},
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import 'package:citycards_customer/checkout/bloc/email_verify_bloc.dart';
|
||||||
|
import 'package:citycards_customer/checkout/repository/auth_local_repository.dart';
|
||||||
import 'package:citycards_customer/common_packages/custom_filled_button.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_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_otp_text_field/flutter_otp_text_field.dart';
|
import 'package:flutter_otp_text_field/flutter_otp_text_field.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
@@ -25,64 +28,88 @@ class VerifyOtpBottomsheet extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min, // shrink to fit content
|
mainAxisSize: MainAxisSize.min, // shrink to fit content
|
||||||
children: [
|
children: [
|
||||||
Image.asset("assets/logo/logo_city_cards_orange.png", scale: 4),
|
Image.asset("assets/logo/logo_city_cards_orange.png", scale: 4),
|
||||||
|
|
||||||
SizedBox(height: 8.h),
|
SizedBox(height: 8.h),
|
||||||
|
|
||||||
CustomText(
|
CustomText(
|
||||||
text: "Verify your phone",
|
text: "Verify your phone",
|
||||||
size: 18.sp,
|
size: 18.sp,
|
||||||
weight: FontWeight.w500,
|
weight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 42.h),
|
SizedBox(height: 42.h),
|
||||||
Text.rich(
|
|
||||||
TextSpan(
|
BlocBuilder<EmailVerifyBloc, EmailVerifyState>(
|
||||||
children: [
|
builder: (context, state) {
|
||||||
|
return Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: "Enter the verification code sent to your email id",
|
children: [
|
||||||
style: TextStyle(
|
TextSpan(
|
||||||
fontSize: 14.sp,
|
text:
|
||||||
color: Colors.black.withOpacity(0.6),
|
"Enter the verification code sent to your email id: ",
|
||||||
),
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: Colors.black.withOpacity(0.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: " ${state.email}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
TextSpan(
|
);
|
||||||
text: " frank7824@mail.com",
|
},
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 15.h),
|
SizedBox(height: 15.h),
|
||||||
|
|
||||||
OtpTextField(
|
BlocBuilder<EmailVerifyBloc, EmailVerifyState>(
|
||||||
numberOfFields: 6,
|
builder: (context, state) {
|
||||||
borderWidth: 0.4.w,
|
final bloc = (context).read<EmailVerifyBloc>();
|
||||||
fieldWidth: 48.w,
|
return OtpTextField(
|
||||||
fieldHeight: 60.h,
|
numberOfFields: 6,
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
borderWidth: 0.4.w,
|
||||||
filled: true,
|
fieldWidth: 48.w,
|
||||||
fillColor: const Color(0xFFFFF5F5),
|
fieldHeight: 60.h,
|
||||||
borderColor: const Color(0xFFBB474A),
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
cursorColor: const Color(0xFFF95F62),
|
filled: true,
|
||||||
showFieldAsBox: true,
|
fillColor: const Color(0xFFFFF5F5),
|
||||||
textStyle: TextStyle(
|
borderColor: const Color(0xFFBB474A),
|
||||||
fontSize: 18.sp,
|
cursorColor: const Color(0xFFF95F62),
|
||||||
fontWeight: FontWeight.w500,
|
showFieldAsBox: true,
|
||||||
),
|
textStyle: TextStyle(
|
||||||
onCodeChanged: (code) {},
|
fontSize: 18.sp,
|
||||||
onSubmit: (code) {
|
fontWeight: FontWeight.w500,
|
||||||
debugPrint("OTP entered: $code");
|
),
|
||||||
|
onCodeChanged: (code) {},
|
||||||
|
onSubmit: (code) {
|
||||||
|
bloc.add(CheckOtpFilled(true));
|
||||||
|
debugPrint("OTP entered: $code");
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 42.h),
|
SizedBox(height: 42.h),
|
||||||
CustomFilledButton(
|
BlocBuilder<EmailVerifyBloc, EmailVerifyState>(
|
||||||
onTap: () {
|
builder: (context, state) {
|
||||||
Navigator.pop(context);
|
return CustomFilledButton(
|
||||||
|
onTap: () async {
|
||||||
|
if (state.isOtpFilled) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
await LocalAuth().setloggedIn(true);
|
||||||
|
context.read<EmailVerifyBloc>().add(CheckIsLoggedIn());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: "Continue",
|
||||||
|
width: double.infinity,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
label: "Continue",
|
|
||||||
width: double.infinity,
|
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 20.h),
|
SizedBox(height: 20.h),
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import 'package:citycards_customer/itinerary_creation/views/itinerary_creation_v
|
|||||||
import 'package:citycards_customer/itinerary_creation/views/magic_itinerary_empty_view.dart';
|
import 'package:citycards_customer/itinerary_creation/views/magic_itinerary_empty_view.dart';
|
||||||
import 'package:citycards_customer/itinerary_creation/views/magic_itinerary_filled_view.dart';
|
import 'package:citycards_customer/itinerary_creation/views/magic_itinerary_filled_view.dart';
|
||||||
import 'package:citycards_customer/offer_pass_detail/offer_pass_detail_view.dart';
|
import 'package:citycards_customer/offer_pass_detail/offer_pass_detail_view.dart';
|
||||||
|
import 'package:citycards_customer/postcard/views/postcard_creation_page_view.dart';
|
||||||
import 'package:citycards_customer/privacy/privacy_view.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/bloc/search_offers_listing_bloc.dart';
|
||||||
import 'package:citycards_customer/search_offers/view/search_offers_with_listing.dart';
|
import 'package:citycards_customer/search_offers/view/search_offers_with_listing.dart';
|
||||||
@@ -231,6 +232,12 @@ class AppRouter {
|
|||||||
return RegisteredUserHomePage();
|
return RegisteredUserHomePage();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case RouteConstants.postCardCreationPage:
|
||||||
|
return MaterialPageRoute(builder: (_){
|
||||||
|
return PostcardCreationPage();
|
||||||
|
});
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) =>
|
builder: (_) =>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Widget buildOffstageNavigator(
|
|||||||
return IntroScreensView();
|
return IntroScreensView();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 🔹 Attractions Page
|
// 🔹 Attractions PageF
|
||||||
case RouteConstants.attractionsPage:
|
case RouteConstants.attractionsPage:
|
||||||
final args = settings.arguments as String;
|
final args = settings.arguments as String;
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
@@ -93,7 +93,7 @@ Widget buildOffstageNavigator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 🔹 Upload Photo Page (start of postcard creation flow)
|
// 🔹 Upload Photo Page (start of postcard creation flow)
|
||||||
case RouteConstants.uploadPhotoPage:
|
case RouteConstants.postCardCreationPage:
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider(
|
builder: (_) => BlocProvider(
|
||||||
create: (_) => PostcardCreationBloc(),
|
create: (_) => PostcardCreationBloc(),
|
||||||
|
|||||||
@@ -56,4 +56,5 @@ class RouteConstants {
|
|||||||
static const String qrPage = '/qrPage';
|
static const String qrPage = '/qrPage';
|
||||||
static const String makeBooking = '/makeBooking';
|
static const String makeBooking = '/makeBooking';
|
||||||
static const String bookingSuccessful = '/bookingSuccessful';
|
static const String bookingSuccessful = '/bookingSuccessful';
|
||||||
|
static const String postCardCreationPage = '/postCardCreationPage';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'attraction_details/bloc/attraction_details_bloc.dart';
|
||||||
import 'core/app_router.dart';
|
import 'core/app_router.dart';
|
||||||
import 'my_pass/blocs/my_pass_bloc.dart';
|
import 'my_pass/blocs/my_pass_bloc.dart';
|
||||||
|
|
||||||
@@ -38,6 +39,9 @@ class MyApp extends StatelessWidget {
|
|||||||
BlocProvider<MyPassBloc>(
|
BlocProvider<MyPassBloc>(
|
||||||
create: (_) => MyPassBloc()..add(LoadMyPasses()),
|
create: (_) => MyPassBloc()..add(LoadMyPasses()),
|
||||||
),
|
),
|
||||||
|
BlocProvider<AttractionDetailsBloc>(
|
||||||
|
create: (_) => AttractionDetailsBloc(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
onGenerateRoute: _appRouter.onGenerateRoute,
|
onGenerateRoute: _appRouter.onGenerateRoute,
|
||||||
|
|||||||
@@ -18,46 +18,44 @@ class PostcardCreationPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocBuilder<PostcardCreationBloc, PostcardCreationState>(
|
||||||
create: (_) => PostcardCreationBloc(),
|
builder: (context, state) {
|
||||||
child: BlocBuilder<PostcardCreationBloc, PostcardCreationState>(
|
Widget stepWidget;
|
||||||
builder: (context, state) {
|
switch (state.currentStep) {
|
||||||
Widget stepWidget;
|
case PostcardStep.uploadPhoto:
|
||||||
switch (state.currentStep) {
|
stepWidget = const UploadPhotoStepPageView();
|
||||||
case PostcardStep.uploadPhoto:
|
break;
|
||||||
stepWidget = const UploadPhotoStepPageView();
|
case PostcardStep.addFilter:
|
||||||
break;
|
stepWidget = const AddFilterStepPageView();
|
||||||
case PostcardStep.addFilter:
|
break;
|
||||||
stepWidget = const AddFilterStepPageView();
|
case PostcardStep.writeMessage:
|
||||||
break;
|
stepWidget = const WriteMessageStepPageView();
|
||||||
case PostcardStep.writeMessage:
|
break;
|
||||||
stepWidget = const WriteMessageStepPageView();
|
case PostcardStep.preview:
|
||||||
break;
|
stepWidget = const PreviewPostcardStepPageView();
|
||||||
case PostcardStep.preview:
|
break;
|
||||||
stepWidget = const PreviewPostcardStepPageView();
|
case PostcardStep.purchase:
|
||||||
break;
|
stepWidget = const PostcardPurchaseFormPageView();
|
||||||
case PostcardStep.purchase:
|
break;
|
||||||
stepWidget = const PostcardPurchaseFormPageView();
|
case PostcardStep.checkout:
|
||||||
break;
|
stepWidget = const PostcardCheckoutPageView();
|
||||||
case PostcardStep.checkout:
|
break;
|
||||||
stepWidget = const PostcardCheckoutPageView();
|
case PostcardStep.orderSuccess:
|
||||||
break;
|
stepWidget = const OrderSuccessPageView();
|
||||||
case PostcardStep.orderSuccess:
|
break;
|
||||||
stepWidget = const OrderSuccessPageView();
|
case PostcardStep.myOrders:
|
||||||
break;
|
stepWidget = const MyOrdersPageView();
|
||||||
case PostcardStep.myOrders:
|
break;
|
||||||
stepWidget = const MyOrdersPageView();
|
case PostcardStep.myOrderPostcardPreview:
|
||||||
break;
|
stepWidget = const OrderPostcardPreviewPageView();
|
||||||
case PostcardStep.myOrderPostcardPreview:
|
break;
|
||||||
stepWidget = const OrderPostcardPreviewPageView();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
body: SafeArea(child: stepWidget),
|
body: SafeArea(child: stepWidget),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class PostcardPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pushNamed(RouteConstants.uploadPhotoPage);
|
Navigator.of(context).pushNamed(RouteConstants.postCardCreationPage);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Lets Create",
|
"Lets Create",
|
||||||
|
|||||||
@@ -8,13 +8,71 @@ import '../blocs/postcard_creation_bloc.dart';
|
|||||||
import '../blocs/postcard_creation_events.dart';
|
import '../blocs/postcard_creation_events.dart';
|
||||||
import '../blocs/postcard_creation_state.dart';
|
import '../blocs/postcard_creation_state.dart';
|
||||||
|
|
||||||
class PostcardPurchaseFormPageView extends StatelessWidget {
|
class PostcardPurchaseFormPageView extends StatefulWidget {
|
||||||
const PostcardPurchaseFormPageView({super.key});
|
const PostcardPurchaseFormPageView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PostcardPurchaseFormPageView> createState() =>
|
||||||
|
_PostcardPurchaseFormPageViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostcardPurchaseFormPageViewState
|
||||||
|
extends State<PostcardPurchaseFormPageView> {
|
||||||
|
|
||||||
|
/// Controllers
|
||||||
|
final titleCtrl = TextEditingController();
|
||||||
|
final fullNameCtrl = TextEditingController();
|
||||||
|
final emailCtrl = TextEditingController();
|
||||||
|
final phoneCtrl = TextEditingController();
|
||||||
|
final cityCtrl = TextEditingController();
|
||||||
|
final zipCtrl = TextEditingController();
|
||||||
|
|
||||||
|
String? country;
|
||||||
|
String? stateName;
|
||||||
|
|
||||||
|
/// Error messages
|
||||||
|
String? titleError;
|
||||||
|
String? fullNameError;
|
||||||
|
String? emailError;
|
||||||
|
String? phoneError;
|
||||||
|
String? cityError;
|
||||||
|
String? countryError;
|
||||||
|
String? stateError;
|
||||||
|
String? zipError;
|
||||||
|
|
||||||
|
bool validate() {
|
||||||
|
final emailRegex = RegExp(r'^[\w\.-]+@[\w\.-]+\.\w+$');
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
titleError = titleCtrl.text.isEmpty ? "Required" : null;
|
||||||
|
fullNameError = fullNameCtrl.text.isEmpty ? "Required" : null;
|
||||||
|
emailError = !emailRegex.hasMatch(emailCtrl.text.trim())
|
||||||
|
? "Invalid email format"
|
||||||
|
: null;
|
||||||
|
|
||||||
|
phoneError = phoneCtrl.text.length < 10 ? "Invalid phone" : null;
|
||||||
|
cityError = cityCtrl.text.isEmpty ? "Required" : null;
|
||||||
|
countryError = country == null ? "Required" : null;
|
||||||
|
stateError = stateName == null ? "Required" : null;
|
||||||
|
zipError = zipCtrl.text.length < 4 ? "Invalid zip" : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return titleError == null &&
|
||||||
|
fullNameError == null &&
|
||||||
|
emailError == null &&
|
||||||
|
phoneError == null &&
|
||||||
|
cityError == null &&
|
||||||
|
countryError == null &&
|
||||||
|
stateError == null &&
|
||||||
|
zipError == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<PostcardCreationBloc, PostcardCreationState>(
|
return BlocBuilder<PostcardCreationBloc, PostcardCreationState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
|
||||||
final bloc = context.read<PostcardCreationBloc>();
|
final bloc = context.read<PostcardCreationBloc>();
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
@@ -23,8 +81,7 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
CommonAppBar(isWhiteLogo: false, isProfilePage: false, showDivider: true,),
|
CommonAppBar(isWhiteLogo: false, isProfilePage: false, showDivider: true),
|
||||||
|
|
||||||
// Order ID
|
// Order ID
|
||||||
Text(
|
Text(
|
||||||
"#78895436",
|
"#78895436",
|
||||||
@@ -36,7 +93,7 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
// Postcard image + title
|
// Title
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
@@ -58,24 +115,38 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: Column(
|
||||||
decoration: InputDecoration(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
hintText: "Add title",
|
children: [
|
||||||
hintStyle: GoogleFonts.poppins(
|
TextField(
|
||||||
color: const Color(0xff999999), fontSize: 14.sp),
|
controller: titleCtrl,
|
||||||
enabledBorder: const UnderlineInputBorder(
|
onChanged: (_) {
|
||||||
borderSide:
|
setState(() => titleError = null);
|
||||||
BorderSide(color: Color(0xffFDCDCE), width: 1),
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Add title",
|
||||||
|
hintStyle: GoogleFonts.poppins(
|
||||||
|
color: const Color(0xff999999),
|
||||||
|
fontSize: 14.sp),
|
||||||
|
enabledBorder: const UnderlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xffFDCDCE), width: 1),
|
||||||
|
),
|
||||||
|
focusedBorder: const UnderlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xffFDCDCE), width: 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
style: GoogleFonts.poppins(fontSize: 14.sp),
|
||||||
),
|
),
|
||||||
focusedBorder: const UnderlineInputBorder(
|
if (titleError != null)
|
||||||
borderSide:
|
Padding(
|
||||||
BorderSide(color: Color(0xffFDCDCE), width: 1),
|
padding: const EdgeInsets.only(top: 4),
|
||||||
),
|
child: Text(titleError!,
|
||||||
),
|
style: const TextStyle(
|
||||||
style: GoogleFonts.poppins(fontSize: 14.sp),
|
color: Colors.red, fontSize: 12)),
|
||||||
onChanged: (val) {
|
),
|
||||||
// You can dispatch event here: bloc.add(UpdateTitle(val));
|
],
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -83,7 +154,7 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
|
|
||||||
const SizedBox(height: 28),
|
const SizedBox(height: 28),
|
||||||
|
|
||||||
// Personal details section
|
// Personal details
|
||||||
Text(
|
Text(
|
||||||
"Add personal details",
|
"Add personal details",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -97,21 +168,45 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
_buildInputField(
|
_buildInputField(
|
||||||
label: "Full Name",
|
label: "Full Name",
|
||||||
hint: "Lorem Ipsum",
|
hint: "Lorem Ipsum",
|
||||||
|
controller: fullNameCtrl,
|
||||||
|
errorText: fullNameError,
|
||||||
|
onChanged: (_) {
|
||||||
|
setState(() => fullNameError = null);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
_buildInputField(
|
_buildInputField(
|
||||||
label: "Email ID",
|
label: "Email ID",
|
||||||
hint: "Lorem@gmail.com",
|
hint: "Lorem@gmail.com",
|
||||||
icon: Icons.email_outlined,
|
icon: Icons.email_outlined,
|
||||||
|
controller: emailCtrl,
|
||||||
|
errorText: emailError,
|
||||||
|
type: TextInputType.emailAddress,
|
||||||
|
onChanged: (_) {
|
||||||
|
setState(() => emailError = null);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
_buildInputField(
|
_buildInputField(
|
||||||
label: "Phone number",
|
label: "Phone number",
|
||||||
hint: "+91 9999 999 999",
|
hint: "+91 9999 999 999",
|
||||||
icon: Icons.phone_outlined,
|
icon: Icons.phone_outlined,
|
||||||
|
controller: phoneCtrl,
|
||||||
|
errorText: phoneError,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value.length > 10) {
|
||||||
|
phoneCtrl.text = value.substring(0, 10);
|
||||||
|
phoneCtrl.selection = TextSelection.fromPosition(
|
||||||
|
TextPosition(offset: phoneCtrl.text.length),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setState(() => phoneError = null);
|
||||||
|
},
|
||||||
|
type: TextInputType.number
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 28),
|
const SizedBox(height: 28),
|
||||||
|
|
||||||
// Address details section
|
|
||||||
Text(
|
Text(
|
||||||
"Add address details",
|
"Add address details",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -122,10 +217,51 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
_buildInputField(label: "City", hint: "Lorem Ipsum"),
|
_buildInputField(
|
||||||
_buildDropdownField(label: "Country", hint: "Lorem Ipsum"),
|
label: "City",
|
||||||
_buildDropdownField(label: "State", hint: "Lorem Ipsum"),
|
hint: "Lorem Ipsum",
|
||||||
_buildInputField(label: "Zip Code", hint: "000000"),
|
controller: cityCtrl,
|
||||||
|
errorText: cityError,
|
||||||
|
onChanged: (_) {
|
||||||
|
setState(() => cityError = null);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
_buildDropdownField(
|
||||||
|
label: "Country",
|
||||||
|
hint: "Lorem Ipsum",
|
||||||
|
value: country,
|
||||||
|
errorText: countryError,
|
||||||
|
onChanged: (val) {
|
||||||
|
setState(() {
|
||||||
|
country = val;
|
||||||
|
countryError = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
_buildDropdownField(
|
||||||
|
label: "State",
|
||||||
|
hint: "Lorem Ipsum",
|
||||||
|
value: stateName,
|
||||||
|
errorText: stateError,
|
||||||
|
onChanged: (val) {
|
||||||
|
setState(() {
|
||||||
|
stateName = val;
|
||||||
|
stateError = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
_buildInputField(
|
||||||
|
label: "Zip Code",
|
||||||
|
hint: "000000",
|
||||||
|
controller: zipCtrl,
|
||||||
|
errorText: zipError,
|
||||||
|
onChanged: (_) {
|
||||||
|
setState(() => zipError = null);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
|
|
||||||
@@ -134,7 +270,9 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
bloc.add(GoToNextStep());
|
if (validate()) {
|
||||||
|
bloc.add(GoToNextStep());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xffF95F62),
|
backgroundColor: const Color(0xffF95F62),
|
||||||
@@ -161,36 +299,39 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 🔹 Reusable text field widget
|
/// TEXT FIELD (NO UI CHANGES)
|
||||||
Widget _buildInputField({
|
Widget _buildInputField({
|
||||||
required String label,
|
required String label,
|
||||||
required String hint,
|
required String hint,
|
||||||
|
required TextEditingController controller,
|
||||||
|
required Function(String) onChanged,
|
||||||
|
String? errorText,
|
||||||
IconData? icon,
|
IconData? icon,
|
||||||
|
TextInputType? type
|
||||||
}) {
|
}) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 18),
|
padding: const EdgeInsets.only(bottom: 18),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(label,
|
||||||
label,
|
style: GoogleFonts.poppins(
|
||||||
style: GoogleFonts.poppins(
|
fontSize: 13.sp,
|
||||||
fontSize: 13.sp,
|
fontWeight: FontWeight.w500,
|
||||||
fontWeight: FontWeight.w500,
|
color: const Color(0xff1A1A1A))),
|
||||||
color: const Color(0xff1A1A1A),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
TextField(
|
TextField(
|
||||||
|
controller: controller,
|
||||||
|
onChanged: onChanged,
|
||||||
|
keyboardType: type,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: hint,
|
hintText: hint,
|
||||||
hintStyle: GoogleFonts.poppins(
|
hintStyle: GoogleFonts.poppins(
|
||||||
color: const Color(0xff999999),
|
color: const Color(0xff999999),
|
||||||
fontSize: 14.sp,
|
fontSize: 14.sp,
|
||||||
),
|
),
|
||||||
suffixIcon: icon != null
|
suffixIcon:
|
||||||
? Icon(icon, color: Colors.black, size: 20)
|
icon != null ? Icon(icon, color: Colors.black, size: 20) : null,
|
||||||
: null,
|
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
|
const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
@@ -203,32 +344,38 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (errorText != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4),
|
||||||
|
child: Text(errorText!,
|
||||||
|
style: const TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 🔹 Dropdown input
|
/// DROPDOWN FIELD (NO UI CHANGES)
|
||||||
Widget _buildDropdownField({
|
Widget _buildDropdownField({
|
||||||
required String label,
|
required String label,
|
||||||
required String hint,
|
required String hint,
|
||||||
|
required String? value,
|
||||||
|
required Function(String?) onChanged,
|
||||||
|
String? errorText,
|
||||||
}) {
|
}) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 18),
|
padding: const EdgeInsets.only(bottom: 18),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(label,
|
||||||
label,
|
style: GoogleFonts.poppins(
|
||||||
style: GoogleFonts.poppins(
|
fontSize: 13.sp,
|
||||||
fontSize: 13.sp,
|
fontWeight: FontWeight.w500,
|
||||||
fontWeight: FontWeight.w500,
|
color: const Color(0xff1A1A1A))),
|
||||||
color: const Color(0xff1A1A1A),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
DropdownButtonFormField<String>(
|
DropdownButtonFormField<String>(
|
||||||
value: null,
|
value: value,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
|
const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
|
||||||
@@ -253,8 +400,14 @@ class PostcardPurchaseFormPageView extends StatelessWidget {
|
|||||||
items: const [
|
items: const [
|
||||||
DropdownMenuItem(value: "Lorem Ipsum", child: Text("Lorem Ipsum")),
|
DropdownMenuItem(value: "Lorem Ipsum", child: Text("Lorem Ipsum")),
|
||||||
],
|
],
|
||||||
onChanged: (val) {},
|
onChanged: onChanged,
|
||||||
),
|
),
|
||||||
|
if (errorText != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4),
|
||||||
|
child: Text(errorText!,
|
||||||
|
style: const TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,36 +5,171 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
class MessageCardWidget extends StatelessWidget {
|
class MessageCardWidget extends StatelessWidget {
|
||||||
final String message;
|
final String message;
|
||||||
final String? selectedFont;
|
final String? selectedFont;
|
||||||
const MessageCardWidget({super.key, required this.message, this.selectedFont});
|
MessageCardWidget({super.key, required this.message, this.selectedFont});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Stack(
|
return Container(
|
||||||
alignment: Alignment.center,
|
constraints: BoxConstraints(minHeight: 227.h),
|
||||||
children: [
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8.h),
|
||||||
Image.asset(
|
decoration: BoxDecoration(
|
||||||
'assets/images/postcard_bg.png',
|
borderRadius: BorderRadius.circular(5.r),
|
||||||
width: double.infinity,
|
gradient: const LinearGradient(
|
||||||
fit: BoxFit.contain,
|
colors: [
|
||||||
|
Color(0xFFF5E9D7), // top-left shade
|
||||||
|
Color(0xFFE7D3B8), // bottom-right shade
|
||||||
|
],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0xFFA08264).withOpacity(0.15),
|
||||||
|
blurRadius: 6,
|
||||||
|
spreadRadius: 0,
|
||||||
|
offset: Offset(-0.5, -0.5),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
foregroundDecoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(5.r),
|
||||||
|
gradient: RadialGradient(
|
||||||
|
center: const Alignment(-0.6, -0.6),
|
||||||
|
radius: 1.2,
|
||||||
|
colors: [Color(0xFFBEA078).withOpacity(0.15), Colors.transparent],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
Positioned(
|
// ---------- IMPORTANT: IntrinsicHeight ensures children get bounded height ----------
|
||||||
right: 10,
|
child: IntrinsicHeight(
|
||||||
top: 50,
|
child: Row(
|
||||||
child: SizedBox(
|
crossAxisAlignment: CrossAxisAlignment.stretch, // stretch so children fill height
|
||||||
width: 150.w,
|
children: [
|
||||||
child: Text(message,
|
// ---------------- LEFT SECTION ---------------- //
|
||||||
textAlign: TextAlign.left,
|
Expanded(
|
||||||
style: TextStyle(
|
child: Column(
|
||||||
fontFamily: selectedFont ??
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
GoogleFonts.poppins().fontFamily,
|
// SpaceBetween ensures top content stays top and CityCards.co stays bottom
|
||||||
color: Colors.black,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
fontSize: 10,
|
children: [
|
||||||
|
// Top group
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
"assets/logo/logo_city_cards.png",
|
||||||
|
height: 22.h,
|
||||||
|
),
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"POSTCARD",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 6.sp,
|
||||||
|
letterSpacing: 0.93,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF000000).withOpacity(0.4),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 7.h),
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"MESSAGE PREVIEW",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 5.sp,
|
||||||
|
letterSpacing: 0.93,
|
||||||
|
color: Color(0xFF000000).withOpacity(0.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
|
||||||
|
Text(
|
||||||
|
message,
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: selectedFont,
|
||||||
|
fontSize: 12.sp,
|
||||||
|
height: 1.6,
|
||||||
|
color: Color(0xFF0A0D13).withOpacity(0.8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
// Bottom text — will stay at the bottom of the left column
|
||||||
|
Text(
|
||||||
|
"CityCards.co",
|
||||||
|
style: TextStyle(fontSize: 12.sp, color: Color(0xFFF95F62)),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
// ---------------- DIVIDER (middle) ---------------- //
|
||||||
|
Container(
|
||||||
|
width: 3.86.w,
|
||||||
|
height: double.infinity, // will match IntrinsicHeight-bounded Row height
|
||||||
|
margin: EdgeInsets.only(right: 10.w,top:24.h,bottom: 24.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Color(0xFF000000).withOpacity(0),
|
||||||
|
Color(0xFF65543F).withOpacity(0.4),
|
||||||
|
Color(0xFF65543F).withOpacity(0.6),
|
||||||
|
Color(0xFF65543F).withOpacity(0.8),
|
||||||
|
Color(0xFF65543F).withOpacity(0.6),
|
||||||
|
Color(0xFF65543F).withOpacity(0.4),
|
||||||
|
Color(0xFF000000).withOpacity(0),
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// ---------------- RIGHT SECTION ---------------- //
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(7),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4.r),
|
||||||
|
border: Border.all(
|
||||||
|
color: Color(0xFF000000).withOpacity(0.12),
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"ADDRESS",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 5.sp,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
letterSpacing: 0.93,
|
||||||
|
color: Color(0xFF000000).withOpacity(0.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"121 Saint Denis Street,\n"
|
||||||
|
"Louisiana,\n"
|
||||||
|
"United States of America",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: selectedFont,
|
||||||
|
fontSize: 8.sp,
|
||||||
|
height: 1.7.h,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,22 +16,13 @@ class PostCardPreviewWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 230.h,
|
height: 227.h,
|
||||||
padding: const EdgeInsets.all(10),
|
child: ClipRRect(
|
||||||
decoration: BoxDecoration(
|
borderRadius: BorderRadius.circular(6.r),
|
||||||
gradient: LinearGradient(colors: [
|
child: Image.file(File(imagePath), fit: BoxFit.cover)),
|
||||||
Color(0xffE2D6C2),
|
|
||||||
Color(0xffFFF5E6),
|
|
||||||
Color(0xffFFF5E6),
|
|
||||||
]),
|
|
||||||
border: Border.all(
|
|
||||||
color: Color(0xff000000).withOpacity(0.12),
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Image.file(File(imagePath), fit: BoxFit.cover),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
backgroundColor: const Color(0xFFF95F62), // Coral red background
|
backgroundColor: const Color(0xFFF95F62), // Coral red background
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Lottie.asset(
|
child: Lottie.asset(
|
||||||
'assets/intro/animation.json', // Your Lottie file
|
'assets/intro/animm.json', // Your Lottie file
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user