completed the attraction details screen with share bottom sheet.

This commit is contained in:
Vinayakkadge04
2025-10-24 15:23:08 +05:30
parent 741036188d
commit 94c91abf32
18 changed files with 644 additions and 2 deletions

BIN
assets/icons/bus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/icons/bx_qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

BIN
assets/icons/clock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
assets/icons/facebook.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

BIN
assets/icons/indeed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 B

BIN
assets/icons/insta.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
assets/icons/skype.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
assets/icons/snapchat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

BIN
assets/icons/truecaller.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/icons/whatsapp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 MiB

View File

@@ -0,0 +1,482 @@
import 'package:citycards_customer/attraction_details/share_bottomsheet.dart';
import 'package:citycards_customer/common_packages/app_bar.dart';
import 'package:citycards_customer/common_packages/custom_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class AttractionDetailsView extends StatelessWidget {
const AttractionDetailsView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
Image.asset(
'assets/images/koh_rong_samloem_banner.png',
height: 377.h,
width: double.infinity,
fit: BoxFit.cover,
),
Positioned(
top: 0,
left: 0,
right: 0,
child: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CommonAppBar(isWhiteLogo: true, isProfilePage: false),
SizedBox(height: 10.h),
Divider(
color: Colors.white.withOpacity(0.6),
height: 1.h,
),
SizedBox(height: 8.h),
Row(
children: [
GestureDetector(
onTap: () => Navigator.pop(context),
child: Icon(
Icons.arrow_back,
size: 24.sp,
color: Colors.white,
),
),
SizedBox(width: 8.w),
Text(
"Koh Rong Samloem",
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
],
),
],
),
),
),
),
Positioned(
bottom: 31.h,
left: 12.w,
child: Text(
"Koh Rong\nSamloem",
style: TextStyle(
color: Colors.white,
fontSize: 44.sp,
fontWeight: FontWeight.w500,
height: 1.2,
),
),
),
Positioned(
bottom: 31.h,
right: 17.w,
child: GestureDetector(
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => const ShareBottomSheet(),
);
},
child: Container(
height: 36.h,
width: 36.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.r),
),
child: Center(
child: Icon(
Icons.share_sharp,
color: Colors.black,
size: 18.sp,
),
),
),
),
),
],
),
// About Section
Padding(
padding: EdgeInsets.only(left: 16.w, right: 16.w, top: 30.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"About",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w400,
),
),
SizedBox(height: 12.32.h),
Text(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Convallis condimentum morbi non egestas enim amet sagittis. Proin sed aliquet rhoncus ut pellentesque ullamcorper sit eget ac.Sit nisi, cras amet varius eget egestas pellentesque. Cursus gravida euismod non...",
style: TextStyle(
color: Color(0xFF262626),
fontWeight: FontWeight.w400,
fontSize: 14.sp,
height: 1.5,
),
),
],
),
),
SizedBox(height: 41.h),
// Booking Section
Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"How to make a booking?",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w400,
),
),
SizedBox(height: 16.h),
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),
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),
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: [
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",
),
],
),
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...",
),
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: 24.h),
],
),
),
),
);
}
Widget includedBox(String icon, String title, String disc) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.h),
decoration: BoxDecoration(
color: Color(0xFFFFF5F5),
borderRadius: BorderRadius.circular(10.r),
border: Border.all(color: Color(0xFFFDCDCE)),
),
child: IntrinsicWidth(
child: Row(
children: [
Image.asset(icon, scale: 4),
SizedBox(width: 16.w),
Column(
children: [
CustomText(
text: title,
size: 16.sp,
weight: FontWeight.w500,
color: Color(0xFF212121),
),
SizedBox(height: 4.h),
CustomText(
text: disc,
size: 11.sp,
weight: FontWeight.w400,
color: Color(0xFF666666),
),
],
),
],
),
),
);
}
Widget faqBox(String title, String desc) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h),
decoration: BoxDecoration(
color: Color(0xFFFFF5F5),
border: Border.all(color: Color(0xFFFDCDCE)),
borderRadius: BorderRadius.circular(10.r),
),
child: Column(
children: [
Row(
children: [
CustomText(
text: title,
size: 16.sp,
weight: FontWeight.w500,
color: Color(0xFF212121),
),
SizedBox(width: 20.w),
Icon(Icons.arrow_forward_ios_outlined, size: 18.sp),
],
),
SizedBox(height: 9.h),
CustomText(text: desc, size: 11.sp, color: Color(0xFF7D7D7D)),
],
),
);
}
}

