diff --git a/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart b/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart index c2e69d39..d36f0c74 100644 --- a/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart +++ b/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart @@ -1,28 +1,218 @@ import 'dart:async'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/bloc/smart_power_event.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/bloc/smart_power_state.dart'; +import 'package:syncrow_web/pages/device_managment/power_clamp/models/device_event.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_model.dart'; +import 'package:syncrow_web/pages/device_managment/power_clamp/view/power_chart.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; class SmartPowerBloc extends Bloc { SmartPowerBloc({required this.deviceId}) : super(SmartPowerInitial()) { on(_onFetchDeviceStatus); - // on(_onControl); + on(_onArrowPressed); on(_onFetchBatchStatus); + on(_onPageChanged); on(_onBatchControl); - // on(_onFactoryReset); + on(_filterRecordsByDate); + on(checkDayMonthYearSelected); + // SelectDateEvent } late PowerClampModel deviceStatus; final String deviceId; Timer? _timer; List> phaseData = []; + int currentPage = 0; + + List record = [ + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:43'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:35'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:29'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:25'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:21'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:17'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:15:07'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:14:47'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:14:40'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:14:23'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2024-10-23 11:14:13'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:43'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:35'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:29'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:25'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:21'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:17'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:15:07'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:14:47'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:14:40'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:14:23'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-10-23 11:14:13'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:43'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:35'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:29'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:25'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:21'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:17'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:15:07'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:14:47'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:14:40'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:14:23'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-23 11:14:13'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-11 11:15:43'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-11 11:15:35'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-12 11:15:29'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-13 11:15:25'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-14 11:15:21'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-15 11:15:17'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-16 11:15:07'), + value: '2286'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-17 11:14:47'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-18 11:14:40'), + value: '2284'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-19 11:14:23'), + value: '2285'), + EventDevice( + code: 'VoltageA', + eventTime: DateTime.parse('2023-02-20 11:14:13'), + value: '2284'), + ]; + FutureOr _onFetchDeviceStatus( SmartPowerFetchDeviceEvent event, Emitter emit) async { emit(SmartPowerLoading()); try { - var status = await DevicesManagementApi().getPowerClampInfo(event.deviceId); + var status = + await DevicesManagementApi().getPowerClampInfo(event.deviceId); deviceStatus = PowerClampModel.fromJson(status); phaseData = [ @@ -48,21 +238,30 @@ class SmartPowerBloc extends Bloc { 'powerFactor': '${deviceStatus.status.phaseC.dataPoints[3].value}', }, ]; - emit(SmartPowerStatusLoaded(deviceStatus)); + emit(SmartPowerStatusLoaded(deviceStatus, currentPage)); } catch (e) { emit(SmartPowerError(e.toString())); } } + FutureOr _onArrowPressed( + SmartPowerArrowPressedEvent event, Emitter emit) { + currentPage = (currentPage + event.direction + 4) % 4; + emit(SmartPowerStatusLoaded(deviceStatus, currentPage)); + } + + FutureOr _onPageChanged( + SmartPowerPageChangedEvent event, Emitter emit) { + currentPage = event.page; + emit(SmartPowerStatusLoaded(deviceStatus, currentPage)); + } + Future _onFetchBatchStatus( SmartPowerFetchBatchEvent event, Emitter emit) async { emit(SmartPowerLoading()); try { - - await DevicesManagementApi().getBatchStatus(event.devicesIds); - // deviceStatus = - // SmartPowerStatusModel.fromJson(event.devicesIds.first, status.status); - emit(SmartPowerStatusLoaded(deviceStatus)); + await DevicesManagementApi().getBatchStatus(event.devicesIds); + emit(SmartPowerStatusLoaded(deviceStatus, currentPage)); } catch (e) { emit(SmartPowerError(e.toString())); } @@ -76,30 +275,408 @@ class SmartPowerBloc extends Bloc { FutureOr _onBatchControl( SmartPowerBatchControl event, Emitter emit) async { - // final oldValue = _getValueByCode(event.code); - - // _updateLocalValue(event.code, event.value); - - emit(SmartPowerStatusLoaded(deviceStatus)); - - FutureOr _onFactoryReset( - WallLightFactoryReset event, Emitter emit) async { - emit(SmartPowerLoading()); - try { - final response = await DevicesManagementApi().factoryReset( - event.factoryReset, - event.deviceId, - ); - if (!response) { - emit(SmartPowerError('Failed')); - } else { - emit(SmartPowerStatusLoaded(deviceStatus)); - } - } catch (e) { - emit(SmartPowerError(e.toString())); - } - } + emit(SmartPowerStatusLoaded(deviceStatus, currentPage)); } - + List filteredRecords = []; + + int currentIndex = 0; + final List views = ['Day', 'Month', 'Year']; + + Widget dateSwitcher() { + void switchView(int direction) { + currentIndex = (currentIndex + direction + views.length) % views.length; + } + + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + icon: const Icon(Icons.arrow_left), + onPressed: () { + setState(() { + switchView(-1); + }); + }, + ), + Text( + views[currentIndex], + style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w500), + ), + IconButton( + icon: const Icon(Icons.arrow_right), + onPressed: () { + setState(() { + switchView(1); + }); + }, + ), + ], + ); + }, + ); + } + + Future selectMonthAndYear(BuildContext context) async { + int selectedYear = DateTime.now().year; + int selectedMonth = DateTime.now().month; + + FixedExtentScrollController yearController = + FixedExtentScrollController(initialItem: selectedYear - 1905); + FixedExtentScrollController monthController = + FixedExtentScrollController(initialItem: selectedMonth - 1); + + return await showDialog( + context: context, + builder: (BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + color: Colors.white, + height: 350, + width: 350, + child: Column( + children: [ + const Padding( + padding: EdgeInsets.all(16.0), + child: Text( + 'Select Month and Year', + style: + TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + const Divider(), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Spacer(), + Expanded( + child: ListWheelScrollView.useDelegate( + controller: yearController, + overAndUnderCenterOpacity: 0.2, + itemExtent: 50, + onSelectedItemChanged: (index) { + selectedYear = 1905 + index; + }, + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + return Center( + child: Text( + (1905 + index).toString(), + style: const TextStyle(fontSize: 18), + ), + ); + }, + childCount: 200, + ), + ), + ), + Expanded( + flex: 2, + child: ListWheelScrollView.useDelegate( + controller: monthController, + overAndUnderCenterOpacity: 0.2, + itemExtent: 50, + onSelectedItemChanged: (index) { + selectedMonth = index + 1; + }, + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + return Center( + child: Text( + DateFormat.MMMM() + .format(DateTime(0, index + 1)), + style: const TextStyle(fontSize: 18), + ), + ); + }, + childCount: 12, + ), + ), + ), + const Spacer(), + ], + ), + ), + const Divider(), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, vertical: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('OK'), + onPressed: () { + final selectedDateTime = + DateTime(selectedYear, selectedMonth); + Navigator.of(context).pop(selectedDateTime); + }, + ), + ], + ), + ), + ], + ), + ), + ], + ); + }, + ); + } + + Future selectYear(BuildContext context) async { + int selectedYear = DateTime.now().year; + FixedExtentScrollController yearController = + FixedExtentScrollController(initialItem: selectedYear - 1905); + + return await showDialog( + context: context, + builder: (BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + color: Colors.white, + height: 350, + width: 350, + child: Column( + children: [ + const Padding( + padding: EdgeInsets.all(16.0), + child: Text( + 'Select Year', + style: + TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + const Divider(), + Expanded( + child: ListWheelScrollView.useDelegate( + controller: yearController, + overAndUnderCenterOpacity: 0.2, + itemExtent: 50, + onSelectedItemChanged: (index) { + selectedYear = 1905 + index; + }, + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + return Center( + child: Text( + (1905 + index).toString(), + style: const TextStyle(fontSize: 18), + ), + ); + }, + childCount: 200, + ), + ), + ), + const Divider(), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, vertical: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context) + .pop(); // Pops without value, returning null + }, + ), + TextButton( + child: const Text('OK'), + onPressed: () { + final selectedDateTime = DateTime(selectedYear); + Navigator.of(context).pop( + selectedDateTime); // Pops with the selected date + }, + ), + ], + ), + ), + ], + ), + ), + ], + ); + }, + ); + } + + Future dayMonthYearPicker({ + required BuildContext context, + }) async { + DateTime selectedDate = DateTime.now(); // Default selected date + + return await showDialog( + context: context, + builder: (BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + color: Colors.white, + height: 350, + width: 350, + child: Column( + children: [ + Expanded( + child: CupertinoDatePicker( + mode: CupertinoDatePickerMode.date, + initialDateTime: DateTime.now(), + minimumYear: 1900, + maximumYear: DateTime.now().year, + onDateTimeChanged: (DateTime newDateTime) { + selectedDate = + newDateTime; // Update the selected date when changed + }, + ), + ), + const Divider(), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, vertical: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context) + .pop(); // Dismiss the modal without returning a value + }, + ), + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context) + .pop(selectedDate); // Return the selected date + }, + ), + ], + ), + ), + ], + ), + ), + ], + ); + }, + ); + } + + DateTime? dateTime = DateTime.now(); + String formattedDate = DateFormat('yyyy/MM/dd').format(DateTime.now()); + void checkDayMonthYearSelected( + SelectDateEvent event, Emitter emit) async { + // emit(SmartPowerLoading()); + + if (currentIndex == 0) { + await dayMonthYearPicker(context: event.context).then( + (newDate) { + if (newDate != null) { + dateTime = newDate; + formattedDate = DateFormat('yyyy/MM/dd').format(dateTime!); + + add(FilterRecordsByDateEvent( + selectedDate: dateTime!, + viewType: views[currentIndex], + )); + } + }, + ); + } else if (currentIndex == 1) { + await selectMonthAndYear(event.context).then( + (newDate) { + if (newDate != null) { + dateTime = newDate; + formattedDate = DateFormat('yyyy-MM').format(dateTime!); + + add(FilterRecordsByDateEvent( + selectedDate: dateTime!, + viewType: views[currentIndex], + )); + } + }, + ); + } else if (currentIndex == 2) { + await selectYear(event.context).then( + (newDate) { + if (newDate != null) { + dateTime = newDate; + formattedDate = DateFormat('yyyy').format(dateTime!); + + add(FilterRecordsByDateEvent( + selectedDate: dateTime!, + viewType: views[currentIndex], + )); + } + }, + ); + } + emit(DateSelectedState()); + } + + List energyDataList = []; + void _filterRecordsByDate( + FilterRecordsByDateEvent event, Emitter emit) { + print('dddddddddddddddddddd'); + // emit(SmartPowerLoading()); + if (event.viewType == 'Year') { + filteredRecords = record + .where((record) => record.eventTime!.year == event.selectedDate.year) + .toList(); + } else if (event.viewType == 'Month') { + filteredRecords = record + .where((record) => + record.eventTime!.year == event.selectedDate.year && + record.eventTime!.month == event.selectedDate.month) + .toList(); + } else if (event.viewType == 'Day') { + filteredRecords = record + .where((record) => + record.eventTime!.year == event.selectedDate.year && + record.eventTime!.month == event.selectedDate.month && + record.eventTime!.day == event.selectedDate.day) + .toList(); + } + String getMonthShortName(int month) { + final date = DateTime(0, month); + return DateFormat.MMM().format(date); + } + + energyDataList = filteredRecords.map((eventDevice) { + return EnergyData( + event.viewType == 'Year' + ? getMonthShortName( + int.tryParse(DateFormat('MM').format(eventDevice.eventTime!))!) + : event.viewType == 'Month' + ? DateFormat('yyyy/MM/dd').format(eventDevice.eventTime!) + : DateFormat('HH:mm:ss').format(eventDevice.eventTime!), + double.parse(eventDevice.value!), + ); + }).toList(); + + Future.delayed(const Duration(milliseconds: 500)); + emit(SmartPowerStatusLoaded(deviceStatus, currentPage)); + + emit(FilterRecordsState(filteredRecords: energyDataList)); + } } diff --git a/lib/pages/device_managment/power_clamp/bloc/smart_power_event.dart b/lib/pages/device_managment/power_clamp/bloc/smart_power_event.dart index 9eb680cd..0e18cbb9 100644 --- a/lib/pages/device_managment/power_clamp/bloc/smart_power_event.dart +++ b/lib/pages/device_managment/power_clamp/bloc/smart_power_event.dart @@ -1,4 +1,5 @@ import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; class SmartPowerEvent extends Equatable { @@ -57,6 +58,7 @@ class WallLightFactoryReset extends SmartPowerEvent { @override List get props => [deviceId, factoryReset]; } + class PageChangedEvent extends SmartPowerEvent { final int newPage; PageChangedEvent(this.newPage); @@ -65,4 +67,27 @@ class PageChangedEvent extends SmartPowerEvent { class PageArrowPressedEvent extends SmartPowerEvent { final int direction; PageArrowPressedEvent(this.direction); -} \ No newline at end of file +} + +class SmartPowerArrowPressedEvent extends SmartPowerEvent { + final int direction; + SmartPowerArrowPressedEvent(this.direction); +} + +class SmartPowerPageChangedEvent extends SmartPowerEvent { + final int page; + SmartPowerPageChangedEvent(this.page); +} + +class SelectDateEvent extends SmartPowerEvent { + BuildContext context; + SelectDateEvent({required this.context}); +} + +class FilterRecordsByDateEvent extends SmartPowerEvent { + final DateTime selectedDate; + final String viewType; // 'Day', 'Month', 'Year' + + FilterRecordsByDateEvent( + {required this.selectedDate, required this.viewType}); +} diff --git a/lib/pages/device_managment/power_clamp/bloc/smart_power_state.dart b/lib/pages/device_managment/power_clamp/bloc/smart_power_state.dart index 7d705a72..ad75872e 100644 --- a/lib/pages/device_managment/power_clamp/bloc/smart_power_state.dart +++ b/lib/pages/device_managment/power_clamp/bloc/smart_power_state.dart @@ -1,5 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_model.dart'; +import 'package:syncrow_web/pages/device_managment/power_clamp/view/power_chart.dart'; class SmartPowerState extends Equatable { @override @@ -9,16 +10,15 @@ class SmartPowerState extends Equatable { class SmartPowerInitial extends SmartPowerState {} class SmartPowerLoading extends SmartPowerState {} +class DateSelectedState extends SmartPowerState {} class SmartPowerStatusLoaded extends SmartPowerState { - final PowerClampModel status; - - SmartPowerStatusLoaded(this.status); - - @override - List get props => [status]; + final PowerClampModel deviceStatus; + final int currentPage; + SmartPowerStatusLoaded(this.deviceStatus, this.currentPage); } + class SmartPowerError extends SmartPowerState { final String message; @@ -55,3 +55,8 @@ class SmartPowerBatchStatusLoaded extends SmartPowerState { List get props => [status]; } +class FilterRecordsState extends SmartPowerState { + final List filteredRecords; + + FilterRecordsState({required this.filteredRecords}); +} diff --git a/lib/pages/device_managment/power_clamp/models/device_event.dart b/lib/pages/device_managment/power_clamp/models/device_event.dart new file mode 100644 index 00000000..09f7b46e --- /dev/null +++ b/lib/pages/device_managment/power_clamp/models/device_event.dart @@ -0,0 +1,23 @@ + +class EventDevice { + final String? code; + final DateTime? eventTime; + final String? value; + + EventDevice({ + this.code, + this.eventTime, + this.value, + }); + + EventDevice.fromJson(Map json) + : code = json['code'] as String?, + eventTime = json['eventTime'] , + value = json['value'] as String?; + + Map toJson() => { + 'code': code, + 'eventTime': eventTime, + 'value': value, + }; +} diff --git a/lib/pages/device_managment/power_clamp/view/power_chart.dart b/lib/pages/device_managment/power_clamp/view/power_chart.dart index 28e91cd5..a4cb4a07 100644 --- a/lib/pages/device_managment/power_clamp/view/power_chart.dart +++ b/lib/pages/device_managment/power_clamp/view/power_chart.dart @@ -6,11 +6,17 @@ class EnergyConsumptionPage extends StatefulWidget { final List chartData; final double totalConsumption; final String date; + final String formattedDate; + final Widget widget; + final Function()? onTap; EnergyConsumptionPage({ required this.chartData, required this.totalConsumption, required this.date, + required this.widget, + required this.onTap, + required this.formattedDate, }); @override @@ -85,135 +91,186 @@ class _EnergyConsumptionPageState extends State { ], ), Expanded( - child: Padding( - padding: const EdgeInsets.only(top: 15), - child: LineChart( - LineChartData( - lineTouchData: LineTouchData( - handleBuiltInTouches: true, - touchSpotThreshold: 2, - getTouchLineEnd: (barData, spotIndex) { - return 10.0; - }, - touchTooltipData: LineTouchTooltipData( - getTooltipColor: (touchTooltipItem) => Colors.white, - tooltipRoundedRadius: 10.0, - tooltipPadding: const EdgeInsets.all(8.0), - tooltipBorder: BorderSide(color: Colors.grey, width: 1), - getTooltipItems: (List touchedSpots) { - return touchedSpots.map((spot) { - return LineTooltipItem( - '${spot.x},\n ${spot.y.toStringAsFixed(2)} kWh', - const TextStyle( - color: Colors.blue, - fontWeight: FontWeight.bold, - fontSize: 12, - ), + child: Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(top: 15), + child: LineChart( + LineChartData( + lineTouchData: LineTouchData( + handleBuiltInTouches: true, + touchSpotThreshold: 2, + getTouchLineEnd: (barData, spotIndex) { + return 10.0; + }, + touchTooltipData: LineTouchTooltipData( + getTooltipColor: (touchTooltipItem) => + Colors.white, + tooltipRoundedRadius: 10.0, + tooltipPadding: const EdgeInsets.all(8.0), + tooltipBorder: + BorderSide(color: Colors.grey, width: 1), + getTooltipItems: + (List touchedSpots) { + return touchedSpots.map((spot) { + return LineTooltipItem( + '${spot.x},\n ${spot.y.toStringAsFixed(2)} kWh', + const TextStyle( + color: Colors.blue, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ); + }).toList(); + }, + )), + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + ), + ), + leftTitles: const AxisTitles( + sideTitles: SideTitles( + showTitles: false, + ), + ), + rightTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + ), + ), + topTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + reservedSize: 70, + getTitlesWidget: (value, meta) { + int index = value.toInt(); + if (index >= 0 && index < _chartData.length) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: RotatedBox( + quarterTurns: -1, + child: Text(_chartData[index].time, + style: TextStyle(fontSize: 10)), + ), + ); + } + return const SizedBox.shrink(); + }, + ), + ), + ), + gridData: FlGridData( + show: true, + drawVerticalLine: true, + horizontalInterval: 1, + verticalInterval: 1, + getDrawingVerticalLine: (value) { + return FlLine( + color: Colors.grey.withOpacity(0.2), + dashArray: [8, 8], + strokeWidth: 1, ); - }).toList(); - }, - )), - titlesData: FlTitlesData( - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: false, - ), - ), - leftTitles: const AxisTitles( - sideTitles: SideTitles( - showTitles: false, - ), - ), - rightTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: false, - ), - ), - topTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: false, - reservedSize: 70, - getTitlesWidget: (value, meta) { - int index = value.toInt(); - if (index >= 0 && index < _chartData.length) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: RotatedBox( - quarterTurns: -1, - child: Text(_chartData[index].time, - style: TextStyle(fontSize: 10)), - ), + }, + getDrawingHorizontalLine: (value) { + return FlLine( + color: Colors.grey.withOpacity(0.2), + dashArray: [5, 5], + strokeWidth: 1, ); - } - return const SizedBox.shrink(); - }, - ), - ), - ), - gridData: FlGridData( - show: true, - drawVerticalLine: true, - horizontalInterval: 1, - verticalInterval: 1, - getDrawingVerticalLine: (value) { - return FlLine( - color: Colors.grey.withOpacity(0.2), - dashArray: [8, 8], - strokeWidth: 1, - ); - }, - getDrawingHorizontalLine: (value) { - return FlLine( - color: Colors.grey.withOpacity(0.2), - dashArray: [5, 5], - strokeWidth: 1, - ); - }, - drawHorizontalLine: false, - ), - lineBarsData: [ - LineChartBarData( - preventCurveOvershootingThreshold: 0.1, - curveSmoothness: 0.5, - preventCurveOverShooting: true, - aboveBarData: BarAreaData(), - spots: _chartData - .asMap() - .entries - .map((entry) => FlSpot( - entry.key.toDouble(), entry.value.consumption)) - .toList(), - isCurved: true, - color: ColorsManager.primaryColor.withOpacity(0.6), - show: true, - shadow: Shadow(color: Colors.black12), - belowBarData: BarAreaData( - show: true, - gradient: LinearGradient( - colors: [ - ColorsManager.primaryColor.withOpacity(0.5), - Colors.blue.withOpacity(0.1), - ], - begin: Alignment.center, - end: Alignment.bottomCenter, + }, + drawHorizontalLine: false, + ), + lineBarsData: [ + LineChartBarData( + preventCurveOvershootingThreshold: 0.1, + curveSmoothness: 0.5, + preventCurveOverShooting: true, + aboveBarData: BarAreaData(), + spots: _chartData + .asMap() + .entries + .map((entry) => FlSpot(entry.key.toDouble(), + entry.value.consumption)) + .toList(), + isCurved: true, + color: ColorsManager.primaryColor.withOpacity(0.6), + show: true, + shadow: Shadow(color: Colors.black12), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + ColorsManager.primaryColor.withOpacity(0.5), + Colors.blue.withOpacity(0.1), + ], + begin: Alignment.center, + end: Alignment.bottomCenter, + ), + ), + dotData: FlDotData( + show: false, + ), + isStrokeCapRound: true, + barWidth: 2, + ), + ], + borderData: FlBorderData( + show: false, + border: Border.all( + color: Color(0xff023DFE).withOpacity(0.7), + width: 10, + ), ), ), - dotData: FlDotData( - show: false, - ), - isStrokeCapRound: true, - barWidth: 2, - ), - ], - borderData: FlBorderData( - show: false, - border: Border.all( - color: Color(0xff023DFE).withOpacity(0.7), - width: 10, ), ), ), - ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 2, + child: Container( + decoration: BoxDecoration( + color: ColorsManager.graysColor, + borderRadius: BorderRadius.circular(10), + ), + child: + Expanded(child: Container(child: widget.widget)), + ), + ), + Spacer(), + Expanded( + flex: 2, + child: Container( + padding: const EdgeInsets.all(5.0), + decoration: BoxDecoration( + color: ColorsManager.graysColor, + borderRadius: BorderRadius.circular(10), + ), + child: InkWell( + onTap: widget.onTap, + child: Center( + child: Container( + child: SizedBox( + child: Padding( + padding: const EdgeInsets.all(5), + child: Text(widget.formattedDate), + ), + )), + ), + ), + ), + ), + ], + ), + ) + ], ), ), ], diff --git a/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart b/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart index 884a668a..531a4297 100644 --- a/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart +++ b/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart @@ -12,23 +12,17 @@ import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; //Smart Power Clamp -class SmartPowerDeviceControl extends StatefulWidget +class SmartPowerDeviceControl extends StatelessWidget with HelperResponsiveLayout { final String deviceId; const SmartPowerDeviceControl({super.key, required this.deviceId}); - @override - State createState() => - _SmartPowerDeviceControlState(); -} - -class _SmartPowerDeviceControlState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => SmartPowerBloc(deviceId: widget.deviceId) - ..add(SmartPowerFetchDeviceEvent(widget.deviceId)), + create: (context) => SmartPowerBloc(deviceId: deviceId) + ..add(SmartPowerFetchDeviceEvent(deviceId)), child: BlocBuilder( builder: (context, state) { final _blocProvider = BlocProvider.of(context); @@ -37,6 +31,7 @@ class _SmartPowerDeviceControlState extends State { return const Center(child: CircularProgressIndicator()); } else if (state is SmartPowerStatusLoaded) { return _buildStatusControls( + currentPage: _blocProvider.currentPage, context: context, blocProvider: _blocProvider, ); @@ -51,24 +46,9 @@ class _SmartPowerDeviceControlState extends State { Widget _buildStatusControls({ required BuildContext context, required SmartPowerBloc blocProvider, + required int currentPage, }) { - PageController _pageController = PageController(); - int _currentPage = 0; - - void _onArrowPressed(int direction) { - setState(() { - _currentPage = (_currentPage + direction) % 3; - if (_currentPage < 0) { - _currentPage = 2; - } - _pageController.animateToPage( - _currentPage, - duration: Duration(milliseconds: 300), - curve: Curves.easeInOut, - ); - }); - } - + PageController _pageController = PageController(initialPage: currentPage); return Container( child: DeviceControlsContainer( child: Column( @@ -84,45 +64,55 @@ class _SmartPowerDeviceControlState extends State { ), ], ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - PowerClampInfoCard( - iconPath: Assets.powerActiveIcon, - title: 'Active', - value: blocProvider - .deviceStatus.status.general.dataPoints[2].value - .toString(), - unit: '', - ), - PowerClampInfoCard( - iconPath: Assets.voltMeterIcon, - title: 'Current', - value: blocProvider - .deviceStatus.status.general.dataPoints[1].value - .toString(), - unit: ' A', - ), - PowerClampInfoCard( - iconPath: Assets.frequencyIcon, - title: 'Frequency', - value: blocProvider - .deviceStatus.status.general.dataPoints[4].value - .toString(), - unit: ' Hz', - ), - ], + Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + PowerClampInfoCard( + iconPath: Assets.powerActiveIcon, + title: 'Active', + value: blocProvider + .deviceStatus.status.general.dataPoints[2].value + .toString(), + unit: '', + ), + PowerClampInfoCard( + iconPath: Assets.voltMeterIcon, + title: 'Current', + value: blocProvider + .deviceStatus.status.general.dataPoints[1].value + .toString(), + unit: ' A', + ), + PowerClampInfoCard( + iconPath: Assets.frequencyIcon, + title: 'Frequency', + value: blocProvider + .deviceStatus.status.general.dataPoints[4].value + .toString(), + unit: ' Hz', + ), + ], + ), + ), + SizedBox( + height: 10, ), PhaseWidget( phaseData: blocProvider.phaseData, ), Container( - padding: EdgeInsets.all(10), + padding: EdgeInsets.only( + top: 10, + left: 20, + right: 20, + ), decoration: BoxDecoration( color: ColorsManager.whiteColors, borderRadius: BorderRadius.circular(20), ), - height: 250, + height: 325, child: Column( children: [ Container( @@ -130,94 +120,125 @@ class _SmartPowerDeviceControlState extends State { color: ColorsManager.graysColor, borderRadius: BorderRadius.circular(20), ), - height: 60, + height: 50, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( - icon: Icon(Icons.arrow_left), - onPressed: () => _onArrowPressed(-1), + icon: const Icon(Icons.arrow_left), + onPressed: () { + blocProvider.add(SmartPowerArrowPressedEvent(-1)); + _pageController.previousPage( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + }, ), Text( - _currentPage == 0 + currentPage == 0 ? 'Total' - : _currentPage == 0 + : currentPage == 1 ? 'Phase A' - : _currentPage == 0 + : currentPage == 2 ? 'Phase B' : 'Phase C', style: TextStyle(fontSize: 18), ), IconButton( icon: Icon(Icons.arrow_right), - onPressed: () => _onArrowPressed(1), + onPressed: () { + blocProvider.add(SmartPowerArrowPressedEvent(1)); + _pageController.nextPage( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + }, ), ], ), ), + SizedBox( + height: 10, + ), Expanded( child: PageView( controller: _pageController, onPageChanged: (int page) { - setState(() { - _currentPage = page; - }); + blocProvider.add(SmartPowerPageChangedEvent(page)); }, children: [ EnergyConsumptionPage( - chartData: [ - EnergyData('12:00 AM', 4.0), - EnergyData('01:00 AM', 3.5), - EnergyData('02:00 AM', 3.8), - EnergyData('03:00 AM', 3.2), - EnergyData('04:00 AM', 4.0), - EnergyData('05:00 AM', 3.4), - EnergyData('06:00 AM', 3.2), - EnergyData('07:00 AM', 3.5), - EnergyData('08:00 AM', 3.8), - EnergyData('09:00 AM', 3.6), - EnergyData('10:00 AM', 3.9), - EnergyData('10:00 AM', 3.9), - EnergyData('11:00 AM', 4.0), - ], + formattedDate: blocProvider.formattedDate, + onTap: () { + blocProvider.add(SelectDateEvent(context: context)); + }, + widget: blocProvider.dateSwitcher(), + chartData: blocProvider.energyDataList.isNotEmpty + ? blocProvider.energyDataList + : [ + EnergyData('12:00 AM', 4.0), + EnergyData('01:00 AM', 3.5), + EnergyData('02:00 AM', 3.8), + EnergyData('03:00 AM', 3.2), + EnergyData('04:00 AM', 4.0), + EnergyData('05:00 AM', 3.4), + EnergyData('06:00 AM', 3.2), + EnergyData('07:00 AM', 3.5), + EnergyData('08:00 AM', 3.8), + EnergyData('09:00 AM', 3.6), + EnergyData('10:00 AM', 3.9), + EnergyData('11:00 AM', 4.0), + ], totalConsumption: 10000, date: '10/08/2024', ), EnergyConsumptionPage( - chartData: [ - EnergyData('12:00 AM', 4.0), - EnergyData('01:00 AM', 3.5), - EnergyData('02:00 AM', 3.8), - EnergyData('03:00 AM', 3.2), - EnergyData('04:00 AM', 4.0), - EnergyData('05:00 AM', 3.4), - EnergyData('06:00 AM', 3.2), - EnergyData('07:00 AM', 3.5), - EnergyData('08:00 AM', 3.8), - EnergyData('09:00 AM', 3.6), - EnergyData('10:00 AM', 3.9), - EnergyData('10:00 AM', 3.9), - EnergyData('11:00 AM', 4.0), - ], + formattedDate: blocProvider.formattedDate, + onTap: () { + blocProvider.add(SelectDateEvent(context: context)); + }, + widget: blocProvider.dateSwitcher(), + chartData: blocProvider.energyDataList.isNotEmpty + ? blocProvider.energyDataList + : [ + EnergyData('12:00 AM', 4.0), + EnergyData('01:00 AM', 3.5), + EnergyData('02:00 AM', 3.8), + EnergyData('03:00 AM', 3.2), + EnergyData('04:00 AM', 4.0), + EnergyData('05:00 AM', 3.4), + EnergyData('06:00 AM', 3.2), + EnergyData('07:00 AM', 3.5), + EnergyData('08:00 AM', 3.8), + EnergyData('09:00 AM', 3.6), + EnergyData('10:00 AM', 3.9), + EnergyData('11:00 AM', 4.0), + ], totalConsumption: 10000, date: '10/08/2024', ), EnergyConsumptionPage( - chartData: [ - EnergyData('12:00 AM', 4.0), - EnergyData('01:00 AM', 6.5), - EnergyData('02:00 AM', 3.8), - EnergyData('03:00 AM', 3.2), - EnergyData('04:00 AM', 6.0), - EnergyData('05:00 AM', 3.4), - EnergyData('06:00 AM', 5.2), - EnergyData('07:00 AM', 3.5), - EnergyData('08:00 AM', 3.8), - EnergyData('09:00 AM', 5.6), - EnergyData('10:00 AM', 6.9), - EnergyData('10:00 AM', 3.9), - EnergyData('11:00 AM', 6.0), - ], + formattedDate: blocProvider.formattedDate, + onTap: () { + blocProvider.add(SelectDateEvent(context: context)); + }, + widget: blocProvider.dateSwitcher(), + chartData: blocProvider.energyDataList.isNotEmpty + ? blocProvider.energyDataList + : [ + EnergyData('12:00 AM', 4.0), + EnergyData('01:00 AM', 6.5), + EnergyData('02:00 AM', 3.8), + EnergyData('03:00 AM', 3.2), + EnergyData('04:00 AM', 6.0), + EnergyData('05:00 AM', 3.4), + EnergyData('06:00 AM', 5.2), + EnergyData('07:00 AM', 3.5), + EnergyData('08:00 AM', 3.8), + EnergyData('09:00 AM', 5.6), + EnergyData('10:00 AM', 6.9), + EnergyData('11:00 AM', 6.0), + ], totalConsumption: 10000, date: '10/08/2024', ),