diff --git a/lib/screens/mains/discover/discover.dart b/lib/screens/mains/discover/discover.dart index d628b7a..92f8bff 100644 --- a/lib/screens/mains/discover/discover.dart +++ b/lib/screens/mains/discover/discover.dart @@ -126,7 +126,7 @@ class _DiscoverState extends State with TickerProviderStateMixin { const SizedBox(height: 12), _buildAnimatedSection(_buildSeasonalDiscountSection(), 3), const SizedBox(height: 24), - _buildAnimatedSection(_buildSectionTitle("Crafting something for you"), 4), + _buildAnimatedSection(_buildSectionTitle("Occasion Specials"), 4), const SizedBox(height: 12), _buildAnimatedSection(_buildCraftingSomethingSection(), 5), const SizedBox(height: 24), @@ -483,7 +483,7 @@ class _DiscoverState extends State with TickerProviderStateMixin { final int itemCount = (seasonalItems.length / 2).ceil(); return SizedBox( - height: 110 * 2 + 16, // Height for two cards + spacing + height: 110 * 2 + 16, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), @@ -958,12 +958,8 @@ class FirstPurchaseCard extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( + return SizedBox( width: 160, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - border: Border.all(color: Colors.grey.shade200), - ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/screens/product/item.dart b/lib/screens/product/item.dart index 4d20642..dd85d7d 100644 --- a/lib/screens/product/item.dart +++ b/lib/screens/product/item.dart @@ -6,6 +6,7 @@ import 'package:lba/gen/assets.gen.dart'; import 'package:lba/res/colors.dart'; import 'package:lba/widgets/buildWarpedInfo.dart'; import 'package:lba/widgets/orderType.dart'; +import 'package:lba/widgets/price_reserve_widget.dart'; import 'package:lba/widgets/rate.dart'; import 'package:lba/widgets/reviews.dart'; @@ -82,14 +83,14 @@ class _ItemState extends State with TickerProviderStateMixin { @override void initState() { super.initState(); - displayedReviews = reviews.length > 2 ? reviews.sublist(0, 2) : List.from(reviews); + displayedReviews = + reviews.length > 2 ? reviews.sublist(0, 2) : List.from(reviews); _staggeredController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1200), ); - // --- FIX: Changed itemCount from 7 to 8 --- final int itemCount = 8; _staggeredAnimations = List.generate(itemCount, (index) { return Tween(begin: 0.0, end: 1.0).animate( @@ -106,7 +107,7 @@ class _ItemState extends State with TickerProviderStateMixin { _staggeredController.forward(); } - + @override void dispose() { _staggeredController.dispose(); @@ -116,10 +117,10 @@ class _ItemState extends State with TickerProviderStateMixin { void _showAllReviewsWithAnimation() async { final newItems = reviews.sublist(displayedReviews.length); for (int i = 0; i < newItems.length; i++) { - await Future.delayed(Duration(milliseconds: 150)); + await Future.delayed(const Duration(milliseconds: 150)); displayedReviews.add(newItems[i]); _listKey.currentState?.insertItem(displayedReviews.length - 1); - setState(() {}); + setState(() {}); } setState(() { showAllReviews = true; @@ -143,142 +144,144 @@ class _ItemState extends State with TickerProviderStateMixin { Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildAnimatedWidget( - Align( - alignment: Alignment.centerLeft, - child: Text( - widget.title, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - ), - 0, - ), - SizedBox(height: 5), - _buildAnimatedWidget( - Row( - children: [ - Text("Brand: "), - Expanded( - child: Text( - widget.brand, - style: TextStyle(color: LightAppColors.primary), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - 1, - ), - SizedBox(height: 10), - _buildAnimatedWidget( - Row( - children: [ - CustomStarRating(rating: 4.8), - SizedBox(width: 3), - Text( - "4.8", - style: TextStyle(color: LightAppColors.productDetailDivider), - ), - ], - ), - 2, - ), - SizedBox(height: 15), - _buildAnimatedWidget( - Row( - children: [ - OrderType( - icon: Assets.icons.cardPos.path, - typename: "Delivery", - fill: true, - ), - SizedBox(width: 7), - OrderType( - icon: Assets.icons.shoppingCart.path, - typename: "Pickup", - fill: true, - ), - ], - ), - 3, - ), - SizedBox(height: 15), - _buildAnimatedWidget(buildWrappedInfo("Dimensions:", widget.dimensions), 4), - _buildAnimatedWidget(buildWrappedInfo("Colour:", widget.colour), 5), - _buildAnimatedWidget(buildWrappedInfo("Material:", widget.material), 6), - _buildAnimatedWidget(buildWrappedInfo("Description:", widget.description), 7), // Now this is valid - SizedBox(height: 30), - Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildAnimatedWidget( + Align( + alignment: Alignment.centerLeft, child: Text( - "Top reviews from the United Arab Emirates", - style: TextStyle(fontWeight: FontWeight.bold), + widget.title, + style: + const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), ), - SizedBox(height: 15), - - AnimatedList( - key: _listKey, - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - initialItemCount: displayedReviews.length, - itemBuilder: (context, index, animation) { - final review = displayedReviews[index]; - return SlideTransition( - position: Tween( - begin: const Offset(-1, 0), - end: Offset.zero, - ).animate(CurvedAnimation(parent: animation, curve: Curves.easeInOut)), - child: SizeTransition( - sizeFactor: animation, - axisAlignment: -1, - child: Reviews( - name: review['name'], - comment: review['comment'], - rate: review['rate'], - yesCount: review['yesCount'], - noCount: review['noCount'], - date: review['date'], - ), + 0, + ), + const SizedBox(height: 5), + _buildAnimatedWidget( + Row( + children: [ + const Text("Brand: "), + Expanded( + child: Text( + widget.brand, + style: const TextStyle(color: LightAppColors.primary), + overflow: TextOverflow.ellipsis, ), - ); - }, + ), + ], ), - - if (!showAllReviews && reviews.length > 2) - Column( - children: [ - Center( - child: InkWell( - onTap: _showAllReviewsWithAnimation, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "See all reviews", - style: TextStyle( - color: LightAppColors.allReviewOpener, - fontWeight: FontWeight.bold, - fontSize: 18, - ), - ), - SizedBox(width: 10), - SvgPicture.asset( - Assets.icons.arrowDown.path, + 1, + ), + const SizedBox(height: 10), + _buildAnimatedWidget( + Row( + children: [ + const CustomStarRating(rating: 4.8), + const SizedBox(width: 3), + const Text( + "4.8", + style: TextStyle(color: LightAppColors.productDetailDivider), + ), + ], + ), + 2, + ), + const SizedBox(height: 15), + _buildAnimatedWidget( + Row( + children: [ + OrderType( + icon: Assets.icons.cardPos.path, + typename: "Delivery", + fill: true, + ), + const SizedBox(width: 7), + OrderType( + icon: Assets.icons.shoppingCart.path, + typename: "Pickup", + fill: true, + ), + ], + ), + 3, + ), + const SizedBox(height: 15), + _buildAnimatedWidget( + buildWrappedInfo("Dimensions:", widget.dimensions), 4), + _buildAnimatedWidget(buildWrappedInfo("Colour:", widget.colour), 5), + _buildAnimatedWidget( + buildWrappedInfo("Material:", widget.material), 6), + _buildAnimatedWidget( + buildWrappedInfo("Description:", widget.description), 7), + const SizedBox(height: 30), + const Center( + child: Text( + "Top reviews from the United Arab Emirates", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + const SizedBox(height: 15), + AnimatedList( + key: _listKey, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + initialItemCount: displayedReviews.length, + itemBuilder: (context, index, animation) { + final review = displayedReviews[index]; + return SlideTransition( + position: Tween( + begin: const Offset(-1, 0), + end: Offset.zero, + ).animate(CurvedAnimation( + parent: animation, curve: Curves.easeInOut)), + child: SizeTransition( + sizeFactor: animation, + axisAlignment: -1, + child: Reviews( + name: review['name'], + comment: review['comment'], + rate: review['rate'], + yesCount: review['yesCount'], + noCount: review['noCount'], + date: review['date'], + ), + ), + ); + }, + ), + if (!showAllReviews && reviews.length > 2) + Column( + children: [ + Center( + child: InkWell( + onTap: _showAllReviewsWithAnimation, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + "See all reviews", + style: TextStyle( color: LightAppColors.allReviewOpener, + fontWeight: FontWeight.bold, + fontSize: 18, ), - ], - ), + ), + const SizedBox(width: 10), + SvgPicture.asset( + Assets.icons.arrowDown.path, + color: LightAppColors.allReviewOpener, + ), + ], ), ), - SizedBox(height: 50,) - ], - ), - ], - ), + ), + ], + ), + const SizedBox(height: 20), + const PriceReserveWidget(), + ], ), ); } diff --git a/lib/screens/product/shop.dart b/lib/screens/product/shop.dart index dbb6b07..65eb06c 100644 --- a/lib/screens/product/shop.dart +++ b/lib/screens/product/shop.dart @@ -9,6 +9,7 @@ import 'package:lba/widgets/customCard.dart'; import 'package:lba/widgets/dividerTitle.dart'; import 'package:lba/widgets/openChecker.dart'; import 'package:lba/widgets/rate.dart'; +import 'package:lba/widgets/similar_business_card.dart'; import 'package:maps_launcher/maps_launcher.dart'; class Shop extends StatefulWidget { @@ -39,7 +40,28 @@ class _ShopState extends State with TickerProviderStateMixin { late AnimationController _staggeredController; late List> _staggeredAnimations; + late AnimationController _listAnimationController; + late List> _itemAnimations; + late AnimationController _similarBusinessAnimationController; + late List> _similarBusinessAnimations; + final List> similarBusinesses = [ + { + "imagePath": Assets.images.image.path, + "name": "The Odd Piece", + "location": "Al Quoz 1", + }, + { + "imagePath": Assets.images.topDealsAndStores.path, + "name": "IKEA", + "location": "Dubai Festival City", + }, + { + "imagePath": Assets.images.media.path, + "name": "Home Centre", + "location": "Mall of the Emirates", + } + ]; @override void initState() { @@ -51,7 +73,17 @@ class _ShopState extends State with TickerProviderStateMixin { duration: const Duration(milliseconds: 1200), ); - final int itemCount = 8; + _listAnimationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 1000), + ); + + _similarBusinessAnimationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 1200), + ); + + final int itemCount = 9; _staggeredAnimations = List.generate(itemCount, (index) { return Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( @@ -65,12 +97,43 @@ class _ShopState extends State with TickerProviderStateMixin { ); }); + _itemAnimations = List.generate(2, (index) { + return Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _listAnimationController, + curve: Interval( + (0.2 * index), + (0.6 + 0.2 * index).clamp(0.0, 1.0), + curve: Curves.easeOut, + ), + ), + ); + }); + + _similarBusinessAnimations = + List.generate(similarBusinesses.length, (index) { + return Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _similarBusinessAnimationController, + curve: Interval( + (0.2 * index), + (0.6 + 0.2 * index).clamp(0.0, 1.0), + curve: Curves.easeOut, + ), + ), + ); + }); + _staggeredController.forward(); + _listAnimationController.forward(); + _similarBusinessAnimationController.forward(); } @override void dispose() { _staggeredController.dispose(); + _listAnimationController.dispose(); + _similarBusinessAnimationController.dispose(); super.dispose(); } @@ -115,30 +178,33 @@ class _ShopState extends State with TickerProviderStateMixin { color: Colors.black, height: 25, ), - SizedBox(width: 10), + const SizedBox(width: 10), Text( widget.shopName, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17), + style: const TextStyle( + fontWeight: FontWeight.bold, fontSize: 17), ), ], ), 0, ), - SizedBox(height: 15), + const SizedBox(height: 15), _buildAnimatedWidget( Row( children: [ CustomStarRating(rating: widget.star), - SizedBox(width: 5), + const SizedBox(width: 5), Text( widget.star.toString(), - style: TextStyle(color: LightAppColors.productDetailDivider), + style: const TextStyle( + color: LightAppColors.productDetailDivider, + ), ), ], ), 1, ), - SizedBox(height: 5), + const SizedBox(height: 5), _buildAnimatedWidget( Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -149,10 +215,10 @@ class _ShopState extends State with TickerProviderStateMixin { Assets.icons.location.path, color: Colors.black, ), - SizedBox(width: 5), + const SizedBox(width: 5), Text( selectedPlace, - style: TextStyle( + style: const TextStyle( color: LightAppColors.productDetailDivider, ), ), @@ -183,47 +249,50 @@ class _ShopState extends State with TickerProviderStateMixin { ), 2, ), - SizedBox(height: 5), + const SizedBox(height: 5), _buildAnimatedWidget( Row( children: [ SvgPicture.asset(Assets.icons.clock.path), - SizedBox(width: 5), + const SizedBox(width: 5), Text( isOpen ? 'Open Now' : 'Closed', style: TextStyle(color: isOpen ? Colors.green : Colors.red), ), - SizedBox(width: 5), + const SizedBox(width: 5), Container( color: LightAppColors.productDetailDivider, width: 1, height: 13, ), - SizedBox(width: 5), + const SizedBox(width: 5), Text( timeRange, - style: TextStyle(color: LightAppColors.productDetailDivider), + style: const TextStyle( + color: LightAppColors.productDetailDivider, + ), ), ], ), 3, ), - SizedBox(height: 15), - _buildAnimatedWidget(DividerTitleWidget(title: "Facilities"), 4), + const SizedBox(height: 15), + _buildAnimatedWidget( + const DividerTitleWidget(title: "Facilities"), 4), _buildAnimatedWidget( SizedBox( height: 50, child: ListView.builder( - physics: NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), itemCount: 1, itemBuilder: (context, index) { return Row( children: [ SvgPicture.asset(Assets.icons.tick.path), - SizedBox(width: 5), + const SizedBox(width: 5), Text( widget.facilities, - style: TextStyle( + style: const TextStyle( color: LightAppColors.productDetailDivider, ), ), @@ -234,7 +303,7 @@ class _ShopState extends State with TickerProviderStateMixin { ), 5, ), - SizedBox(height: 20), + const SizedBox(height: 20), _buildAnimatedWidget( ElevatedButton( style: ElevatedButton.styleFrom( @@ -254,92 +323,164 @@ class _ShopState extends State with TickerProviderStateMixin { Assets.icons.routing2.path, color: Colors.black, ), - SizedBox(width: 5), - Text( + const SizedBox(width: 5), + const Text( "Direction", - style: const TextStyle( - color: Colors.black, - fontSize: 16, - ), + style: TextStyle(color: Colors.black, fontSize: 16), ), ], ), ), 6, ), - SizedBox(height: 30), + const SizedBox(height: 30), _buildAnimatedWidget( - Text( + const Text( "List of offers", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - ), + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), ), 7, ), - SizedBox(height: 15), - Container( - height: 45, - width: 150, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: const Color.fromARGB(17, 77, 77, 77), - ), - child: Row( - children: [ - GestureDetector( - onTap: () { - setState(() { - isActiveOffer = true; - }); - }, - child: Padding( - padding: const EdgeInsets.all(5.0), - child: Container( - height: 35, - width: 70, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: isActiveOffer ? Colors.white : Colors.transparent, + const SizedBox(height: 15), + _buildAnimatedWidget( + Container( + height: 45, + width: 150, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: const Color.fromARGB(17, 77, 77, 77), + ), + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () { + setState(() { + isActiveOffer = true; + }); + }, + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Container( + height: 35, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: + isActiveOffer ? Colors.white : Colors.transparent, + ), + child: const Center(child: Text("Active")), + ), ), - child: Center(child: Text("Active")), ), ), - ), - GestureDetector( - onTap: () { - setState(() { - isActiveOffer = false; - }); - }, - child: Padding( - padding: const EdgeInsets.all(5.0), - child: Container( - height: 35, - width: 60, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: !isActiveOffer ? Colors.white : Colors.transparent, + Expanded( + child: GestureDetector( + onTap: () { + setState(() { + isActiveOffer = false; + }); + }, + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Container( + height: 35, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: + !isActiveOffer ? Colors.white : Colors.transparent, + ), + child: const Center(child: Text("Old")), + ), ), - child: Center(child: Text("Old")), ), ), - ), - ], + ], + ), ), + 8, ), - SizedBox(height: 15), + const SizedBox(height: 15), SizedBox( - height: 160, + height: 160, child: ListView.builder( scrollDirection: Axis.horizontal, shrinkWrap: true, itemCount: 2, itemBuilder: (context, index) { - return CustomCard( - title: "Calamaro Table Lamp", - description: "Elegant lighting with a modern twist.", + return FadeTransition( + opacity: _itemAnimations[index], + child: SlideTransition( + position: Tween( + begin: const Offset(0.5, 0.0), + end: Offset.zero, + ).animate(_itemAnimations[index]), + child: ColorFiltered( + colorFilter: !isActiveOffer + ? const ColorFilter.matrix([ + 0.2126, + 0.7152, + 0.0722, + 0, + 0, + 0.2126, + 0.7152, + 0.0722, + 0, + 0, + 0.2126, + 0.7152, + 0.0722, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + ]) + : const ColorFilter.mode( + Colors.transparent, + BlendMode.multiply, + ), + child: const CustomCard( + title: "Calamaro Table Lamp", + description: "Elegant lighting with a modern twist.", + ), + ), + ), + ); + }, + ), + ), + const SizedBox(height: 20), + const Text( + "Similar Business", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + ), + const SizedBox(height: 15), + SizedBox( + height: 280, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: similarBusinesses.length, + itemBuilder: (context, index) { + final business = similarBusinesses[index]; + return FadeTransition( + opacity: _similarBusinessAnimations[index], + child: SlideTransition( + position: Tween( + begin: const Offset(0.5, 0.0), + end: Offset.zero, + ).animate(_similarBusinessAnimations[index]), + child: SimilarBusinessCard( + imagePath: business['imagePath']!, + name: business['name']!, + location: business['location']!, + onTap: () { + print("${business['name']} tapped!"); + }, + ), + ), ); }, ), diff --git a/lib/widgets/price_reserve_widget.dart b/lib/widgets/price_reserve_widget.dart new file mode 100644 index 0000000..22bb9fd --- /dev/null +++ b/lib/widgets/price_reserve_widget.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:lba/res/colors.dart'; + +class PriceReserveWidget extends StatelessWidget { + const PriceReserveWidget({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 12), + decoration: BoxDecoration( + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // بخش قیمت + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Container( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 3), + decoration: BoxDecoration( + color: LightAppColors.offerTimer, + borderRadius: BorderRadius.circular(4), + ), + child: const Text( + 'HOT', + style: TextStyle( + color: Colors.white, + fontSize: 11, + fontWeight: FontWeight.bold, + ), + ), + ), + const SizedBox(width: 8), + Row( + children: [ + const Text( + '2126.88', + style: TextStyle( + fontSize: 14, + color: Colors.grey, + decoration: TextDecoration.lineThrough, + ), + ), + SizedBox(width: 5,), + const Text( + '(12%)', + style: TextStyle( + fontSize: 14, + color: LightAppColors.offerTimer, + ), + ), + ], + ), + ], + ), + const SizedBox(height: 6), + const FittedBox( + fit: BoxFit.scaleDown, + child: Text( + 'AED 1,899', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: LightAppColors.offerTimer, + ), + maxLines: 1, + ), + ), + ], + ), + ), + + const SizedBox(width: 16), + + SizedBox( + width: 200, + height: 50, + child: ElevatedButton( + onPressed: () { + // TODO: Add reservation logic here + }, + style: ElevatedButton.styleFrom( + backgroundColor: LightAppColors.offerTimer, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + child: const Text( + 'Reserve', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/similar_business_card.dart b/lib/widgets/similar_business_card.dart new file mode 100644 index 0000000..5ae9df3 --- /dev/null +++ b/lib/widgets/similar_business_card.dart @@ -0,0 +1,113 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:lba/gen/assets.gen.dart'; +import 'package:lba/res/colors.dart'; + +class SimilarBusinessCard extends StatelessWidget { + final String imagePath; + final String name; + final String location; + final VoidCallback onTap; + + const SimilarBusinessCard({ + super.key, + required this.imagePath, + required this.name, + required this.location, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Container( + width: 220, + margin: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.15), + offset: const Offset(0, 4), + blurRadius: 8, + spreadRadius: 1, + ), + ], + borderRadius: BorderRadius.circular(12), + color: LightAppColors.nearbyPopup, + border: Border.all(color: Colors.white, width: 4.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 15,), + Center( + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(8)), + child: Image.asset( + imagePath, + height: 110, + width: 180, + fit: BoxFit.cover, + ), + ), + ), + Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 16, + color: Colors.black, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 6), + Row( + children: [ + SvgPicture.asset( + Assets.icons.location.path, + color: Colors.black, + width: 16, + ), + const SizedBox(width: 6), + Expanded( + child: Text( + location, + style: TextStyle( + fontSize: 14, + color: Colors.black, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SizedBox(height: 16), + SizedBox( + width: 120, + child: ElevatedButton( + onPressed: onTap, + style: ElevatedButton.styleFrom( + backgroundColor: LightAppColors.primary, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + ), + child: const Text("See more about",style: TextStyle(fontWeight: FontWeight.bold),), + ), + ), + ], + ), + ), + ], + ), + ); + } +} \ No newline at end of file