finishCommit
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_storage/get_storage.dart';
|
import 'package:get_storage/get_storage.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import '../models/response_output.dart';
|
||||||
|
|
||||||
import '../helper/constants.dart';
|
import '../helper/constants.dart';
|
||||||
|
|
||||||
@@ -14,74 +19,193 @@ class HomeController extends GetxController {
|
|||||||
final currentView = MainView.dashboard.obs;
|
final currentView = MainView.dashboard.obs;
|
||||||
|
|
||||||
//--------------Settings View---------------------------
|
//--------------Settings View---------------------------
|
||||||
final askiUserController = TextEditingController().obs;
|
final userWebMethodesController = TextEditingController().obs;
|
||||||
final askiPasswordController = TextEditingController().obs;
|
final passwordWebMethodesController = TextEditingController().obs;
|
||||||
final loginUrlController = TextEditingController().obs;
|
|
||||||
final powerUrlController = TextEditingController().obs;
|
final powerUrlController = TextEditingController().obs;
|
||||||
|
|
||||||
final pvTraunDeviceController = TextEditingController().obs;
|
|
||||||
final pvTraunDeviceMeterIdPVController = TextEditingController().obs;
|
|
||||||
final pvTraunDeviceMeterIdImportController = TextEditingController().obs;
|
|
||||||
|
|
||||||
final pvSarleinsbachDeviceController = TextEditingController().obs;
|
|
||||||
final pvSarleinsbachDeviceMeterIdPV01Controller = TextEditingController().obs;
|
|
||||||
final pvSarleinsbachDeviceMeterIdPV02Controller = TextEditingController().obs;
|
|
||||||
final pvSarleinsbachDeviceMeterIdPV03Controller = TextEditingController().obs;
|
|
||||||
final pvSarleinsbachDeviceMeterIdImportController = TextEditingController().obs;
|
|
||||||
|
|
||||||
final pvLannachDeviceController = TextEditingController().obs;
|
|
||||||
final pvLannachDeviceMeterIdPVController = TextEditingController().obs;
|
|
||||||
final pvLannachDeviceMeterIdImportController = TextEditingController().obs;
|
|
||||||
|
|
||||||
void saveSettings() {
|
void saveSettings() {
|
||||||
String askiUser = askiUserController.value.text;
|
String wbUser = userWebMethodesController.value.text;
|
||||||
String askiPassword = askiPasswordController.value.text;
|
String wbPassword = passwordWebMethodesController.value.text;
|
||||||
String loginUrl = loginUrlController.value.text;
|
String wbPowerUrl = powerUrlController.value.text;
|
||||||
String powerUrl = powerUrlController.value.text;
|
|
||||||
//traun
|
|
||||||
String pvTraunDevice = pvTraunDeviceController.value.text;
|
|
||||||
int pvTraunDeviceMeterIdPV = int.parse(pvTraunDeviceMeterIdPVController.value.text);
|
|
||||||
int pvTraunDeviceMeterIdImport = int.parse(pvTraunDeviceMeterIdImportController.value.text);
|
|
||||||
//sarleinsbach
|
|
||||||
String pvSarleinsbachDevice = pvSarleinsbachDeviceController.value.text;
|
|
||||||
int pvSarleinsbachDeviceMeterIdPV01 = int.parse(pvSarleinsbachDeviceMeterIdPV01Controller.value.text);
|
|
||||||
int pvSarleinsbachDeviceMeterIdPV02 = int.parse(pvSarleinsbachDeviceMeterIdPV02Controller.value.text);
|
|
||||||
int pvSarleinsbachDeviceMeterIdPV03 = int.parse(pvSarleinsbachDeviceMeterIdPV03Controller.value.text);
|
|
||||||
int pvSarleinsbachDeviceMeterIdImport = int.parse(pvSarleinsbachDeviceMeterIdImportController.value.text);
|
|
||||||
//lannach
|
|
||||||
String pvLannachDevice = pvLannachDeviceController.value.text;
|
|
||||||
int pvLannachDeviceMeterIdPV = int.parse(pvLannachDeviceMeterIdPVController.value.text);
|
|
||||||
int pvLannachDeviceMeterIdImport = int.parse(pvLannachDeviceMeterIdImportController.value.text);
|
|
||||||
|
|
||||||
|
boxSettings.write('wbUser', wbUser);
|
||||||
boxSettings.write('askiUser', askiUser);
|
boxSettings.write('wbPassword', wbPassword);
|
||||||
boxSettings.write('askiPassword', askiPassword);
|
boxSettings.write('wbPowerUrl', wbPowerUrl);
|
||||||
boxSettings.write('loginUrl', loginUrl);
|
|
||||||
boxSettings.write('powerUrl', powerUrl);
|
|
||||||
boxSettings.write('pvTraunDevice', pvTraunDevice);
|
|
||||||
boxSettings.write('pvTraunDeviceMeterIdPV', pvTraunDeviceMeterIdPV);
|
|
||||||
boxSettings.write('pvTraunDeviceMeterIdImport', pvTraunDeviceMeterIdImport);
|
|
||||||
boxSettings.write('pvSarleinsbachDevice', pvSarleinsbachDevice);
|
|
||||||
boxSettings.write('pvSarleinsbachDeviceMeterIdPV01', pvSarleinsbachDeviceMeterIdPV01);
|
|
||||||
boxSettings.write('pvSarleinsbachDeviceMeterIdPV02', pvSarleinsbachDeviceMeterIdPV02);
|
|
||||||
boxSettings.write('pvSarleinsbachDeviceMeterIdPV03', pvSarleinsbachDeviceMeterIdPV03);
|
|
||||||
boxSettings.write('pvSarleinsbachDeviceMeterIdImport', pvSarleinsbachDeviceMeterIdImport);
|
|
||||||
boxSettings.write('pvLannachDevice', pvLannachDevice);
|
|
||||||
boxSettings.write('pvLannachDeviceMeterIdPV', pvLannachDeviceMeterIdPV);
|
|
||||||
boxSettings.write('pvLannachDeviceMeterIdImport', pvLannachDeviceMeterIdImport);
|
|
||||||
|
|
||||||
kDisplaySnackBarGreen("Settings saved successfully!");
|
kDisplaySnackBarGreen("Settings saved successfully!");
|
||||||
|
|
||||||
print('Einstellungen gespeichert:');
|
print('Einstellungen gespeichert:');
|
||||||
print('ASKI User: $askiUser');
|
print('Admin User: $wbUser');
|
||||||
print('ASKI Password: $askiPassword');
|
print('Admin Password: $wbPassword');
|
||||||
print('Login URL: $loginUrl');
|
print('Web Methodes Power URL: $wbPowerUrl');
|
||||||
print('Power URL: $powerUrl');
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
// http get request to fetch data from the provided URL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
final dateFromToIsoController = TextEditingController().obs;
|
||||||
|
final dateToIsoController = TextEditingController().obs;
|
||||||
|
final inputSwitchBranches = RxnString('TraunPV');
|
||||||
|
final responseOutputTraunPV = ResponseOutput().obs;
|
||||||
|
final responseOutputTraunImport = ResponseOutput().obs;
|
||||||
|
final responseOutputSarleinsbachPV = ResponseOutput().obs;
|
||||||
|
final responseOutputSarleinsbachImport = ResponseOutput().obs;
|
||||||
|
final responseOutputLannachPV = ResponseOutput().obs;
|
||||||
|
final responseOutputLannachImport = ResponseOutput().obs;
|
||||||
|
|
||||||
|
/// Map: Branch → (PV Observable, Import Observable)
|
||||||
|
Map<String, Map<String, dynamic>> get _branchConfig => {
|
||||||
|
'TraunPV': {
|
||||||
|
'pv': responseOutputTraunPV,
|
||||||
|
'import': responseOutputTraunImport,
|
||||||
|
'pvSuffix': 'TraunPV',
|
||||||
|
'importSuffix': 'TraunImport',
|
||||||
|
},
|
||||||
|
'TraunImport': {
|
||||||
|
'pv': responseOutputTraunPV,
|
||||||
|
'import': responseOutputTraunImport,
|
||||||
|
'pvSuffix': 'TraunPV',
|
||||||
|
'importSuffix': 'TraunImport',
|
||||||
|
},
|
||||||
|
'SarleinsbachPV': {
|
||||||
|
'pv': responseOutputSarleinsbachPV,
|
||||||
|
'import': responseOutputSarleinsbachImport,
|
||||||
|
'pvSuffix': 'SarleinsbachPV',
|
||||||
|
'importSuffix': 'SarleinsbachImport',
|
||||||
|
},
|
||||||
|
'SarleinsbachImport': {
|
||||||
|
'pv': responseOutputSarleinsbachPV,
|
||||||
|
'import': responseOutputSarleinsbachImport,
|
||||||
|
'pvSuffix': 'SarleinsbachPV',
|
||||||
|
'importSuffix': 'SarleinsbachImport',
|
||||||
|
},
|
||||||
|
'LannachPV': {
|
||||||
|
'pv': responseOutputLannachPV,
|
||||||
|
'import': responseOutputLannachImport,
|
||||||
|
'pvSuffix': 'LannachPV',
|
||||||
|
'importSuffix': 'LannachImport',
|
||||||
|
},
|
||||||
|
'LannachImport': {
|
||||||
|
'pv': responseOutputLannachPV,
|
||||||
|
'import': responseOutputLannachImport,
|
||||||
|
'pvSuffix': 'LannachPV',
|
||||||
|
'importSuffix': 'LannachImport',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void fetchData() async {
|
||||||
|
final inputFromIso = dateFromToIsoController.value.text;
|
||||||
|
final inputToIso = dateToIsoController.value.text;
|
||||||
|
final branch = inputSwitchBranches.value;
|
||||||
|
|
||||||
|
if (branch == null || branch.isEmpty) {
|
||||||
|
kDisplaySnackBarRed('Ungültiger Standort ausgewählt.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final baseUrl = _getBaseUrl();
|
||||||
|
if (baseUrl.isEmpty) {
|
||||||
|
kDisplaySnackBarRed('Bitte zuerst die Server-URL eintragen.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final config = _branchConfig[branch];
|
||||||
|
if (config == null) {
|
||||||
|
kDisplaySnackBarRed('Unbekannte Branche: $branch');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final credentials =
|
||||||
|
'${userWebMethodesController.value.text}:${passwordWebMethodesController.value.text}';
|
||||||
|
final basicAuth = 'Basic ${base64Encode(utf8.encode(credentials))}';
|
||||||
|
final baseUri = Uri.parse(baseUrl);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fetch PV Daten
|
||||||
|
await _fetchAndStore(baseUri, inputFromIso, inputToIso,
|
||||||
|
config['pvSuffix'], config['pv'], basicAuth);
|
||||||
|
|
||||||
|
// Fetch Import Daten
|
||||||
|
await _fetchAndStore(baseUri, inputFromIso, inputToIso,
|
||||||
|
config['importSuffix'], config['import'], basicAuth);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error: $e');
|
||||||
|
kDisplaySnackBarRed('Netzwerkfehler: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hilfsfunktion - reduziert Codeverdoppelung
|
||||||
|
Future<void> _fetchAndStore(
|
||||||
|
Uri baseUri,
|
||||||
|
String inputFromIso,
|
||||||
|
String inputToIso,
|
||||||
|
String switchBranch,
|
||||||
|
dynamic responseObservable,
|
||||||
|
String basicAuth,
|
||||||
|
) async {
|
||||||
|
final uri = baseUri.replace(
|
||||||
|
queryParameters: {
|
||||||
|
...baseUri.queryParameters,
|
||||||
|
'InputFromIso': inputFromIso,
|
||||||
|
'InputToIso': inputToIso,
|
||||||
|
'InputSwitchBranches': switchBranch,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.get(
|
||||||
|
uri,
|
||||||
|
headers: {'Authorization': basicAuth, 'Accept': 'application/json'},
|
||||||
|
);
|
||||||
|
|
||||||
|
final statusGroup = response.statusCode ~/ 100;
|
||||||
|
|
||||||
|
if (statusGroup == 2) {
|
||||||
|
print('✓ $switchBranch erfolgreich geladen');
|
||||||
|
responseObservable.value = ResponseOutput.fromJson(jsonDecode(response.body));
|
||||||
|
} else if (statusGroup == 4) {
|
||||||
|
kDisplaySnackBarRed('Fehler 4xx: ${response.statusCode}');
|
||||||
|
} else if (statusGroup == 5) {
|
||||||
|
kDisplaySnackBarRed('Fehler 5xx: ${response.statusCode}');
|
||||||
|
} else {
|
||||||
|
kDisplaySnackBarRed('Fehler: ${response.statusCode}');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error fetching $switchBranch: $e');
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wählt die richtige Base-URL:
|
||||||
|
/// Web: localhost:3000 (Reverse Proxy)
|
||||||
|
/// Desktop: Direkt von Settings
|
||||||
|
String _getBaseUrl() {
|
||||||
|
final settingsUrl = powerUrlController.value.text.trim();
|
||||||
|
|
||||||
|
// Auf Web: verwende Reverse Proxy auf localhost:3000
|
||||||
|
if (kIsWeb) {
|
||||||
|
return 'http://localhost:3000/invoke/IFN_ASKI_Service.flows/getAskiData?';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auf Desktop (Windows, Linux, macOS): direkt von Settings
|
||||||
|
return settingsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
void changeView(MainView view) {
|
void changeView(MainView view) {
|
||||||
currentView.value = view;
|
currentView.value = view;
|
||||||
|
if (currentView.value == MainView.dashboard) {
|
||||||
|
inputSwitchBranches.value = 'TraunPV';
|
||||||
|
} else if (currentView.value == MainView.traun) {
|
||||||
|
inputSwitchBranches.value = 'TraunPV';
|
||||||
|
} else if (currentView.value == MainView.sarleinsbach) {
|
||||||
|
inputSwitchBranches.value = 'SarleinsbachPV';
|
||||||
|
} else if (currentView.value == MainView.lannach) {
|
||||||
|
inputSwitchBranches.value = 'LannachPV';
|
||||||
|
}
|
||||||
|
if (currentView.value != MainView.dashboard) {
|
||||||
|
fetchData(); // Fetch data whenever the view changes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleDrawer() {
|
void toggleDrawer() {
|
||||||
@@ -100,49 +224,41 @@ class HomeController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
_readStorageData();
|
_readStorageData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _readStorageData() {
|
void _readStorageData() {
|
||||||
bool hasAskiUser = boxSettings.hasData('askiUser');
|
bool hasWbUser = boxSettings.hasData('wbUser');
|
||||||
if (hasAskiUser) {
|
if (hasWbUser) {
|
||||||
askiUserController.value.text = boxSettings.read('askiUser');
|
userWebMethodesController.value.text = boxSettings.read('wbUser');
|
||||||
}
|
}
|
||||||
bool hasAskiPassword = boxSettings.hasData('askiPassword');
|
bool hasWbPassword = boxSettings.hasData('wbPassword');
|
||||||
if (hasAskiPassword) {
|
if (hasWbPassword) {
|
||||||
askiPasswordController.value.text = boxSettings.read('askiPassword');
|
passwordWebMethodesController.value.text = boxSettings.read('wbPassword');
|
||||||
}
|
}
|
||||||
bool hasLoginUrl = boxSettings.hasData('loginUrl');
|
bool hasWbPowerUrl = boxSettings.hasData('wbPowerUrl');
|
||||||
if (hasLoginUrl) {
|
if (hasWbPowerUrl) {
|
||||||
loginUrlController.value.text = boxSettings.read('loginUrl');
|
powerUrlController.value.text = boxSettings.read('wbPowerUrl');
|
||||||
}
|
|
||||||
bool hasPowerUrl = boxSettings.hasData('powerUrl');
|
|
||||||
if (hasPowerUrl) {
|
|
||||||
powerUrlController.value.text = boxSettings.read('powerUrl');
|
|
||||||
}
|
}
|
||||||
|
//fromDateTimeIso and toDateTimeIso
|
||||||
|
dateFromToIsoController.value.text = DateTime(
|
||||||
|
DateTime.now().year,
|
||||||
|
DateTime.now().month,
|
||||||
|
DateTime.now().day,
|
||||||
|
).toIso8601String();
|
||||||
|
dateToIsoController.value.text = DateTime.now().toIso8601String();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
askiUserController.close();
|
userWebMethodesController.close();
|
||||||
askiPasswordController.close();
|
|
||||||
loginUrlController.close();
|
|
||||||
powerUrlController.close();
|
powerUrlController.close();
|
||||||
pvTraunDeviceController.close();
|
passwordWebMethodesController.close();
|
||||||
pvTraunDeviceMeterIdPVController.close();
|
dateFromToIsoController.close();
|
||||||
pvTraunDeviceMeterIdImportController.close();
|
dateToIsoController.close();
|
||||||
pvSarleinsbachDeviceController.close();
|
|
||||||
pvSarleinsbachDeviceMeterIdPV01Controller.close();
|
|
||||||
pvSarleinsbachDeviceMeterIdPV02Controller.close();
|
|
||||||
pvSarleinsbachDeviceMeterIdPV03Controller.close();
|
|
||||||
pvSarleinsbachDeviceMeterIdImportController.close();
|
|
||||||
pvLannachDeviceController.close();
|
|
||||||
pvLannachDeviceMeterIdPVController.close();
|
|
||||||
pvLannachDeviceMeterIdImportController.close();
|
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-15
@@ -3,11 +3,15 @@ import 'package:get/get.dart';
|
|||||||
|
|
||||||
var kFontSizeDouble = 15.0;
|
var kFontSizeDouble = 15.0;
|
||||||
|
|
||||||
var kTextSyleLittleGrey =
|
var kTextSyleLittleGrey = TextStyle(
|
||||||
TextStyle(fontSize: 12.0, color: Colors.grey.shade800);
|
fontSize: 12.0,
|
||||||
|
color: Colors.grey.shade800,
|
||||||
|
);
|
||||||
|
|
||||||
var kTextSyleHeaderGrey =
|
var kTextSyleHeaderGrey = TextStyle(
|
||||||
TextStyle(fontSize: 25.0, color: Colors.grey.shade800);
|
fontSize: 25.0,
|
||||||
|
color: Colors.grey.shade800,
|
||||||
|
);
|
||||||
|
|
||||||
var kElevatetButtonStyleDrawer = ElevatedButton.styleFrom(
|
var kElevatetButtonStyleDrawer = ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blueGrey,
|
backgroundColor: Colors.blueGrey,
|
||||||
@@ -28,24 +32,30 @@ var kInputDecorationDropDownMenue = InputDecoration(
|
|||||||
);
|
);
|
||||||
|
|
||||||
SnackbarController kDisplaySnackBarRed(String szInfoText) {
|
SnackbarController kDisplaySnackBarRed(String szInfoText) {
|
||||||
return Get.snackbar('Info', szInfoText,
|
return Get.snackbar(
|
||||||
backgroundColor: Colors.red[600],
|
'Info',
|
||||||
snackPosition: SnackPosition.TOP,
|
szInfoText,
|
||||||
colorText: Colors.white,
|
backgroundColor: Colors.red[600],
|
||||||
snackStyle: SnackStyle.GROUNDED);
|
snackPosition: SnackPosition.TOP,
|
||||||
|
colorText: Colors.white,
|
||||||
|
snackStyle: SnackStyle.GROUNDED,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SnackbarController kDisplaySnackBarGreen(String szInfoText) {
|
SnackbarController kDisplaySnackBarGreen(String szInfoText) {
|
||||||
return Get.snackbar('Info', szInfoText,
|
return Get.snackbar(
|
||||||
backgroundColor: Colors.green[600],
|
'Info',
|
||||||
snackPosition: SnackPosition.TOP,
|
szInfoText,
|
||||||
colorText: Colors.black,
|
backgroundColor: Colors.green[600],
|
||||||
snackStyle: SnackStyle.GROUNDED);
|
snackPosition: SnackPosition.TOP,
|
||||||
|
colorText: Colors.black,
|
||||||
|
snackStyle: SnackStyle.GROUNDED,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Setting Wait for Delete
|
//Setting Wait for Delete
|
||||||
List<Map<String, dynamic>> kListMapSetting = [
|
List<Map<String, dynamic>> kListMapSetting = [
|
||||||
{'ContainerID': '', 'Info': ''}
|
{'ContainerID': '', 'Info': ''},
|
||||||
];
|
];
|
||||||
|
|
||||||
//Switching PROD/DEV
|
//Switching PROD/DEV
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
class ResponseOutput {
|
||||||
|
DataResult? dataResult;
|
||||||
|
|
||||||
|
ResponseOutput({this.dataResult});
|
||||||
|
|
||||||
|
ResponseOutput.fromJson(Map<String, dynamic> json) {
|
||||||
|
dataResult = json['DataResult'] != null
|
||||||
|
? DataResult.fromJson(json['DataResult'])
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
if (dataResult != null) {
|
||||||
|
data['DataResult'] = dataResult!.toJson();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DataResult {
|
||||||
|
String? httpStatus;
|
||||||
|
String? orderType;
|
||||||
|
String? location;
|
||||||
|
int? meterId;
|
||||||
|
List<Values>? values;
|
||||||
|
|
||||||
|
DataResult(
|
||||||
|
{this.httpStatus,
|
||||||
|
this.orderType,
|
||||||
|
this.location,
|
||||||
|
this.meterId,
|
||||||
|
this.values});
|
||||||
|
|
||||||
|
DataResult.fromJson(Map<String, dynamic> json) {
|
||||||
|
httpStatus = json['HttpStatus'];
|
||||||
|
orderType = json['OrderType'];
|
||||||
|
location = json['Location'];
|
||||||
|
meterId = json['meterId'];
|
||||||
|
if (json['values'] != null) {
|
||||||
|
values = <Values>[];
|
||||||
|
json['values'].forEach((v) {
|
||||||
|
values!.add(Values.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['HttpStatus'] = httpStatus;
|
||||||
|
data['OrderType'] = orderType;
|
||||||
|
data['Location'] = location;
|
||||||
|
data['meterId'] = meterId;
|
||||||
|
if (values != null) {
|
||||||
|
data['values'] = values!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Values {
|
||||||
|
String? datetime;
|
||||||
|
double? value;
|
||||||
|
Null tariff;
|
||||||
|
|
||||||
|
Values({this.datetime, this.value, this.tariff});
|
||||||
|
|
||||||
|
Values.fromJson(Map<String, dynamic> json) {
|
||||||
|
datetime = json['datetime'];
|
||||||
|
value = json['value'];
|
||||||
|
tariff = json['tariff'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['datetime'] = datetime;
|
||||||
|
data['value'] = value;
|
||||||
|
data['tariff'] = tariff;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,333 @@
|
|||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../models/response_output.dart';
|
||||||
|
|
||||||
|
/// Wiederverwendbares Balkendiagramm Widget für PV/Import Vergleich
|
||||||
|
///
|
||||||
|
/// Zeigt zwei Datensätze (z.B. TraunPV + TraunImport) als nebeneinander angeordnete Balken
|
||||||
|
/// - PV Daten in Orange
|
||||||
|
/// - Import Daten in Rot
|
||||||
|
/// - Y-Achse: kW Werte
|
||||||
|
/// - X-Achse: Datetime (als Uhrzeit angezeigt)
|
||||||
|
class ComparisonBarChart extends StatelessWidget {
|
||||||
|
final ResponseOutput pvData;
|
||||||
|
final ResponseOutput importData;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
const ComparisonBarChart({
|
||||||
|
required this.pvData,
|
||||||
|
required this.importData,
|
||||||
|
required this.title,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final pvValues = pvData.dataResult?.values ?? [];
|
||||||
|
final importValues = importData.dataResult?.values ?? [];
|
||||||
|
|
||||||
|
// Erstelle eine Map mit datetime als Schlüssel
|
||||||
|
final Map<String, double> pvMap = {
|
||||||
|
for (var v in pvValues) (v.datetime ?? ''): (v.value ?? 0.0),
|
||||||
|
};
|
||||||
|
final Map<String, double> importMap = {
|
||||||
|
for (var v in importValues) (v.datetime ?? ''): (v.value ?? 0.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alle eindeutigen datetimes sammeln und sortieren
|
||||||
|
final allDatetimes = {...pvMap.keys, ...importMap.keys}.toList();
|
||||||
|
allDatetimes.sort();
|
||||||
|
|
||||||
|
// Begrenzen auf die letzten 20 Einträge für bessere Lesbarkeit
|
||||||
|
// final displayDatetimes = allDatetimes.length > 20
|
||||||
|
// ? allDatetimes.sublist(allDatetimes.length - 20)
|
||||||
|
// : allDatetimes;
|
||||||
|
final displayDatetimes = allDatetimes;
|
||||||
|
|
||||||
|
if (displayDatetimes.isEmpty) {
|
||||||
|
return const Center(child: Text('Keine Daten verfügbar'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berechne Maximalwert
|
||||||
|
final allValues = [...pvMap.values, ...importMap.values];
|
||||||
|
final maxValue = allValues.fold(0.0, (a, b) => a > b ? a : b);
|
||||||
|
|
||||||
|
// Maxima für PV und Import separat
|
||||||
|
double maxPvValue = 0;
|
||||||
|
int maxPvIndex = 0;
|
||||||
|
double maxImportValue = 0;
|
||||||
|
int maxImportIndex = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < displayDatetimes.length; i++) {
|
||||||
|
final dt = displayDatetimes[i];
|
||||||
|
final pv = pvMap[dt] ?? 0.0;
|
||||||
|
final imp = importMap[dt] ?? 0.0;
|
||||||
|
|
||||||
|
if (pv > maxPvValue) {
|
||||||
|
maxPvValue = pv;
|
||||||
|
maxPvIndex = i;
|
||||||
|
}
|
||||||
|
if (imp > maxImportValue) {
|
||||||
|
maxImportValue = imp;
|
||||||
|
maxImportIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
// Chart mit fester Höhe
|
||||||
|
SizedBox(
|
||||||
|
height: 500,
|
||||||
|
child: BarChart(
|
||||||
|
BarChartData(
|
||||||
|
alignment: BarChartAlignment.spaceAround,
|
||||||
|
maxY: maxValue * 1.02,
|
||||||
|
minY: 0,
|
||||||
|
gridData: FlGridData(
|
||||||
|
show: true,
|
||||||
|
drawVerticalLine: false,
|
||||||
|
horizontalInterval: maxValue * 0.2,
|
||||||
|
),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
show: true,
|
||||||
|
topTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 40,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
final index = value.toInt();
|
||||||
|
|
||||||
|
// PV Maximum - oranger Pin
|
||||||
|
if (index == maxPvIndex) {
|
||||||
|
return Transform.translate(
|
||||||
|
offset: const Offset(-5, 0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.orange,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.withValues(alpha: 0.3),
|
||||||
|
blurRadius: 4,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
maxPvValue.toStringAsFixed(0),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Pin nach unten
|
||||||
|
CustomPaint(
|
||||||
|
size: const Size(20, 10),
|
||||||
|
painter: PinPainter(Colors.orange),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import Maximum - roter Pin
|
||||||
|
if (index == maxImportIndex) {
|
||||||
|
return Transform.translate(
|
||||||
|
offset: const Offset(5, 0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.red,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.withValues(alpha: 0.3),
|
||||||
|
blurRadius: 4,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
maxImportValue.toStringAsFixed(0),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Pin nach unten
|
||||||
|
CustomPaint(
|
||||||
|
size: const Size(20, 10),
|
||||||
|
painter: PinPainter(Colors.red),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
rightTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(showTitles: false),
|
||||||
|
),
|
||||||
|
leftTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 50,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
return Text(
|
||||||
|
'${value.toInt()} kW',
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 60,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
final index = value.toInt();
|
||||||
|
if (index < 0 || index >= displayDatetimes.length) {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
final datetime = displayDatetimes[index];
|
||||||
|
// Extrahiere nur Uhrzeit (HH:mm)
|
||||||
|
final timePart = datetime.contains('T')
|
||||||
|
? datetime.split('T').last.substring(0, 5)
|
||||||
|
: datetime.substring(0, 5);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: RotatedBox(
|
||||||
|
quarterTurns: 1,
|
||||||
|
child: Text(
|
||||||
|
timePart,
|
||||||
|
style: const TextStyle(fontSize: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
barGroups: _generateBarGroups(
|
||||||
|
displayDatetimes,
|
||||||
|
pvMap,
|
||||||
|
importMap,
|
||||||
|
),
|
||||||
|
borderData: FlBorderData(show: true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
// Legende
|
||||||
|
Wrap(
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
spacing: 24,
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(width: 16, height: 16, color: Colors.orange),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Text('PV-Anlage(kW)'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(width: 16, height: 16, color: Colors.red),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Text('Netzbezug(kW)'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BarChartGroupData> _generateBarGroups(
|
||||||
|
List<String> datetimes,
|
||||||
|
Map<String, double> pvMap,
|
||||||
|
Map<String, double> importMap,
|
||||||
|
) {
|
||||||
|
return List.generate(datetimes.length, (index) {
|
||||||
|
final datetime = datetimes[index];
|
||||||
|
final pvValue = pvMap[datetime] ?? 0.0;
|
||||||
|
final importValue = importMap[datetime] ?? 0.0;
|
||||||
|
|
||||||
|
return BarChartGroupData(
|
||||||
|
x: index,
|
||||||
|
barRods: [
|
||||||
|
// Orange Bar für PV
|
||||||
|
BarChartRodData(
|
||||||
|
toY: pvValue,
|
||||||
|
color: Colors.orange,
|
||||||
|
width: 8,
|
||||||
|
borderRadius: const BorderRadius.vertical(top: Radius.circular(4)),
|
||||||
|
),
|
||||||
|
// Roter Bar für Import
|
||||||
|
BarChartRodData(
|
||||||
|
toY: importValue,
|
||||||
|
color: Colors.red,
|
||||||
|
width: 8,
|
||||||
|
borderRadius: const BorderRadius.vertical(top: Radius.circular(4)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PinPainter extends CustomPainter {
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
PinPainter(this.color);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final paint = Paint()..color = color;
|
||||||
|
final path = Path();
|
||||||
|
path.moveTo(size.width / 2, size.height);
|
||||||
|
path.lineTo(0, 0);
|
||||||
|
path.lineTo(size.width, 0);
|
||||||
|
path.close();
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(PinPainter oldDelegate) => false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class StaticLocationDropdown extends StatelessWidget {
|
||||||
|
const StaticLocationDropdown({super.key, required this.selectedValue});
|
||||||
|
|
||||||
|
final RxnString selectedValue;
|
||||||
|
|
||||||
|
static const List<String> _locations = [
|
||||||
|
'TraunPV',
|
||||||
|
'TraunImport',
|
||||||
|
'SarleinsbachPV',
|
||||||
|
'SarleinsbachImport',
|
||||||
|
'LannachPV',
|
||||||
|
'LannachImport',
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Obx(() => DropdownButtonFormField<String>(
|
||||||
|
initialValue: selectedValue.value ?? _locations.first,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Select Location / Data Source',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 15),
|
||||||
|
),
|
||||||
|
items: _locations.map((String location) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: location,
|
||||||
|
child: Text(location),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
selectedValue.value = newValue;
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,38 +11,69 @@ class DashboardView extends StatelessWidget {
|
|||||||
var hCtrl = Get.find<HomeController>();
|
var hCtrl = Get.find<HomeController>();
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
width: 1000,
|
width: 1000,
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
runSpacing: 20,
|
runSpacing: 20,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
Padding(
|
||||||
onTap: () {
|
padding: const EdgeInsets.only(right: 35.0),
|
||||||
hCtrl.changeView(MainView.dashboard);
|
child: TextField(
|
||||||
},
|
controller: hCtrl.dateFromToIsoController.value,
|
||||||
child: Image.asset('assets/images/AskiDashboard.png',width: 450),
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Input From ISO',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
hintText: 'Enter Input From ISO',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 35.0),
|
||||||
|
child: TextField(
|
||||||
|
controller: hCtrl.dateToIsoController.value,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Input To ISO',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
hintText: 'Enter Input To ISO',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Padding(
|
||||||
|
// padding: const EdgeInsets.only(right: 35.0),
|
||||||
|
// child: StaticLocationDropdown(
|
||||||
|
// selectedValue: hCtrl.inputSwitchBranches,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
hCtrl.changeView(MainView.dashboard);
|
||||||
|
},
|
||||||
|
child: Image.asset('assets/images/AskiDashboard.png', width: 450),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
hCtrl.changeView(MainView.traun);
|
||||||
|
},
|
||||||
|
child: Image.asset('assets/images/AskiTraun.png', width: 450),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
hCtrl.changeView(MainView.sarleinsbach);
|
||||||
|
},
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/AskiSarleinsbach.png',
|
||||||
|
width: 450,
|
||||||
),
|
),
|
||||||
InkWell(
|
),
|
||||||
onTap: () {
|
InkWell(
|
||||||
hCtrl.changeView(MainView.traun);
|
onTap: () {
|
||||||
},
|
hCtrl.changeView(MainView.lannach);
|
||||||
child: Image.asset('assets/images/AskiTraun.png',width: 450),
|
},
|
||||||
),
|
child: Image.asset('assets/images/AskiLannach.png', width: 450),
|
||||||
InkWell(
|
),
|
||||||
onTap: () {
|
],
|
||||||
hCtrl.changeView(MainView.sarleinsbach);
|
),
|
||||||
},
|
|
||||||
child: Image.asset('assets/images/AskiSarleinsbach.png',width: 450),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
hCtrl.changeView(MainView.lannach);
|
|
||||||
},
|
|
||||||
child: Image.asset('assets/images/AskiLannach.png',width: 450),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import '../../controller/home_controller.dart';
|
import '../../controller/home_controller.dart';
|
||||||
|
import '../comparison_bar_chart.dart';
|
||||||
|
|
||||||
class LannachView extends StatelessWidget {
|
class LannachView extends StatelessWidget {
|
||||||
const LannachView({super.key});
|
const LannachView({super.key});
|
||||||
@@ -23,11 +24,19 @@ class LannachView extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
body: const Center(
|
body: Obx(
|
||||||
child: Text(
|
() => hCtrl.responseOutputLannachPV.value.dataResult?.values?.isEmpty ?? true
|
||||||
"PV Lannach",
|
? const Center(
|
||||||
style: TextStyle(fontSize: 30),
|
child: Text(
|
||||||
),
|
'Keine Daten verfügbar',
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ComparisonBarChart(
|
||||||
|
pvData: hCtrl.responseOutputLannachPV.value,
|
||||||
|
importData: hCtrl.responseOutputLannachImport.value,
|
||||||
|
title: 'LannachPV/Import Vergleich',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
import '../../controller/home_controller.dart';
|
import '../../controller/home_controller.dart';
|
||||||
|
import '../comparison_bar_chart.dart';
|
||||||
|
|
||||||
class SarleinsbachView extends StatelessWidget {
|
class SarleinsbachView extends StatelessWidget {
|
||||||
const SarleinsbachView({super.key});
|
const SarleinsbachView({super.key});
|
||||||
@@ -24,11 +25,19 @@ class SarleinsbachView extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
body: const Center(
|
body: Obx(
|
||||||
child: Text(
|
() => hCtrl.responseOutputSarleinsbachPV.value.dataResult?.values?.isEmpty ?? true
|
||||||
"PV Sarleinsbach",
|
? const Center(
|
||||||
style: TextStyle(fontSize: 30),
|
child: Text(
|
||||||
),
|
'Keine Daten verfügbar',
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ComparisonBarChart(
|
||||||
|
pvData: hCtrl.responseOutputSarleinsbachPV.value,
|
||||||
|
importData: hCtrl.responseOutputSarleinsbachImport.value,
|
||||||
|
title: 'SarleinsbachPV/Import Vergleich',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class SettingsView extends StatelessWidget {
|
|||||||
var hCtrl = Get.find<HomeController>();
|
var hCtrl = Get.find<HomeController>();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Data Settings'),
|
title: const Text('System Settings'),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
backgroundColor: Colors.blueGrey,
|
backgroundColor: Colors.blueGrey,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
@@ -41,43 +41,34 @@ class SettingsView extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Text(
|
Text(
|
||||||
"Please enter User and Password",
|
"Please enter User and Password for Web Methodes",
|
||||||
style: TextStyle(fontSize: 18),
|
style: TextStyle(fontSize: 18),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
TextField(
|
TextField(
|
||||||
controller: hCtrl.askiUserController.value,
|
controller: hCtrl.userWebMethodesController.value,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Input User',
|
labelText: 'Input User',
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
hintText: 'Enter ASKI User',
|
hintText: 'Enter Admin User',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
TextField(
|
TextField(
|
||||||
controller: hCtrl.askiPasswordController.value,
|
controller: hCtrl.passwordWebMethodesController.value,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Input Password',
|
labelText: 'Input Password',
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
hintText: 'Enter ASKI Password',
|
hintText: 'Enter Admin Password',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Text(
|
Text(
|
||||||
"Please enter the URLs for the ASKI login and power data",
|
"Please enter the URLs for WebMethodes PV data Url",
|
||||||
style: TextStyle(fontSize: 18),
|
style: TextStyle(fontSize: 18),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
TextField(
|
|
||||||
controller: hCtrl.loginUrlController.value,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Login URL',
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
hintText: 'Enter ASKI Login URL',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 10),
|
|
||||||
TextField(
|
TextField(
|
||||||
controller: hCtrl.powerUrlController.value,
|
controller: hCtrl.powerUrlController.value,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@@ -85,21 +76,7 @@ class SettingsView extends StatelessWidget {
|
|||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
hintText: 'Enter ASKI Power URL',
|
hintText: 'Enter ASKI Power URL',
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please enter the device for PV Traun and PV Sarleinsbach and PV Lannach",
|
|
||||||
style: TextStyle(fontSize: 18),
|
|
||||||
),
|
|
||||||
SizedBox(height: 10),
|
|
||||||
TextField(
|
|
||||||
controller: hCtrl.pvTraunDeviceController.value,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'PV Traun Device',
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
hintText: 'Enter PV Traun Device',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import '../../controller/home_controller.dart';
|
import '../../controller/home_controller.dart';
|
||||||
|
import '../comparison_bar_chart.dart';
|
||||||
|
|
||||||
class TraunView extends StatelessWidget {
|
class TraunView extends StatelessWidget {
|
||||||
const TraunView({super.key});
|
const TraunView({super.key});
|
||||||
@@ -23,11 +24,19 @@ class TraunView extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
body: const Center(
|
body: Obx(
|
||||||
child: Text(
|
() => hCtrl.responseOutputTraunPV.value.dataResult?.values?.isEmpty ?? true
|
||||||
"PV Traun",
|
? const Center(
|
||||||
style: TextStyle(fontSize: 30),
|
child: Text(
|
||||||
),
|
'Keine Daten verfügbar',
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ComparisonBarChart(
|
||||||
|
pvData: hCtrl.responseOutputTraunPV.value,
|
||||||
|
importData: hCtrl.responseOutputTraunImport.value,
|
||||||
|
title: 'TraunPV/Import Vergleich',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.9"
|
version: "1.0.9"
|
||||||
|
equatable:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
sha256: "3bce007a596ff8b3119c45d68aaef631272537c03d30e5d4534dd24bf4c5eaa2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -89,6 +97,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
fl_chart:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: fl_chart
|
||||||
|
sha256: d0f0d49112f2f4b192481c16d05b6418bd7820e021e265a3c22db98acf7ed7fb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.68.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -131,6 +147,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.2"
|
||||||
|
http:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.0"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.2"
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ environment:
|
|||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
|
fl_chart: ^0.68.0
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
get: ^4.7.3
|
get: ^4.7.3
|
||||||
get_storage: ^2.1.1
|
get_storage: ^2.1.1
|
||||||
|
http: ^1.6.0
|
||||||
intl: ^0.20.3
|
intl: ^0.20.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user