186 lines
4.9 KiB
Dart
186 lines
4.9 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:fl_chart/fl_chart.dart';
|
||
import 'StockCategory.dart';
|
||
|
||
void main() {
|
||
runApp(const MyApp());
|
||
}
|
||
|
||
class MyApp extends StatelessWidget {
|
||
const MyApp({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MaterialApp(
|
||
title: 'Gerimovich demo',
|
||
theme: ThemeData(
|
||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.red),
|
||
useMaterial3: true,
|
||
),
|
||
home: const MyHomePage(title: 'Gerimovich Ilya Maximovich'),
|
||
);
|
||
}
|
||
}
|
||
|
||
class MyHomePage extends StatefulWidget {
|
||
const MyHomePage({super.key, required this.title});
|
||
|
||
final String title;
|
||
|
||
@override
|
||
State<MyHomePage> createState() => _MyHomePageState();
|
||
}
|
||
|
||
class _MyHomePageState extends State<MyHomePage> {
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: AppBar(
|
||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||
title: Text(widget.title),
|
||
),
|
||
body: const StocksWidget(),
|
||
);
|
||
}
|
||
}
|
||
|
||
|
||
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: [
|
||
...stocks.map((e) => StockCard(stock: e)),
|
||
const SizedBox(height: 20),
|
||
ElevatedButton(
|
||
onPressed: _fetchNewPrice,
|
||
child: const Text('Добавить новую цену'),
|
||
),
|
||
const SizedBox(height: 20),
|
||
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),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
class StockCard extends StatelessWidget {
|
||
final Stock stock;
|
||
|
||
const StockCard({super.key, required this.stock});
|
||
|
||
@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(
|
||
stock.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),
|
||
Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
stock.name ?? '',
|
||
style: Theme.of(context).textTheme.headlineSmall,
|
||
),
|
||
Text(
|
||
'${stock.price?.toStringAsFixed(2)} р',
|
||
style: Theme.of(context).textTheme.bodyLarge,
|
||
),
|
||
Text(
|
||
stock.category?.name ?? '',
|
||
style: Theme.of(context).textTheme.bodySmall,
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
} |