View File

@@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class ShareBottomSheet extends StatelessWidget {
const ShareBottomSheet({super.key});
@override
Widget build(BuildContext context) {
final shareItems = [
{'icon': 'assets/icons/whatsapp.png', 'title': 'WhatsApp'},
{'icon': 'assets/icons/insta.png', 'title': 'Direct'},
{'icon': 'assets/icons/snapchat.png', 'title': 'Snapchat'},
{'icon': 'assets/icons/skype.png', 'title': 'Skype'},
{'icon': 'assets/icons/truecaller.png', 'title': 'Truecaller'},
{'icon': 'assets/icons/indeed.png', 'title': 'Private Message'},
{'icon': 'assets/icons/indeed.png', 'title': 'Share In A Post'},
{'icon': 'assets/icons/facebook.png', 'title': 'News Feed'},
];
return Container(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(12.r)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 4.h,
width: 47.w,
margin: EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Color(0xFF222222),
borderRadius: BorderRadius.circular(8),
),
),
TextField(
readOnly: true,
decoration: InputDecoration(
hintText: "https://www.linkedin.com/link",
suffixIcon: IconButton(
icon: const Icon(Icons.copy, color: Color(0xFF858585)),
onPressed: () {},
),
filled: true,
fillColor: const Color(0xffFEE7E7),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
),
),
),
SizedBox(height: 20.h),
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: shareItems.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
mainAxisSpacing: 16,
crossAxisSpacing: 8,
childAspectRatio: 0.8,
),
itemBuilder: (context, index) {
final item = shareItems[index];
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(item['icon']!, width: 55.w),
SizedBox(height: 8.h),
Text(
item['title']!,
style: TextStyle(fontSize: 12.sp),
textAlign: TextAlign.center,
),
],
);
},
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
4,
(index) => Container(
margin: const EdgeInsets.symmetric(horizontal: 3),
width: 8.w,
height: 8.h,
decoration: BoxDecoration(
color: index == 0 ? Color(0xFF676363) : Colors.white,
border: Border.all(color: Color(0xFF676363)),
shape: BoxShape.circle,
),
),
),
),
SizedBox(height: 10.h),
],
),
);
}
}

View File

@@ -0,0 +1,32 @@
import 'package:citycards_customer/common_packages/app_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class BuyPassView extends StatelessWidget {
const BuyPassView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0.w),
child: Column(
children: [
CommonAppBar(isWhiteLogo: false, isProfilePage: true),
SizedBox(height:24.h),
Row(
children: [
Icon(Icons.arrow_back,)
],
)
],
),
),
),
),
);
}
}

View File

@@ -1,4 +1,6 @@
import 'package:citycards_customer/Profile/profile_page_view.dart';
import 'package:citycards_customer/attraction_details/attraction_details_view.dart';
import 'package:citycards_customer/buy_a_pass/buy_pass_view.dart';
import 'package:citycards_customer/common_bloc/language_selection_bloc.dart';
import 'package:citycards_customer/contact_us/contact_us_view.dart';
import 'package:citycards_customer/edit_profile/edit_profile_view.dart';
@@ -28,6 +30,8 @@ class AppRouter {
return BlocProvider(
create: (_) => NavigationBloc(),
child: const HomePage(),
);
},
);
@@ -111,6 +115,16 @@ class AppRouter {
return EsimOfferPage();
},
);
case RouteConstants.attractionDetails:
return MaterialPageRoute(builder: (_) {
return AttractionDetailsView();
});
case RouteConstants.buyPass:
return MaterialPageRoute(builder: (_) {
return BuyPassView();
});
default:
return MaterialPageRoute(
builder: (_) =>

View File

@@ -25,4 +25,15 @@ class RouteConstants {
static const String esimOffer = '/esim_offer';
static const String hotelOffer = '/hotelOffer';
/**************************** Attraction Page *****************************************/
static const String attractionDetails ='/attractionDetails';
/**************************** By Pass Page Page *****************************************/
static const String buyPass ='/buyPass';
}

View File

@@ -29,7 +29,7 @@ class MyApp extends StatelessWidget {
builder: (context, child) {
return MaterialApp(
onGenerateRoute: _appRouter.onGenerateRoute,
initialRoute: RouteConstants.home,
initialRoute: RouteConstants.buyPass,
debugShowCheckedModeBanner: false,
title: 'City Cards',
theme: ThemeData(