nesward_flutter_app/lib/widgets/daily_best_sells_widget.dart

272 lines
8.5 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import '../widgets/product_card.dart';
class DailyBestSellsWidget extends StatefulWidget {
const DailyBestSellsWidget({super.key});
@override
_DailyBestSellsWidgetState createState() => _DailyBestSellsWidgetState();
}
class _DailyBestSellsWidgetState extends State<DailyBestSellsWidget> {
final PageController _pageController = PageController(viewportFraction: 0.85);
bool _isDragging = false;
Timer? _autoScrollTimer;
int _currentPage = 0;
int _selectedTabIndex = 0;
@override
void initState() {
super.initState();
_startAutoScroll();
}
void _startAutoScroll() {
_autoScrollTimer = Timer.periodic(const Duration(seconds: 4), (_) {
if (!_isDragging && _pageController.hasClients) {
final nextPage = (_currentPage + 1) % _products.length;
_pageController.animateToPage(
nextPage,
duration: const Duration(milliseconds: 600),
curve: Curves.easeInOut,
);
}
});
}
final List<Map<String, dynamic>> _products = [
{
'name': 'Seeds of Change Organic Quinoa, Brown',
'brand': 'Hodo Foods',
'rating': 4.5,
'originalPrice': 245.8,
'discountedPrice': 238.85,
'sold': 90,
'total': 120,
'imageUrl': 'https://nest-frontend-v6.vercel.app/assets/imgs/shop/product-3-2.jpg',
'discount': 15,
},
{
'name': 'All Natural Italian-Style Chicken Meatballs',
'brand': 'Hodo Foods',
'rating': 4.5,
'originalPrice': 245.8,
'discountedPrice': 238.85,
'sold': 90,
'total': 120,
'imageUrl': 'https://nest-frontend-v6.vercel.app/assets/imgs/shop/product-3-2.jpg',
'discount': 35,
},
{
'name': 'Organic Brown Rice and Quinoa Mix',
'brand': 'Green Harvest',
'rating': 4.8,
'originalPrice': 310.0,
'discountedPrice': 280.0,
'sold': 60,
'total': 100,
'imageUrl': 'https://nest-frontend-v6.vercel.app/assets/imgs/shop/product-4-1.jpg',
'discount': 10,
},
{
'name': 'Gluten-Free Coconut Flakes',
'brand': 'Let\'s Do Organic',
'rating': 4.7,
'originalPrice': 299.99,
'discountedPrice': 250.0,
'sold': 110,
'total': 150,
'imageUrl': 'https://nest-frontend-v6.vercel.app/assets/imgs/shop/product-5-1.jpg',
'discount': 25,
},
{
'name': 'Organic Almond Butter Crunch',
'brand': 'Nature\'s Best',
'rating': 4.6,
'originalPrice': 280.0,
'discountedPrice': 245.0,
'sold': 85,
'total': 100,
'imageUrl': 'https://nest-frontend-v6.vercel.app/assets/imgs/shop/product-6-1.jpg',
'discount': 12,
},
];
@override
void dispose() {
_autoScrollTimer?.cancel();
_pageController.dispose();
super.dispose();
}
Widget _buildTabs() {
final List<String> tabs = ["Featured", "Popular", "New added"];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: List.generate(tabs.length, (index) {
final bool isSelected = _selectedTabIndex == index;
return GestureDetector(
onTap: () {
setState(() => _selectedTabIndex = index);
},
child: Container(
margin: const EdgeInsets.only(right: 16),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
color: isSelected ? Colors.green[100] : Colors.white,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: isSelected ? Colors.green : Colors.grey.shade400,
width: 1,
),
),
child: Text(
tabs[index],
style: TextStyle(
color: isSelected ? Colors.green[800] : Colors.grey[700],
fontWeight: isSelected ? FontWeight.bold : FontWeight.w500,
),
),
),
);
}),
),
);
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTabs(),
const SizedBox(height: 16),
SizedBox(
height: 400,
child: Stack(
alignment: Alignment.center,
children: [
// PageView for one product at a time
NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollStartNotification) {
setState(() => _isDragging = true);
} else if (notification is ScrollEndNotification) {
setState(() => _isDragging = false);
} else if (notification is ScrollUpdateNotification) {
// Optional: update _currentPage during drag for indicators
}
return true;
},
child: PageView.builder(
controller: _pageController,
itemCount: _products.length,
onPageChanged: (index) {
setState(() => _currentPage = index);
},
itemBuilder: (context, index) {
final product = _products[index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: ProductCard(
productName: product['name']!,
brand: product['brand']!,
rating: product['rating']!,
originalPrice: product['originalPrice']!,
discountedPrice: product['discountedPrice']!,
sold: product['sold']!,
total: product['total']!,
imageUrl: product['imageUrl']!,
discount: product['discount']!,
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Added to cart!")),
);
},
),
);
},
),
),
// Left Arrow
Positioned(
left: 16,
child: _scrollArrowButton(Icons.arrow_back_ios, _goToPrevious),
),
// Right Arrow
Positioned(
right: 16,
child: _scrollArrowButton(Icons.arrow_forward_ios, _goToNext),
),
// Optional: Page indicators (dots) at bottom
// Positioned(
// bottom: 16,
// left: 0,
// right: 0,
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: List.generate(_products.length, (index) {
// return Container(
// width: 8,
// height: 8,
// margin: const EdgeInsets.symmetric(horizontal: 4),
// decoration: BoxDecoration(
// shape: BoxShape.circle,
// color: _currentPage == index ? Colors.green : Colors.grey[300],
// ),
// );
// }),
// ),
// ),
],
),
),
],
);
}
Widget _scrollArrowButton(IconData icon, VoidCallback onPressed) {
return Container(
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.8),
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.white.withOpacity(0.15),
blurRadius: 4,
spreadRadius: 2,
),
],
),
child: IconButton(
icon: Icon(icon, size: 24, color: Colors.black87),
onPressed: onPressed,
),
);
}
void _goToPrevious() {
if (_currentPage > 0) {
_pageController.animateToPage(
_currentPage - 1,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
}
}
void _goToNext() {
if (_currentPage < _products.length - 1) {
_pageController.animateToPage(
_currentPage + 1,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
}
}
}