part of '../../presentation/home_page/home_page.dart'; class Stock { final String? name; final double? price; final String? imageUrl; final StockCategory? category; Stock({ this.name, this.price, this.imageUrl, this.category, }); } class StocksWidget extends StatefulWidget { const StocksWidget({super.key}); @override State createState() => _StocksWidgetState(); } class _StocksWidgetState extends State { final List prices = [52.90, 77, 89, 111, 135.43, 157.50, 111.11]; Future _fetchNewPrice() async { await Future.delayed(const Duration(seconds: 1)); setState(() { prices.add(prices.last + (prices.last * 0.1)); //if (prices.length > 5) { // prices.removeAt(0); //} }); } @override Widget build(BuildContext context) { final stocks = [ Stock( name: 'Алроса', price: 52.90, imageUrl: 'https://data.cbonds.info/organisations_logos/18/1617957662ALROSA_Rus_COLOUR_RGB.jpg', category: StockCategory.mining), Stock( name: 'Газпром', price: 135.431111, imageUrl: 'https://data.cbonds.info/organisations_logos/21/21.png', category: StockCategory.oilgas), Stock( name: 'Сбербанк', imageUrl: 'https://data.cbonds.info/organisations_logos/313/1615279834sberbank__2-01.png', category: StockCategory.finance), Stock(), ]; return Center( child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( height: 300, child: LineChart( LineChartData( lineBarsData: [ LineChartBarData( spots: prices .asMap() .map((index, price) => MapEntry(index.toDouble(), FlSpot(index.toDouble(), price))) .values .toList(), isCurved: true, color: Colors.blue, barWidth: 3, dotData: const FlDotData(show: false), ), ], ), ), ), const SizedBox(height: 20), ElevatedButton( onPressed: _fetchNewPrice, child: const Text('Добавить новую цену'), ), const SizedBox(height: 20), // ...stocks.map((e) => StockCard(stock: e)), ...stocks.map((e) => StockCard.fromData(e, onLike: () => _showSnackBar(context),)), // .toList() ], ), ), ); } void _showSnackBar(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_){ ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( 'Stock liked', style: Theme.of(context).textTheme.bodyLarge, ), backgroundColor: Colors.red, duration: const Duration(seconds: 1), )); }); } } class StockCard extends StatefulWidget { // final Stock stock; final String? name; final double? price; final String? imageUrl; final StockCategory? category; final VoidCallback? onLike; const StockCard({super.key, this.name, this.price, this.imageUrl, this.category, this.onLike}); factory StockCard.fromData(Stock data, {VoidCallback? onLike}) => StockCard( name: data.name, price: data.price, imageUrl: data.imageUrl, category: data.category, onLike: onLike, ); @override State createState() => _StockCardState(); } class _StockCardState extends State { bool isLiked = false; @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.all(8.5), child: Padding( padding: const EdgeInsets.all(20), child: Row( children: [ Image.network( widget.imageUrl ?? 'https://img.freepik.com/premium-vector/vector-illustration-about-concept-of-no-result-data-or-document-or-file-not-found_675567-5734.jpg', width: 85, height: 85, ), const SizedBox(width: 20), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.name ?? '', style: Theme.of(context).textTheme.headlineSmall, ), Text( '${widget.price?.toStringAsFixed(2)} р', style: Theme.of(context).textTheme.bodyLarge, ), Text( widget.category?.name ?? '', style: Theme.of(context).textTheme.bodySmall, ), ], ), ), GestureDetector( onTap: () { setState(() { isLiked = !isLiked; }); }, child: Icon( Icons.favorite, color: isLiked ? Colors.red : Colors.grey, size: 30.0, ), ), ], ), ), ); } }