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),
|
const SizedBox(height: 12),
|
||||||
_buildAnimatedSection(_buildSeasonalDiscountSection(), 3),
|
_buildAnimatedSection(_buildSeasonalDiscountSection(), 3),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
_buildAnimatedSection(_buildSectionTitle("Crafting something for you"), 4),
|
_buildAnimatedSection(_buildSectionTitle("Occasion Specials"), 4),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
_buildAnimatedSection(_buildCraftingSomethingSection(), 5),
|
_buildAnimatedSection(_buildCraftingSomethingSection(), 5),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
@ -483,7 +483,7 @@ class _DiscoverState extends State<Discover> with TickerProviderStateMixin {
|
||||||
final int itemCount = (seasonalItems.length / 2).ceil();
|
final int itemCount = (seasonalItems.length / 2).ceil();
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 110 * 2 + 16, // Height for two cards + spacing
|
height: 110 * 2 + 16,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
|
@ -958,12 +958,8 @@ class FirstPurchaseCard extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return SizedBox(
|
||||||
width: 160,
|
width: 160,
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: Colors.grey.shade200),
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import 'package:lba/gen/assets.gen.dart';
|
||||||
import 'package:lba/res/colors.dart';
|
import 'package:lba/res/colors.dart';
|
||||||
import 'package:lba/widgets/buildWarpedInfo.dart';
|
import 'package:lba/widgets/buildWarpedInfo.dart';
|
||||||
import 'package:lba/widgets/orderType.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/rate.dart';
|
||||||
import 'package:lba/widgets/reviews.dart';
|
import 'package:lba/widgets/reviews.dart';
|
||||||
|
|
||||||
|
|
@ -82,14 +83,14 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.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(
|
_staggeredController = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(milliseconds: 1200),
|
duration: const Duration(milliseconds: 1200),
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- FIX: Changed itemCount from 7 to 8 ---
|
|
||||||
final int itemCount = 8;
|
final int itemCount = 8;
|
||||||
_staggeredAnimations = List.generate(itemCount, (index) {
|
_staggeredAnimations = List.generate(itemCount, (index) {
|
||||||
return Tween<double>(begin: 0.0, end: 1.0).animate(
|
return Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||||
|
|
@ -116,7 +117,7 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
void _showAllReviewsWithAnimation() async {
|
void _showAllReviewsWithAnimation() async {
|
||||||
final newItems = reviews.sublist(displayedReviews.length);
|
final newItems = reviews.sublist(displayedReviews.length);
|
||||||
for (int i = 0; i < newItems.length; i++) {
|
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]);
|
displayedReviews.add(newItems[i]);
|
||||||
_listKey.currentState?.insertItem(displayedReviews.length - 1);
|
_listKey.currentState?.insertItem(displayedReviews.length - 1);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
|
@ -143,7 +144,6 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -152,20 +152,21 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.title,
|
widget.title,
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
style:
|
||||||
|
const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text("Brand: "),
|
const Text("Brand: "),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.brand,
|
widget.brand,
|
||||||
style: TextStyle(color: LightAppColors.primary),
|
style: const TextStyle(color: LightAppColors.primary),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -173,13 +174,13 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
CustomStarRating(rating: 4.8),
|
const CustomStarRating(rating: 4.8),
|
||||||
SizedBox(width: 3),
|
const SizedBox(width: 3),
|
||||||
Text(
|
const Text(
|
||||||
"4.8",
|
"4.8",
|
||||||
style: TextStyle(color: LightAppColors.productDetailDivider),
|
style: TextStyle(color: LightAppColors.productDetailDivider),
|
||||||
),
|
),
|
||||||
|
|
@ -187,7 +188,7 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -196,7 +197,7 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
typename: "Delivery",
|
typename: "Delivery",
|
||||||
fill: true,
|
fill: true,
|
||||||
),
|
),
|
||||||
SizedBox(width: 7),
|
const SizedBox(width: 7),
|
||||||
OrderType(
|
OrderType(
|
||||||
icon: Assets.icons.shoppingCart.path,
|
icon: Assets.icons.shoppingCart.path,
|
||||||
typename: "Pickup",
|
typename: "Pickup",
|
||||||
|
|
@ -206,24 +207,26 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
_buildAnimatedWidget(buildWrappedInfo("Dimensions:", widget.dimensions), 4),
|
_buildAnimatedWidget(
|
||||||
|
buildWrappedInfo("Dimensions:", widget.dimensions), 4),
|
||||||
_buildAnimatedWidget(buildWrappedInfo("Colour:", widget.colour), 5),
|
_buildAnimatedWidget(buildWrappedInfo("Colour:", widget.colour), 5),
|
||||||
_buildAnimatedWidget(buildWrappedInfo("Material:", widget.material), 6),
|
_buildAnimatedWidget(
|
||||||
_buildAnimatedWidget(buildWrappedInfo("Description:", widget.description), 7), // Now this is valid
|
buildWrappedInfo("Material:", widget.material), 6),
|
||||||
SizedBox(height: 30),
|
_buildAnimatedWidget(
|
||||||
Center(
|
buildWrappedInfo("Description:", widget.description), 7),
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"Top reviews from the United Arab Emirates",
|
"Top reviews from the United Arab Emirates",
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
|
|
||||||
AnimatedList(
|
AnimatedList(
|
||||||
key: _listKey,
|
key: _listKey,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
initialItemCount: displayedReviews.length,
|
initialItemCount: displayedReviews.length,
|
||||||
itemBuilder: (context, index, animation) {
|
itemBuilder: (context, index, animation) {
|
||||||
final review = displayedReviews[index];
|
final review = displayedReviews[index];
|
||||||
|
|
@ -231,7 +234,8 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
position: Tween<Offset>(
|
position: Tween<Offset>(
|
||||||
begin: const Offset(-1, 0),
|
begin: const Offset(-1, 0),
|
||||||
end: Offset.zero,
|
end: Offset.zero,
|
||||||
).animate(CurvedAnimation(parent: animation, curve: Curves.easeInOut)),
|
).animate(CurvedAnimation(
|
||||||
|
parent: animation, curve: Curves.easeInOut)),
|
||||||
child: SizeTransition(
|
child: SizeTransition(
|
||||||
sizeFactor: animation,
|
sizeFactor: animation,
|
||||||
axisAlignment: -1,
|
axisAlignment: -1,
|
||||||
|
|
@ -247,7 +251,6 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
if (!showAllReviews && reviews.length > 2)
|
if (!showAllReviews && reviews.length > 2)
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -257,7 +260,7 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text(
|
||||||
"See all reviews",
|
"See all reviews",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: LightAppColors.allReviewOpener,
|
color: LightAppColors.allReviewOpener,
|
||||||
|
|
@ -265,7 +268,7 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
Assets.icons.arrowDown.path,
|
Assets.icons.arrowDown.path,
|
||||||
color: LightAppColors.allReviewOpener,
|
color: LightAppColors.allReviewOpener,
|
||||||
|
|
@ -274,12 +277,12 @@ class _ItemState extends State<Item> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
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/dividerTitle.dart';
|
||||||
import 'package:lba/widgets/openChecker.dart';
|
import 'package:lba/widgets/openChecker.dart';
|
||||||
import 'package:lba/widgets/rate.dart';
|
import 'package:lba/widgets/rate.dart';
|
||||||
|
import 'package:lba/widgets/similar_business_card.dart';
|
||||||
import 'package:maps_launcher/maps_launcher.dart';
|
import 'package:maps_launcher/maps_launcher.dart';
|
||||||
|
|
||||||
class Shop extends StatefulWidget {
|
class Shop extends StatefulWidget {
|
||||||
|
|
@ -39,7 +40,28 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
|
|
||||||
late AnimationController _staggeredController;
|
late AnimationController _staggeredController;
|
||||||
late List<Animation<double>> _staggeredAnimations;
|
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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
@ -51,7 +73,17 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
duration: const Duration(milliseconds: 1200),
|
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) {
|
_staggeredAnimations = List.generate(itemCount, (index) {
|
||||||
return Tween<double>(begin: 0.0, end: 1.0).animate(
|
return Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||||
CurvedAnimation(
|
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();
|
_staggeredController.forward();
|
||||||
|
_listAnimationController.forward();
|
||||||
|
_similarBusinessAnimationController.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_staggeredController.dispose();
|
_staggeredController.dispose();
|
||||||
|
_listAnimationController.dispose();
|
||||||
|
_similarBusinessAnimationController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,30 +178,33 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
height: 25,
|
height: 25,
|
||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Text(
|
Text(
|
||||||
widget.shopName,
|
widget.shopName,
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17),
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, fontSize: 17),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
CustomStarRating(rating: widget.star),
|
CustomStarRating(rating: widget.star),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
widget.star.toString(),
|
widget.star.toString(),
|
||||||
style: TextStyle(color: LightAppColors.productDetailDivider),
|
style: const TextStyle(
|
||||||
|
color: LightAppColors.productDetailDivider,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
|
@ -149,10 +215,10 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
Assets.icons.location.path,
|
Assets.icons.location.path,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
selectedPlace,
|
selectedPlace,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: LightAppColors.productDetailDivider,
|
color: LightAppColors.productDetailDivider,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -183,47 +249,50 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(Assets.icons.clock.path),
|
SvgPicture.asset(Assets.icons.clock.path),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
isOpen ? 'Open Now' : 'Closed',
|
isOpen ? 'Open Now' : 'Closed',
|
||||||
style: TextStyle(color: isOpen ? Colors.green : Colors.red),
|
style: TextStyle(color: isOpen ? Colors.green : Colors.red),
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Container(
|
Container(
|
||||||
color: LightAppColors.productDetailDivider,
|
color: LightAppColors.productDetailDivider,
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 13,
|
height: 13,
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
timeRange,
|
timeRange,
|
||||||
style: TextStyle(color: LightAppColors.productDetailDivider),
|
style: const TextStyle(
|
||||||
|
color: LightAppColors.productDetailDivider,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
_buildAnimatedWidget(DividerTitleWidget(title: "Facilities"), 4),
|
_buildAnimatedWidget(
|
||||||
|
const DividerTitleWidget(title: "Facilities"), 4),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 50,
|
height: 50,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
physics: NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemCount: 1,
|
itemCount: 1,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(Assets.icons.tick.path),
|
SvgPicture.asset(Assets.icons.tick.path),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
widget.facilities,
|
widget.facilities,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: LightAppColors.productDetailDivider,
|
color: LightAppColors.productDetailDivider,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -234,7 +303,7 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
|
|
@ -254,31 +323,26 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
Assets.icons.routing2.path,
|
Assets.icons.routing2.path,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
const Text(
|
||||||
"Direction",
|
"Direction",
|
||||||
style: const TextStyle(
|
style: TextStyle(color: Colors.black, fontSize: 16),
|
||||||
color: Colors.black,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
_buildAnimatedWidget(
|
_buildAnimatedWidget(
|
||||||
Text(
|
const Text(
|
||||||
"List of offers",
|
"List of offers",
|
||||||
style: TextStyle(
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
7,
|
7,
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
|
_buildAnimatedWidget(
|
||||||
Container(
|
Container(
|
||||||
height: 45,
|
height: 45,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
|
@ -288,48 +352,54 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
isActiveOffer = true;
|
isActiveOffer = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(3.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 35,
|
height: 35,
|
||||||
width: 70,
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
color: isActiveOffer ? Colors.white : Colors.transparent,
|
color:
|
||||||
|
isActiveOffer ? Colors.white : Colors.transparent,
|
||||||
),
|
),
|
||||||
child: Center(child: Text("Active")),
|
child: const Center(child: Text("Active")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GestureDetector(
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
isActiveOffer = false;
|
isActiveOffer = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(3.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 35,
|
height: 35,
|
||||||
width: 60,
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
color: !isActiveOffer ? Colors.white : Colors.transparent,
|
color:
|
||||||
|
!isActiveOffer ? Colors.white : Colors.transparent,
|
||||||
|
),
|
||||||
|
child: const Center(child: Text("Old")),
|
||||||
),
|
),
|
||||||
child: Center(child: Text("Old")),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
8,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 15),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 160,
|
height: 160,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
|
|
@ -337,9 +407,80 @@ class _ShopState extends State<Shop> with TickerProviderStateMixin {
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: 2,
|
itemCount: 2,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return CustomCard(
|
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",
|
title: "Calamaro Table Lamp",
|
||||||
description: "Elegant lighting with a modern twist.",
|
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