2024-11-02 21:09:05 +04:00
|
|
|
|
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<StocksWidget> createState() => _StocksWidgetState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _StocksWidgetState extends State<StocksWidget> {
|
|
|
|
|
final List<double> prices = [52.90, 77, 89, 111, 135.43, 157.50, 111.11];
|
|
|
|
|
|
|
|
|
|
Future<void> _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,
|
2024-11-02 23:37:06 +04:00
|
|
|
|
onLike: () => _showSnackBar(context),)).toList(), // .toList()
|
2024-11-02 21:09:05 +04:00
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<StockCard> createState() => _StockCardState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _StockCardState extends State<StockCard> {
|
|
|
|
|
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,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|