add some features to product details
This commit is contained in:
parent
fb2119548e
commit
af14d2d7fc
|
|
@ -126,7 +126,7 @@ class _DiscoverState extends State<Discover> 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<Discover> 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: [
|
||||
|
|
|
|||
|
|
@ -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<Item> 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<double>(begin: 0.0, end: 1.0).animate(
|
||||
|
|
@ -106,7 +107,7 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
|||
|
||||
_staggeredController.forward();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_staggeredController.dispose();
|
||||
|
|
@ -116,10 +117,10 @@ class _ItemState extends State<Item> 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<Item> 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<Offset>(
|
||||
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<Offset>(
|
||||
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(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Shop> with TickerProviderStateMixin {
|
|||
|
||||
late AnimationController _staggeredController;
|
||||
late List<Animation<double>> _staggeredAnimations;
|
||||
late AnimationController _listAnimationController;
|
||||
late List<Animation<double>> _itemAnimations;
|
||||
late AnimationController _similarBusinessAnimationController;
|
||||
late List<Animation<double>> _similarBusinessAnimations;
|
||||
|
||||
final List<Map<String, String>> 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<Shop> 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<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(
|
||||
|
|
@ -65,12 +97,43 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
|||
);
|
||||
});
|
||||
|
||||
_itemAnimations = List.generate(2, (index) {
|
||||
return Tween<double>(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<double>(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<Shop> 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<Shop> 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<Shop> 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<Shop> with TickerProviderStateMixin {
|
|||
),
|
||||
5,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
const SizedBox(height: 20),
|
||||
_buildAnimatedWidget(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
|
|
@ -254,92 +323,164 @@ class _ShopState extends State<Shop> 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<Offset>(
|
||||
begin: const Offset(0.5, 0.0),
|
||||
end: Offset.zero,
|
||||
).animate(_itemAnimations[index]),
|
||||
child: ColorFiltered(
|
||||
colorFilter: !isActiveOffer
|
||||
? const ColorFilter.matrix(<double>[
|
||||
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<Offset>(
|
||||
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!");
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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),),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue