proxybuy-flutter/lib/screens/mains/nearby/bestNearby.dart

322 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:lba/gen/assets.gen.dart';
class Bestnearby extends StatefulWidget {
const Bestnearby({
super.key,
});
@override
State<Bestnearby> createState() => _BestnearbyState();
}
class _BestnearbyState extends State<Bestnearby>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late List<Animation<double>> _staggeredAnimations;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500),
);
_staggeredAnimations = List.generate(3, (index) {
return Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
curve: Interval(
(0.2 * index),
(0.6 + 0.2 * index).clamp(0.0, 1.0),
curve: Curves.easeOutCubic,
),
),
);
});
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Widget _buildAnimatedSection(Widget child, int index) {
return FadeTransition(
opacity: _staggeredAnimations[index],
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0.0, 0.5),
end: Offset.zero,
).animate(_staggeredAnimations[index]),
child: child,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 2,
shadowColor: Colors.grey,
automaticallyImplyLeading: false,
leading: InkWell(
onTap: () => Navigator.pop(context),
child: SvgPicture.asset(
Assets.icons.back.path,
fit: BoxFit.scaleDown,
color: Colors.black,
),
),
title: const Text("Top Deals & Stores",
style: TextStyle(fontSize: 18, color: Colors.black)),
),
body: SingleChildScrollView(
child: Column(
children: [
_buildAnimatedSection(NearbyItems(detailsType: 0), 0),
_buildAnimatedSection(NearbyItems(detailsType: 1), 1),
_buildAnimatedSection(NearbyItems(detailsType: 2), 2),
],
),
),
);
}
}
class NearbyItems extends StatefulWidget {
const NearbyItems({super.key, required this.detailsType});
final int detailsType;
@override
State<NearbyItems> createState() => _NearbyItemsState();
}
class _NearbyItemsState extends State<NearbyItems>
with SingleTickerProviderStateMixin {
late AnimationController _listController;
late List<Animation<double>> _itemAnimations;
@override
void initState() {
super.initState();
_listController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1000),
);
_itemAnimations = List.generate(5, (index) {
return Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _listController,
curve: Interval(
(0.15 * index),
(0.5 + 0.15 * index).clamp(0.0, 1.0),
curve: Curves.easeInOut,
),
),
);
});
_listController.forward();
}
@override
void dispose() {
_listController.dispose();
super.dispose();
}
Widget _buildAnimatedItem(Widget child, int index) {
return FadeTransition(
opacity: _itemAnimations[index],
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0.3, 0.0),
end: Offset.zero,
).animate(_itemAnimations[index]),
child: child,
),
);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
DividerTitle(detailsType: widget.detailsType),
SizedBox(
height: widget.detailsType == 0
? 180
: widget.detailsType == 1
? 240
: widget.detailsType == 2
? 240
: 200,
child: ListView.builder(
itemCount: 5,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return _buildAnimatedItem(
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 7),
Container(
width: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.grey[200],
),
child: Image.asset(
Assets.images.topDealsAndStores.path,
),
),
SizedBox(height: 5),
Text(
"Dubai Outlet Mall",
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: 5),
if (widget.detailsType == 0)
Row(
children: [
SvgPicture.asset(Assets.icons.routing.path),
SizedBox(width: 4),
Text(
"1.2 km away",
style: TextStyle(fontSize: 12),
),
],
)
else if (widget.detailsType == 1)
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 2),
Row(
children: [
SvgPicture.asset(
Assets.icons.category2.path),
SizedBox(width: 4),
Text("Stationery store"),
],
),
SizedBox(height: 5),
Row(
children: [
SvgPicture.asset(
Assets.icons.icRoundLocalOffer.path,
),
SizedBox(width: 4),
Text(
"22 - 35% off",
style: TextStyle(color: Colors.red),
),
],
),
SizedBox(height: 5),
Row(
children: [
SvgPicture.asset(Assets.icons.routing.path),
SizedBox(width: 4),
Text("3.6 km away"),
],
),
],
)
else if (widget.detailsType == 2)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 2),
Row(
children: [
SvgPicture.asset(Assets.icons.shop2.path),
SizedBox(width: 4),
Text("Jumbo Electronics "),
],
),
SizedBox(height: 5),
Row(
children: [
SvgPicture.asset(
Assets.icons.icRoundLocalOffer.path,
),
SizedBox(width: 4),
Text(
"22 - 35% off",
style: TextStyle(color: Colors.red),
),
],
),
SizedBox(height: 5),
Row(
children: [
SvgPicture.asset(Assets.icons.routing.path),
SizedBox(width: 4),
Text("3.6 km away"),
],
),
],
)
],
),
),
index,
);
},
),
),
],
),
);
}
}
class DividerTitle extends StatelessWidget {
const DividerTitle({
super.key,
required this.detailsType,
});
final int detailsType;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
detailsType == 0
? "Highest Discount Areas"
: detailsType == 1
? "Highest Discount Areas"
: "Best Deal, Don't Miss",
style: TextStyle(fontSize: 15),
),
const SizedBox(width: 8),
const Expanded(
child: Divider(color: Colors.grey, thickness: 2),
),
],
),
);
}
}