Сергей Марков
8 months ago
18 changed files with 1218 additions and 79 deletions
@ -0,0 +1,102 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
enum CounterType { |
||||
coldWater(_coldWaterId, Colors.blue, Icons.water_drop), |
||||
hotWater(_hotWaterId, Colors.red, Icons.water_drop), |
||||
electrisity1rates(_electrisity1rateId, Colors.lightBlue, Icons.tungsten), |
||||
electrisity2rates(_electrisity2rateId, Colors.lightBlue, Icons.tungsten), |
||||
electrisity3rates(_electrisity3rateId, Colors.lightBlue, Icons.tungsten), |
||||
gas(_gasId, Colors.blueAccent, Icons.local_fire_department); |
||||
|
||||
const CounterType(this.id, this.color, this.icon); |
||||
|
||||
static const int _coldWaterId = 0; |
||||
static const int _hotWaterId = 1; |
||||
static const int _gasId = 2; |
||||
static const int _electrisity1rateId = 3; |
||||
static const int _electrisity2rateId = 4; |
||||
static const int _electrisity3rateId = 5; |
||||
final int id; |
||||
final Color color; |
||||
final IconData icon; |
||||
|
||||
String getLabel(BuildContext context) { |
||||
switch (id) { |
||||
case _coldWaterId: |
||||
return AppLocalizations.of(context)!.cold_water_type_str; |
||||
case _hotWaterId: |
||||
return AppLocalizations.of(context)!.hot_water_type_str; |
||||
case _electrisity1rateId: |
||||
return AppLocalizations.of(context)!.electrisity1_type_str; |
||||
case _electrisity2rateId: |
||||
return AppLocalizations.of(context)!.electrisity2_type_str; |
||||
case _electrisity3rateId: |
||||
return AppLocalizations.of(context)!.electrisity3_type_str; |
||||
case _gasId: |
||||
return AppLocalizations.of(context)!.gas_type_str; |
||||
default: |
||||
} |
||||
|
||||
return AppLocalizations.of(context)!.unknown_type_str; |
||||
} |
||||
|
||||
CounterUnits getUnits() { |
||||
if (id < _electrisity1rateId) { |
||||
return CounterUnits.m3; |
||||
} |
||||
|
||||
return CounterUnits.kVt; |
||||
} |
||||
} |
||||
|
||||
enum CounterUnits { |
||||
m3(0), |
||||
kVt(1); |
||||
|
||||
const CounterUnits(this.id); |
||||
final int id; |
||||
|
||||
String getLabel(BuildContext context) { |
||||
switch (id) { |
||||
case 0: |
||||
return AppLocalizations.of(context)!.m3; |
||||
case 1: |
||||
return AppLocalizations.of(context)!.kVt; |
||||
} |
||||
|
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
class Counter { |
||||
final int? id; |
||||
final int addressId; |
||||
final CounterType counterType; |
||||
final String name; |
||||
final double? value; |
||||
|
||||
Counter( |
||||
{this.id, |
||||
required this.addressId, |
||||
required this.counterType, |
||||
required this.name, |
||||
this.value}); |
||||
|
||||
factory Counter.fromMap(Map<String, dynamic> json) { |
||||
return Counter( |
||||
id: json["id"], |
||||
addressId: json["address_id"], |
||||
counterType: CounterType.values |
||||
.firstWhere((element) => element.id == json["counter_type"]), |
||||
name: json["name"], |
||||
value: json["value"].toDouble()); |
||||
} |
||||
|
||||
Map<String, dynamic> toMap() => { |
||||
"id": id, |
||||
"address_id": addressId, |
||||
"counter_type": counterType.id, |
||||
"name": name |
||||
}; |
||||
} |
@ -0,0 +1,69 @@
|
||||
import 'package:counters/counters.dart'; |
||||
import 'package:counters/datbase.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
class NewCounterPage extends StatelessWidget { |
||||
final int addressId; |
||||
final nameController = TextEditingController(); |
||||
CounterType counterType = CounterType.coldWater; |
||||
|
||||
NewCounterPage({super.key, required this.addressId}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_counter_title)), |
||||
body: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
DropdownMenu<CounterType>( |
||||
enableFilter: true, |
||||
hintText: |
||||
AppLocalizations.of(context)!.choose_type_of_counter, |
||||
expandedInsets: EdgeInsets.zero, |
||||
dropdownMenuEntries: |
||||
CounterType.values.map<DropdownMenuEntry<CounterType>>( |
||||
(CounterType icon) { |
||||
return DropdownMenuEntry<CounterType>( |
||||
value: icon, |
||||
labelWidget: Text(icon.getLabel(context)), |
||||
label: icon.getLabel(context) |
||||
//leadingIcon: Icon(icon.icon), |
||||
); |
||||
}, |
||||
).toList(), |
||||
onSelected: (value) => counterType = value!, |
||||
), |
||||
const SizedBox(height: 50), |
||||
TextField( |
||||
controller: nameController, |
||||
decoration: InputDecoration( |
||||
hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: |
||||
AppLocalizations.of(context)!.enter_counter_name), |
||||
), |
||||
const SizedBox(height: 50), |
||||
TextButton( |
||||
onPressed: () { |
||||
DBProvider.db |
||||
.newCounter(Counter( |
||||
addressId: addressId, |
||||
counterType: counterType, |
||||
name: nameController.text)) |
||||
.then((value) => Navigator.pop(context)); |
||||
}, |
||||
child: Text( |
||||
AppLocalizations.of(context)!.add_new_address_button)) |
||||
]), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,208 @@
|
||||
import 'package:counters/counters.dart'; |
||||
import 'package:counters/datbase.dart'; |
||||
import 'package:counters/value.dart'; |
||||
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
import 'package:intl/intl.dart'; |
||||
|
||||
class NewValuePage extends StatelessWidget { |
||||
NewValuePage({super.key, required this.counter}); |
||||
|
||||
factory NewValuePage.forCounter({required Counter counter}) { |
||||
switch (counter.counterType) { |
||||
case CounterType.coldWater: |
||||
return NewValuePageWithOneRate(counter: counter); |
||||
case CounterType.hotWater: |
||||
return NewValuePageWithOneRate(counter: counter); |
||||
case CounterType.gas: |
||||
return NewValuePageWithOneRate(counter: counter); |
||||
case CounterType.electrisity1rates: |
||||
return NewValuePageWithOneRate(counter: counter); |
||||
case CounterType.electrisity2rates: |
||||
return NewValuePageWithTwoRates(counter: counter); |
||||
case CounterType.electrisity3rates: |
||||
return NewValuePageWithThreeRates(counter: counter); |
||||
} |
||||
} |
||||
|
||||
final Counter counter; |
||||
final dataFormat = DateFormat("dd-MM-yyyy"); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_value_title)), |
||||
body: SizedBox.shrink(), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class NewValuePageWithOneRate extends NewValuePage { |
||||
final valueController = TextEditingController(); |
||||
final dateController = TextEditingController(); |
||||
NewValuePageWithOneRate({super.key, required super.counter}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_value_title)), |
||||
body: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Center( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
DateTimeField( |
||||
format: dataFormat, |
||||
initialValue: DateTime.now(), |
||||
controller: dateController, |
||||
onShowPicker: (context, currentValue) async { |
||||
final date = await showDatePicker( |
||||
context: context, |
||||
initialDate: currentValue ?? DateTime.now(), |
||||
firstDate: DateTime(2000), |
||||
lastDate: DateTime(2100), |
||||
); |
||||
return date; |
||||
}, |
||||
), |
||||
const SizedBox(height: 20), |
||||
TextField( |
||||
controller: valueController, |
||||
inputFormatters: [ |
||||
FilteringTextInputFormatter.allow(RegExp(r'(^-?\d*\.?\d*)')) |
||||
], |
||||
decoration: InputDecoration( |
||||
label: |
||||
Text(AppLocalizations.of(context)!.new_value_title), |
||||
//hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: '0.0', |
||||
suffixText: |
||||
counter.counterType.getUnits().getLabel(context))), |
||||
const SizedBox(height: 50), |
||||
TextButton( |
||||
onPressed: () { |
||||
DBProvider.db |
||||
.newValue(Value( |
||||
counterId: counter.id!, |
||||
date: dataFormat.parse(dateController.text).toUtc(), |
||||
rate1Id: 0, |
||||
value1: |
||||
double.tryParse(valueController.text) ?? 0.0, |
||||
value2: 0, |
||||
value3: 0)) |
||||
.then((value) => Navigator.pop(context)); |
||||
}, |
||||
child: Text( |
||||
AppLocalizations.of(context)!.add_new_address_button)) |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class NewValuePageWithTwoRates extends NewValuePage { |
||||
final value1Controller = TextEditingController(); |
||||
final value2Controller = TextEditingController(); |
||||
final dateController = TextEditingController(); |
||||
NewValuePageWithTwoRates({super.key, required super.counter}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_value_title)), |
||||
body: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Center( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
DateTimeField( |
||||
format: DateFormat("dd-MM-yyyy"), |
||||
initialValue: DateTime.now(), |
||||
controller: dateController, |
||||
onShowPicker: (context, currentValue) async { |
||||
final date = await showDatePicker( |
||||
context: context, |
||||
initialDate: currentValue ?? DateTime.now(), |
||||
firstDate: DateTime(2000), |
||||
lastDate: DateTime(2100), |
||||
); |
||||
return date; |
||||
}, |
||||
), |
||||
const SizedBox(height: 20), |
||||
TextField( |
||||
controller: value1Controller, |
||||
inputFormatters: [ |
||||
FilteringTextInputFormatter.allow(RegExp(r'(^-?\d*\.?\d*)')) |
||||
], |
||||
decoration: InputDecoration( |
||||
label: |
||||
Text(AppLocalizations.of(context)!.new_value_title), |
||||
//hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: '0.0', |
||||
suffixText: |
||||
counter.counterType.getUnits().getLabel(context))), |
||||
TextField( |
||||
controller: value2Controller, |
||||
inputFormatters: [ |
||||
FilteringTextInputFormatter.allow(RegExp(r'(^-?\d*\.?\d*)')) |
||||
], |
||||
decoration: InputDecoration( |
||||
label: |
||||
Text(AppLocalizations.of(context)!.new_value_title), |
||||
//hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: '0.0', |
||||
suffixText: |
||||
counter.counterType.getUnits().getLabel(context))), |
||||
const SizedBox(height: 50), |
||||
TextButton( |
||||
onPressed: () { |
||||
DBProvider.db |
||||
.newValue(Value( |
||||
counterId: counter.id!, |
||||
date: dataFormat.parse(dateController.text).toUtc(), |
||||
rate1Id: 0, |
||||
value1: |
||||
double.tryParse(value1Controller.text) ?? 0.0, |
||||
value2: |
||||
double.tryParse(value2Controller.text) ?? 0.0, |
||||
value3: 0)) |
||||
.then((value) => Navigator.pop(context)); |
||||
}, |
||||
child: Text( |
||||
AppLocalizations.of(context)!.add_new_address_button)) |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class NewValuePageWithThreeRates extends NewValuePage { |
||||
NewValuePageWithThreeRates({super.key, required super.counter}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_value_title)), |
||||
body: SizedBox.shrink(), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
import 'package:flutter_slidable/flutter_slidable.dart'; |
||||
|
||||
class RecordActionPane extends StatelessWidget { |
||||
const RecordActionPane({ |
||||
super.key, |
||||
this.onDelete, |
||||
this.onEdit, |
||||
}); |
||||
|
||||
final VoidCallback? onDelete; |
||||
final VoidCallback? onEdit; |
||||
|
||||
@override |
||||
ActionPane build(BuildContext context) { |
||||
return ActionPane( |
||||
motion: const BehindMotion(), |
||||
//dismissible: DismissiblePane(onDismissed: () {}), |
||||
|
||||
children: [ |
||||
SlidableAction( |
||||
onPressed: (context) { |
||||
onEdit?.call(); |
||||
}, |
||||
backgroundColor: Colors.green, |
||||
foregroundColor: Colors.white, |
||||
icon: Icons.edit, |
||||
label: AppLocalizations.of(context)!.edit, |
||||
), |
||||
SlidableAction( |
||||
onPressed: (context) { |
||||
onDelete?.call(); |
||||
}, |
||||
backgroundColor: Colors.red, |
||||
foregroundColor: Colors.white, |
||||
icon: Icons.delete, |
||||
label: AppLocalizations.of(context)!.delete, |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,62 @@
|
||||
import 'package:counters/address.dart'; |
||||
import 'package:counters/datbase.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
class UpdateAddressPage extends StatelessWidget { |
||||
final streetNameController = TextEditingController(); |
||||
final commentsController = TextEditingController(); |
||||
|
||||
UpdateAddressPage({super.key, required this.address}); |
||||
|
||||
final Address address; |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
streetNameController.text = address.streetName; |
||||
commentsController.text = address.comments; |
||||
|
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_address_title), |
||||
), |
||||
body: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
TextField( |
||||
controller: streetNameController, |
||||
decoration: InputDecoration( |
||||
hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: |
||||
AppLocalizations.of(context)!.enter_your_address), |
||||
), |
||||
const SizedBox(height: 50), |
||||
TextField( |
||||
controller: commentsController, |
||||
decoration: InputDecoration( |
||||
hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: AppLocalizations.of(context)! |
||||
.enter_your_address_comments), |
||||
), |
||||
const SizedBox(height: 50), |
||||
TextButton( |
||||
onPressed: () { |
||||
DBProvider.db |
||||
.updateAddress(Address( |
||||
id: address.id, |
||||
streetName: streetNameController.text, |
||||
comments: commentsController.text)) |
||||
.then((value) => Navigator.pop(context)); |
||||
}, |
||||
child: Text(AppLocalizations.of(context)!.edit)) |
||||
]), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,76 @@
|
||||
import 'package:counters/counters.dart'; |
||||
import 'package:counters/datbase.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
class UpdateCounterPage extends StatelessWidget { |
||||
UpdateCounterPage({super.key, required this.counter}); |
||||
|
||||
final Counter counter; |
||||
final nameController = TextEditingController(); |
||||
final dropdownController = TextEditingController(); |
||||
CounterType counterType = CounterType.coldWater; |
||||
|
||||
@override |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
nameController.text = counter.name; |
||||
counterType = counter.counterType; |
||||
dropdownController.text = counter.counterType.getLabel(context); |
||||
|
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.new_counter_title)), |
||||
body: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
DropdownMenu<CounterType>( |
||||
controller: dropdownController, |
||||
enableFilter: true, |
||||
hintText: |
||||
AppLocalizations.of(context)!.choose_type_of_counter, |
||||
expandedInsets: EdgeInsets.zero, |
||||
dropdownMenuEntries: |
||||
CounterType.values.map<DropdownMenuEntry<CounterType>>( |
||||
(CounterType icon) { |
||||
return DropdownMenuEntry<CounterType>( |
||||
value: icon, |
||||
labelWidget: Text(icon.getLabel(context)), |
||||
label: icon.getLabel(context) |
||||
//leadingIcon: Icon(icon.icon), |
||||
); |
||||
}, |
||||
).toList(), |
||||
onSelected: (value) => counterType = value!, |
||||
), |
||||
const SizedBox(height: 50), |
||||
TextField( |
||||
controller: nameController, |
||||
decoration: InputDecoration( |
||||
hintStyle: const TextStyle(color: Colors.blue), |
||||
hintText: |
||||
AppLocalizations.of(context)!.enter_counter_name), |
||||
), |
||||
const SizedBox(height: 50), |
||||
TextButton( |
||||
onPressed: () { |
||||
DBProvider.db |
||||
.updateCounter(Counter( |
||||
id: counter.id, |
||||
addressId: counter.addressId, |
||||
counterType: counterType, |
||||
name: nameController.text)) |
||||
.then((value) => Navigator.pop(context)); |
||||
}, |
||||
child: Text(AppLocalizations.of(context)!.edit)) |
||||
]), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
class Value { |
||||
final int? id; |
||||
final int counterId; |
||||
final DateTime date; |
||||
final int rate1Id; |
||||
final double value1; |
||||
final int? rate2Id; |
||||
final double? value2; |
||||
final int? rate3Id; |
||||
final double? value3; |
||||
|
||||
Value( |
||||
{this.id, |
||||
required this.counterId, |
||||
required this.date, |
||||
required this.rate1Id, |
||||
required this.value1, |
||||
this.rate2Id, |
||||
this.value2, |
||||
this.rate3Id, |
||||
this.value3}); |
||||
|
||||
factory Value.fromMap(Map<String, dynamic> json) => Value( |
||||
id: json["id"], |
||||
counterId: json["counter_id"], |
||||
date: DateTime.fromMicrosecondsSinceEpoch(json["date"], isUtc: true), |
||||
rate1Id: json["rate1_id"], |
||||
value1: json["value1"], |
||||
rate2Id: json["rate2_id"], |
||||
value2: json["value2"], |
||||
rate3Id: json["rate3_id"], |
||||
value3: json["value3"]); |
||||
|
||||
Map<String, dynamic> toMap() => { |
||||
"id": id, |
||||
"counter_id": counterId, |
||||
"date": date.microsecondsSinceEpoch, |
||||
"rate1_id": rate1Id, |
||||
"value1": value1, |
||||
"rate2_id": rate2Id, |
||||
"value2": value2, |
||||
"rate3_id": rate3Id, |
||||
"value3": value3 |
||||
}; |
||||
} |
@ -0,0 +1,119 @@
|
||||
import 'package:counters/counters.dart'; |
||||
import 'package:counters/datbase.dart'; |
||||
import 'package:counters/new_value_page.dart'; |
||||
import 'package:counters/value.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
import 'package:intl/intl.dart'; |
||||
|
||||
class ValuesPage extends StatefulWidget { |
||||
const ValuesPage({super.key, required this.counter}); |
||||
|
||||
final Counter counter; |
||||
|
||||
@override |
||||
State<ValuesPage> createState() => _ValuesPageState(); |
||||
} |
||||
|
||||
class _ValuesPageState extends State<ValuesPage> { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
var values = DBProvider.db.getValuesOfCounter(widget.counter); |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, |
||||
title: Text(AppLocalizations.of(context)!.app_title)), |
||||
body: Center( |
||||
child: FutureBuilder( |
||||
future: values, |
||||
builder: (context, snapshot) { |
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) { |
||||
return ValuesListView( |
||||
counter: widget.counter, |
||||
values: snapshot.data!.reversed.toList()); |
||||
} |
||||
|
||||
return Text(AppLocalizations.of(context)!.empty_values_list); |
||||
}, |
||||
), |
||||
), |
||||
floatingActionButton: FloatingActionButton( |
||||
onPressed: () { |
||||
Navigator.push( |
||||
context, |
||||
MaterialPageRoute( |
||||
builder: (context) => |
||||
NewValuePage.forCounter(counter: widget.counter))) |
||||
.then((_) => setState(() {})); |
||||
}, |
||||
tooltip: AppLocalizations.of(context)!.add_new_counter_tooltip, |
||||
child: const Icon(Icons.add), |
||||
)); |
||||
} |
||||
} |
||||
|
||||
class ValuesListView extends StatelessWidget { |
||||
ValuesListView({ |
||||
super.key, |
||||
required this.values, |
||||
required this.counter, |
||||
}); |
||||
|
||||
final List<Value> values; |
||||
final Counter counter; |
||||
final dataFormat = DateFormat("dd-MM-yyyy"); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return ListView.builder( |
||||
itemCount: values.length, |
||||
itemBuilder: (context, index) { |
||||
var units = counter.counterType.getUnits().getLabel(context); |
||||
var valueWidgets = List<Widget>.empty(growable: true); |
||||
valueWidgets.add(Text("T1 - ${values[index].value1} $units")); |
||||
var sum = values[index].value1; |
||||
var value = values[index]; |
||||
if (value.value2 != null && |
||||
counter.counterType.id > CounterType.electrisity1rates.id) { |
||||
valueWidgets.add(Text("T2 - ${value.value2} $units")); |
||||
sum += value.value2!; |
||||
} |
||||
if (value.value3 != null && |
||||
counter.counterType.id > CounterType.electrisity2rates.id) { |
||||
valueWidgets.add(Text("T3 - ${value.value3} $units")); |
||||
sum += value.value3!; |
||||
} |
||||
|
||||
if (valueWidgets.length > 1) { |
||||
valueWidgets.add(Text("Итого - $sum $units")); |
||||
} |
||||
return Padding( |
||||
padding: const EdgeInsets.only(left: 8.0, right: 8.0), |
||||
child: Card( |
||||
child: Align( |
||||
alignment: Alignment.centerLeft, |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
children: [ |
||||
Text(dataFormat.format(value.date.toLocal())), |
||||
Text(' ${AppLocalizations.of(context)!.values}:'), |
||||
], |
||||
), |
||||
Column( |
||||
crossAxisAlignment: CrossAxisAlignment.end, |
||||
children: valueWidgets, |
||||
) |
||||
], |
||||
), |
||||
), |
||||
)), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
Loading…
Reference in new issue