formatted all files.

This commit is contained in:
Faris Armoush
2025-06-12 15:33:32 +03:00
parent 29959f567e
commit 04250ebc98
474 changed files with 5425 additions and 4338 deletions

View File

@ -33,7 +33,8 @@ class AirQualityDistributionBloc
state.copyWith(
status: AirQualityDistributionStatus.success,
chartData: result,
filteredChartData: _arrangeChartDataByType(result, state.selectedAqiType),
filteredChartData:
_arrangeChartDataByType(result, state.selectedAqiType),
),
);
} catch (e) {
@ -61,7 +62,8 @@ class AirQualityDistributionBloc
emit(
state.copyWith(
selectedAqiType: event.aqiType,
filteredChartData: _arrangeChartDataByType(state.chartData, event.aqiType),
filteredChartData:
_arrangeChartDataByType(state.chartData, event.aqiType),
),
);
}

View File

@ -7,7 +7,8 @@ import 'package:syncrow_web/pages/analytics/services/device_location/device_loca
part 'device_location_event.dart';
part 'device_location_state.dart';
class DeviceLocationBloc extends Bloc<DeviceLocationEvent, DeviceLocationState> {
class DeviceLocationBloc
extends Bloc<DeviceLocationEvent, DeviceLocationState> {
DeviceLocationBloc(
this._deviceLocationService,
) : super(const DeviceLocationState()) {

View File

@ -53,7 +53,8 @@ class RangeOfAqiBloc extends Bloc<RangeOfAqiEvent, RangeOfAqiState> {
emit(
state.copyWith(
selectedAqiType: event.aqiType,
filteredRangeOfAqi: _arrangeChartDataByType(state.rangeOfAqi, event.aqiType),
filteredRangeOfAqi:
_arrangeChartDataByType(state.rangeOfAqi, event.aqiType),
),
);
}

View File

@ -105,7 +105,8 @@ abstract final class RangeOfAqiChartsHelper {
tooltipRoundedRadius: 16,
showOnTopOfTheChartBoxArea: false,
tooltipPadding: const EdgeInsets.all(8),
getTooltipItems: (touchedSpots) => RangeOfAqiChartsHelper.getTooltipItems(
getTooltipItems: (touchedSpots) =>
RangeOfAqiChartsHelper.getTooltipItems(
touchedSpots,
chartData,
),

View File

@ -81,7 +81,8 @@ class AqiDeviceInfo extends StatelessWidget {
aqiLevel: status
.firstWhere(
(e) => e.code == 'air_quality_index',
orElse: () => Status(code: 'air_quality_index', value: ''),
orElse: () =>
Status(code: 'air_quality_index', value: ''),
)
.value
.toString(),

View File

@ -36,23 +36,25 @@ class AqiDistributionChart extends StatelessWidget {
);
}
List<BarChartGroupData> _buildBarGroups(List<AirQualityDataModel> sortedData) {
List<BarChartGroupData> _buildBarGroups(
List<AirQualityDataModel> sortedData) {
return List.generate(sortedData.length, (index) {
final data = sortedData[index];
final stackItems = <BarChartRodData>[];
double currentY = 0;
bool isFirstElement = true;
var isFirstElement = true;
// Sort data by type to ensure consistent order
final sortedPercentageData = List<AirQualityPercentageData>.from(data.data)
..sort((a, b) => a.type.compareTo(b.type));
final sortedPercentageData =
List<AirQualityPercentageData>.from(data.data)
..sort((a, b) => a.type.compareTo(b.type));
for (final percentageData in sortedPercentageData) {
stackItems.add(
BarChartRodData(
fromY: currentY,
toY: currentY + percentageData.percentage ,
color: AirQualityDataModel.metricColors[percentageData.name]!,
toY: currentY + percentageData.percentage,
color: AirQualityDataModel.metricColors[percentageData.name],
borderRadius: isFirstElement
? const BorderRadius.only(
topLeft: Radius.circular(22),
@ -84,9 +86,9 @@ class AqiDistributionChart extends StatelessWidget {
tooltipRoundedRadius: 16,
tooltipPadding: const EdgeInsets.all(8),
getTooltipItem: (group, groupIndex, rod, rodIndex) {
final data = chartData[group.x.toInt()];
final data = chartData[group.x];
final List<TextSpan> children = [];
final children = <TextSpan>[];
final textStyle = context.textTheme.bodySmall?.copyWith(
color: ColorsManager.blackColor,
@ -94,8 +96,9 @@ class AqiDistributionChart extends StatelessWidget {
);
// Sort data by type to ensure consistent order
final sortedPercentageData = List<AirQualityPercentageData>.from(data.data)
..sort((a, b) => a.type.compareTo(b.type));
final sortedPercentageData =
List<AirQualityPercentageData>.from(data.data)
..sort((a, b) => a.type.compareTo(b.type));
for (final percentageData in sortedPercentageData) {
children.add(TextSpan(

View File

@ -49,7 +49,7 @@ class AqiSubValueWidget extends StatelessWidget {
int _getActiveSegmentByRange(double value, (double min, double max) range) {
final ranges = _getRangesForValue(range);
for (int i = 0; i < ranges.length; i++) {
for (var i = 0; i < ranges.length; i++) {
if (value <= ranges[i].max) return i;
}
return ranges.length - 1;

View File

@ -29,7 +29,8 @@ class AqiTypeDropdown extends StatefulWidget {
class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
AqiType? _selectedItem = AqiType.aqi;
void _updateSelectedItem(AqiType? item) => setState(() => _selectedItem = item);
void _updateSelectedItem(AqiType? item) =>
setState(() => _selectedItem = item);
@override
Widget build(BuildContext context) {

View File

@ -63,7 +63,7 @@ class RangeOfAqiChart extends StatelessWidget {
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
stops: [0.0, 0.2, 0.4, 0.6, 0.8, 1.0],
stops: const [0.0, 0.2, 0.4, 0.6, 0.8, 1.0],
colors: RangeOfAqiChartsHelper.gradientData.map((e) {
final (color, _) = e;
return color.withValues(alpha: 0.6);
@ -99,7 +99,8 @@ class RangeOfAqiChart extends StatelessWidget {
}) {
const invisibleDot = FlDotData(show: false);
return LineChartBarData(
spots: List.generate(values.length, (i) => FlSpot(i.toDouble(), values[i])),
spots:
List.generate(values.length, (i) => FlSpot(i.toDouble(), values[i])),
isCurved: true,
color: color,
barWidth: 4,

View File

@ -32,7 +32,8 @@ class RangeOfAqiChartBox extends StatelessWidget {
const SizedBox(height: 10),
const Divider(),
const SizedBox(height: 20),
Expanded(child: RangeOfAqiChart(chartData: state.filteredRangeOfAqi)),
Expanded(
child: RangeOfAqiChart(chartData: state.filteredRangeOfAqi)),
],
),
);

View File

@ -8,7 +8,8 @@ sealed class AnalyticsDevicesEvent extends Equatable {
}
final class LoadAnalyticsDevicesEvent extends AnalyticsDevicesEvent {
const LoadAnalyticsDevicesEvent({required this.param, required this.onSuccess});
const LoadAnalyticsDevicesEvent(
{required this.param, required this.onSuccess});
final GetAnalyticsDevicesParam param;
final void Function(AnalyticsDevice device) onSuccess;

View File

@ -7,7 +7,7 @@ sealed class AnalyticsTabEvent extends Equatable {
List<Object> get props => [];
}
class UpdateAnalyticsTabEvent extends AnalyticsTabEvent {
class UpdateAnalyticsTabEvent extends AnalyticsTabEvent {
const UpdateAnalyticsTabEvent(this.analyticsTab);
final AnalyticsPageTab analyticsTab;

View File

@ -8,7 +8,8 @@ import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
final class AirQualityDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
final class AirQualityDataLoadingStrategy
implements AnalyticsDataLoadingStrategy {
@override
void onCommunitySelected(
BuildContext context,
@ -25,7 +26,8 @@ final class AirQualityDataLoadingStrategy implements AnalyticsDataLoadingStrateg
SpaceModel space,
) {
final spaceTreeBloc = context.read<SpaceTreeBloc>();
final isSpaceSelected = spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final isSpaceSelected =
spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final hasSelectedSpaces = spaceTreeBloc.state.selectedSpaces.isNotEmpty;
if (hasSelectedSpaces) clearData(context);
@ -34,7 +36,7 @@ final class AirQualityDataLoadingStrategy implements AnalyticsDataLoadingStrateg
spaceTreeBloc
..add(const SpaceTreeClearSelectionEvent())
..add(OnSpaceSelected(community, space.uuid ?? '', []));
..add(OnSpaceSelected(community, space.uuid ?? '', const []));
FetchAirQualityDataHelper.loadAirQualityData(
context,

View File

@ -8,7 +8,8 @@ abstract final class AnalyticsDataLoadingStrategyFactory {
const AnalyticsDataLoadingStrategyFactory._();
static AnalyticsDataLoadingStrategy getStrategy(AnalyticsPageTab tab) {
return switch (tab) {
AnalyticsPageTab.energyManagement => EnergyManagementDataLoadingStrategy(),
AnalyticsPageTab.energyManagement =>
EnergyManagementDataLoadingStrategy(),
AnalyticsPageTab.occupancy => OccupancyDataLoadingStrategy(),
AnalyticsPageTab.airQuality => AirQualityDataLoadingStrategy(),
};

View File

@ -7,7 +7,8 @@ import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
class EnergyManagementDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
class EnergyManagementDataLoadingStrategy
implements AnalyticsDataLoadingStrategy {
@override
void onCommunitySelected(
BuildContext context,
@ -31,7 +32,8 @@ class EnergyManagementDataLoadingStrategy implements AnalyticsDataLoadingStrateg
SpaceModel space,
) {
final spaceTreeBloc = context.read<SpaceTreeBloc>();
final isSpaceSelected = spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final isSpaceSelected =
spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final hasSelectedSpaces = spaceTreeBloc.state.selectedSpaces.isNotEmpty;
if (isSpaceSelected) {

View File

@ -24,7 +24,8 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
SpaceModel space,
) {
final spaceTreeBloc = context.read<SpaceTreeBloc>();
final isSpaceSelected = spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final isSpaceSelected =
spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final hasSelectedSpaces = spaceTreeBloc.state.selectedSpaces.isNotEmpty;
if (hasSelectedSpaces) clearData(context);
@ -33,7 +34,7 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
spaceTreeBloc
..add(const SpaceTreeClearSelectionEvent())
..add(OnSpaceSelected(community, space.uuid ?? '', []));
..add(OnSpaceSelected(community, space.uuid ?? '', const []));
FetchOccupancyDataHelper.loadOccupancyData(
context,

View File

@ -10,7 +10,8 @@ class AnalyticsCommunitiesSidebar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final selectedTab = context.watch<AnalyticsTabBloc>().state;
final strategy = AnalyticsDataLoadingStrategyFactory.getStrategy(selectedTab);
final strategy =
AnalyticsDataLoadingStrategyFactory.getStrategy(selectedTab);
return Expanded(
child: AnalyticsSpaceTreeView(

View File

@ -20,7 +20,7 @@ class AnalyticsDateFilterButton extends StatefulWidget {
final void Function(DateTime)? onDateSelected;
final DatePickerType datePickerType;
static final _color = ColorsManager.blackColor.withValues(alpha: 0.8);
static final Color _color = ColorsManager.blackColor.withValues(alpha: 0.8);
@override
State<AnalyticsDateFilterButton> createState() =>

View File

@ -21,8 +21,8 @@ class AnalyticsPageTabButton extends StatelessWidget {
onPressed: () {
AnalyticsDataLoadingStrategyFactory.getStrategy(tab).clearData(context);
context.read<AnalyticsTabBloc>().add(
UpdateAnalyticsTabEvent(tab),
);
UpdateAnalyticsTabEvent(tab),
);
},
child: Text(
tab.title,
@ -33,8 +33,9 @@ class AnalyticsPageTabButton extends StatelessWidget {
style: TextStyle(
fontWeight: isSelected ? FontWeight.w700 : FontWeight.w400,
fontSize: 16,
color:
isSelected ? ColorsManager.slidingBlueColor : ColorsManager.textGray,
color: isSelected
? ColorsManager.slidingBlueColor
: ColorsManager.textGray,
),
),
);

View File

@ -21,18 +21,18 @@ class _MonthPickerWidgetState extends State<MonthPickerWidget> {
int? _selectedMonth;
static const _monthNames = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
@override
@ -189,14 +189,19 @@ class _MonthPickerWidgetState extends State<MonthPickerWidget> {
final isFutureMonth = isCurrentYear && index > currentDate.month - 1;
return InkWell(
onTap: isFutureMonth ? null : () => setState(() => _selectedMonth = index),
onTap: isFutureMonth
? null
: () => setState(() => _selectedMonth = index),
child: DecoratedBox(
decoration: BoxDecoration(
color: const Color(0xFFEDF2F7),
borderRadius: BorderRadius.only(
topLeft: index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
bottomLeft: index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
topRight: index % 3 == 2 ? const Radius.circular(16) : Radius.zero,
topLeft:
index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
bottomLeft:
index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
topRight:
index % 3 == 2 ? const Radius.circular(16) : Radius.zero,
bottomRight:
index % 3 == 2 ? const Radius.circular(16) : Radius.zero,
),

View File

@ -53,7 +53,8 @@ class _AnalyticsSpaceTreeViewState extends State<AnalyticsSpaceTreeView> {
@override
Widget build(BuildContext context) {
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(builder: (context, state) {
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(
builder: (context, state) {
final communities = state.searchQuery.isNotEmpty
? state.filteredCommunity
: state.communityList;
@ -76,9 +77,10 @@ class _AnalyticsSpaceTreeViewState extends State<AnalyticsSpaceTreeView> {
),
),
CustomSearchBar(
onSearchChanged: (query) => context.read<SpaceTreeBloc>().add(
SearchQueryEvent(query),
),
onSearchChanged: (query) =>
context.read<SpaceTreeBloc>().add(
SearchQueryEvent(query),
),
),
const SizedBox(height: 16),
Expanded(
@ -113,7 +115,8 @@ class _AnalyticsSpaceTreeViewState extends State<AnalyticsSpaceTreeView> {
isExpanded: state.expandedCommunities.contains(
communities[index].uuid,
),
onItemSelected: () => widget.onSelectCommunity?.call(
onItemSelected: () =>
widget.onSelectCommunity?.call(
communities[index],
communities[index].spaces,
),
@ -121,8 +124,8 @@ class _AnalyticsSpaceTreeViewState extends State<AnalyticsSpaceTreeView> {
(space) {
return CustomExpansionTileSpaceTree(
title: space.name,
isExpanded:
state.expandedSpaces.contains(space.uuid),
isExpanded: state.expandedSpaces
.contains(space.uuid),
onItemSelected: () =>
widget.onSelectSpace?.call(
communities[index],
@ -153,7 +156,8 @@ class _AnalyticsSpaceTreeViewState extends State<AnalyticsSpaceTreeView> {
},
),
),
if (state.paginationIsLoading) const CircularProgressIndicator(),
if (state.paginationIsLoading)
const CircularProgressIndicator(),
],
),
);

View File

@ -19,9 +19,9 @@ class YearPickerWidget extends StatefulWidget {
class _YearPickerWidgetState extends State<YearPickerWidget> {
late int _currentYear;
static final years = List.generate(
static final List<int> years = List.generate(
DateTime.now().year - (DateTime.now().year - 5) + 1,
(index) => (2020 + index),
(index) => 2020 + index,
).where((year) => year <= DateTime.now().year).toList();
@override
@ -123,9 +123,12 @@ class _YearPickerWidgetState extends State<YearPickerWidget> {
decoration: BoxDecoration(
color: const Color(0xFFEDF2F7),
borderRadius: BorderRadius.only(
topLeft: index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
bottomLeft: index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
topRight: index % 3 == 2 ? const Radius.circular(16) : Radius.zero,
topLeft:
index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
bottomLeft:
index % 3 == 0 ? const Radius.circular(16) : Radius.zero,
topRight:
index % 3 == 2 ? const Radius.circular(16) : Radius.zero,
bottomRight:
index % 3 == 2 ? const Radius.circular(16) : Radius.zero,
),

View File

@ -8,13 +8,15 @@ import 'package:syncrow_web/services/api/api_exception.dart';
part 'energy_consumption_by_phases_event.dart';
part 'energy_consumption_by_phases_state.dart';
class EnergyConsumptionByPhasesBloc
extends Bloc<EnergyConsumptionByPhasesEvent, EnergyConsumptionByPhasesState> {
class EnergyConsumptionByPhasesBloc extends Bloc<EnergyConsumptionByPhasesEvent,
EnergyConsumptionByPhasesState> {
EnergyConsumptionByPhasesBloc(
this._energyConsumptionByPhasesService,
) : super(const EnergyConsumptionByPhasesState()) {
on<LoadEnergyConsumptionByPhasesEvent>(_onLoadEnergyConsumptionByPhasesEvent);
on<ClearEnergyConsumptionByPhasesEvent>(_onClearEnergyConsumptionByPhasesEvent);
on<LoadEnergyConsumptionByPhasesEvent>(
_onLoadEnergyConsumptionByPhasesEvent);
on<ClearEnergyConsumptionByPhasesEvent>(
_onClearEnergyConsumptionByPhasesEvent);
}
final EnergyConsumptionByPhasesService _energyConsumptionByPhasesService;
@ -25,7 +27,8 @@ class EnergyConsumptionByPhasesBloc
) async {
emit(state.copyWith(status: EnergyConsumptionByPhasesStatus.loading));
try {
final chartData = await _energyConsumptionByPhasesService.load(event.param);
final chartData =
await _energyConsumptionByPhasesService.load(event.param);
emit(
state.copyWith(
status: EnergyConsumptionByPhasesStatus.loaded,
@ -49,7 +52,7 @@ class EnergyConsumptionByPhasesBloc
}
}
void _onClearEnergyConsumptionByPhasesEvent(
Future<void> _onClearEnergyConsumptionByPhasesEvent(
ClearEnergyConsumptionByPhasesEvent event,
Emitter<EnergyConsumptionByPhasesState> emit,
) async {

View File

@ -7,7 +7,8 @@ sealed class EnergyConsumptionByPhasesEvent extends Equatable {
List<Object> get props => [];
}
class LoadEnergyConsumptionByPhasesEvent extends EnergyConsumptionByPhasesEvent {
class LoadEnergyConsumptionByPhasesEvent
extends EnergyConsumptionByPhasesEvent {
const LoadEnergyConsumptionByPhasesEvent({
required this.param,
});
@ -18,6 +19,7 @@ class LoadEnergyConsumptionByPhasesEvent extends EnergyConsumptionByPhasesEvent
List<Object> get props => [param];
}
final class ClearEnergyConsumptionByPhasesEvent extends EnergyConsumptionByPhasesEvent {
final class ClearEnergyConsumptionByPhasesEvent
extends EnergyConsumptionByPhasesEvent {
const ClearEnergyConsumptionByPhasesEvent();
}

View File

@ -8,12 +8,13 @@ import 'package:syncrow_web/services/api/api_exception.dart';
part 'energy_consumption_per_device_event.dart';
part 'energy_consumption_per_device_state.dart';
class EnergyConsumptionPerDeviceBloc
extends Bloc<EnergyConsumptionPerDeviceEvent, EnergyConsumptionPerDeviceState> {
class EnergyConsumptionPerDeviceBloc extends Bloc<
EnergyConsumptionPerDeviceEvent, EnergyConsumptionPerDeviceState> {
EnergyConsumptionPerDeviceBloc(
this._energyConsumptionPerDeviceService,
) : super(const EnergyConsumptionPerDeviceState()) {
on<LoadEnergyConsumptionPerDeviceEvent>(_onLoadEnergyConsumptionPerDeviceEvent);
on<LoadEnergyConsumptionPerDeviceEvent>(
_onLoadEnergyConsumptionPerDeviceEvent);
on<ClearEnergyConsumptionPerDeviceEvent>(
_onClearEnergyConsumptionPerDeviceEvent);
}
@ -26,7 +27,8 @@ class EnergyConsumptionPerDeviceBloc
) async {
emit(state.copyWith(status: EnergyConsumptionPerDeviceStatus.loading));
try {
final chartData = await _energyConsumptionPerDeviceService.load(event.param);
final chartData =
await _energyConsumptionPerDeviceService.load(event.param);
emit(
state.copyWith(
status: EnergyConsumptionPerDeviceStatus.loaded,
@ -50,7 +52,7 @@ class EnergyConsumptionPerDeviceBloc
}
}
void _onClearEnergyConsumptionPerDeviceEvent(
Future<void> _onClearEnergyConsumptionPerDeviceEvent(
ClearEnergyConsumptionPerDeviceEvent event,
Emitter<EnergyConsumptionPerDeviceState> emit,
) async {

View File

@ -8,7 +8,8 @@ import 'package:syncrow_web/services/api/api_exception.dart';
part 'power_clamp_info_event.dart';
part 'power_clamp_info_state.dart';
class PowerClampInfoBloc extends Bloc<PowerClampInfoEvent, PowerClampInfoState> {
class PowerClampInfoBloc
extends Bloc<PowerClampInfoEvent, PowerClampInfoState> {
PowerClampInfoBloc(
this._powerClampInfoService,
) : super(const PowerClampInfoState()) {
@ -25,7 +26,8 @@ class PowerClampInfoBloc extends Bloc<PowerClampInfoEvent, PowerClampInfoState>
) async {
emit(state.copyWith(status: PowerClampInfoStatus.loading));
try {
final powerClampModel = await _powerClampInfoService.getInfo(event.deviceId);
final powerClampModel =
await _powerClampInfoService.getInfo(event.deviceId);
emit(
state.copyWith(
status: PowerClampInfoStatus.loaded,
@ -49,7 +51,7 @@ class PowerClampInfoBloc extends Bloc<PowerClampInfoEvent, PowerClampInfoState>
}
}
void _onUpdatePowerClampStatusEvent(
Future<void> _onUpdatePowerClampStatusEvent(
UpdatePowerClampStatusEvent event,
Emitter<PowerClampInfoState> emit,
) async {

View File

@ -16,7 +16,6 @@ final class LoadPowerClampInfoEvent extends PowerClampInfoEvent {
List<Object> get props => [deviceId];
}
final class UpdatePowerClampStatusEvent extends PowerClampInfoEvent {
const UpdatePowerClampStatusEvent(this.statusList);
@ -28,4 +27,4 @@ final class UpdatePowerClampStatusEvent extends PowerClampInfoEvent {
final class ClearPowerClampInfoEvent extends PowerClampInfoEvent {
const ClearPowerClampInfoEvent();
}
}

View File

@ -24,4 +24,4 @@ class _RealtimeDeviceChangesUpdated extends RealtimeDeviceChangesEvent {
final List<Status> deviceStatusList;
const _RealtimeDeviceChangesUpdated(this.deviceStatusList);
}
}

View File

@ -49,7 +49,7 @@ class TotalEnergyConsumptionBloc
}
}
void _onClearTotalEnergyConsumptionEvent(
Future<void> _onClearTotalEnergyConsumptionEvent(
ClearTotalEnergyConsumptionEvent event,
Emitter<TotalEnergyConsumptionState> emit,
) async {

View File

@ -7,7 +7,8 @@ sealed class TotalEnergyConsumptionEvent extends Equatable {
List<Object?> get props => [];
}
final class TotalEnergyConsumptionLoadEvent extends TotalEnergyConsumptionEvent {
final class TotalEnergyConsumptionLoadEvent
extends TotalEnergyConsumptionEvent {
const TotalEnergyConsumptionLoadEvent({required this.param});
final GetTotalEnergyConsumptionParam param;
@ -16,6 +17,7 @@ final class TotalEnergyConsumptionLoadEvent extends TotalEnergyConsumptionEvent
List<Object?> get props => [param];
}
final class ClearTotalEnergyConsumptionEvent extends TotalEnergyConsumptionEvent {
final class ClearTotalEnergyConsumptionEvent
extends TotalEnergyConsumptionEvent {
const ClearTotalEnergyConsumptionEvent();
}

View File

@ -69,7 +69,8 @@ abstract final class EnergyManagementChartsHelper {
return labels.where((element) => element.isNotEmpty).join(', ');
}
static List<LineTooltipItem?> getTooltipItems(List<LineBarSpot> touchedSpots) {
static List<LineTooltipItem?> getTooltipItems(
List<LineBarSpot> touchedSpots) {
return touchedSpots.map((spot) {
return LineTooltipItem(
getToolTipLabel(spot.x, spot.y),
@ -85,7 +86,8 @@ abstract final class EnergyManagementChartsHelper {
static LineTouchTooltipData lineTouchTooltipData() {
return LineTouchTooltipData(
getTooltipColor: (touchTooltipItem) => ColorsManager.whiteColors,
tooltipBorder: const BorderSide(color: ColorsManager.semiTransparentBlack),
tooltipBorder:
const BorderSide(color: ColorsManager.semiTransparentBlack),
tooltipRoundedRadius: 16,
showOnTopOfTheChartBoxArea: false,
tooltipPadding: const EdgeInsets.all(8),

View File

@ -122,7 +122,8 @@ abstract final class FetchEnergyManagementDataHelper {
final selectedDevice = getSelectedDevice(context);
context.read<RealtimeDeviceChangesBloc>().add(
RealtimeDeviceChangesStarted(deviceUuid ?? selectedDevice?.uuid ?? ''),
RealtimeDeviceChangesStarted(
deviceUuid ?? selectedDevice?.uuid ?? ''),
);
}

View File

@ -51,7 +51,8 @@ class AnalyticsEnergyManagementView extends StatelessWidget {
spacing: 20,
children: [
Expanded(child: TotalEnergyConsumptionChartBox()),
Expanded(child: EnergyConsumptionPerDeviceChartBox()),
Expanded(
child: EnergyConsumptionPerDeviceChartBox()),
],
),
),

View File

@ -52,7 +52,8 @@ class AnalyticsDeviceDropdown extends StatelessWidget {
);
}
Widget _buildDevicesDropdown(BuildContext context, AnalyticsDevicesState state) {
Widget _buildDevicesDropdown(
BuildContext context, AnalyticsDevicesState state) {
final spaceUuid = state.selectedDevice?.spaceUuid;
return DropdownButton<AnalyticsDevice?>(
value: state.selectedDevice,

View File

@ -18,7 +18,6 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
Widget build(BuildContext context) {
return BarChart(
BarChartData(
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250,
@ -100,11 +99,11 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
}) {
final data = energyData;
final date = DateFormat('dd/MM/yyyy').format(data[group.x.toInt()].date);
final phaseA = data[group.x.toInt()].energyConsumedA;
final phaseB = data[group.x.toInt()].energyConsumedB;
final phaseC = data[group.x.toInt()].energyConsumedC;
final total = data[group.x.toInt()].energyConsumedKw;
final date = DateFormat('dd/MM/yyyy').format(data[group.x].date);
final phaseA = data[group.x].energyConsumedA;
final phaseB = data[group.x].energyConsumedB;
final phaseC = data[group.x].energyConsumedC;
final total = data[group.x].energyConsumedKw;
return BarTooltipItem(
'$date\n',

View File

@ -22,7 +22,8 @@ class EnergyConsumptionByPhasesChartBox extends StatelessWidget {
children: [
AnalyticsErrorWidget(state.errorMessage),
EnergyConsumptionByPhasesTitle(
isLoading: state.status == EnergyConsumptionByPhasesStatus.loading,
isLoading:
state.status == EnergyConsumptionByPhasesStatus.loading,
),
const SizedBox(height: 20),
Expanded(

View File

@ -17,7 +17,6 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
context,
leftTitlesInterval: 250,
),
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250,

View File

@ -46,7 +46,8 @@ class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
flex: 2,
child: EnergyConsumptionPerDeviceDevicesList(
chartData: state.chartData,
devices: context.watch<AnalyticsDevicesBloc>().state.devices,
devices:
context.watch<AnalyticsDevicesBloc>().state.devices,
),
),
],
@ -55,7 +56,8 @@ class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
const Divider(height: 0),
const SizedBox(height: 20),
Expanded(
child: EnergyConsumptionPerDeviceChart(chartData: state.chartData),
child:
EnergyConsumptionPerDeviceChart(chartData: state.chartData),
),
],
),

View File

@ -43,11 +43,14 @@ class PowerClampEnergyDataWidget extends StatelessWidget {
title: 'Smart Power Clamp',
showSpaceUuidInDevicesDropdown: true,
onChanged: (device) {
FetchEnergyManagementDataHelper.loadEnergyConsumptionByPhases(
FetchEnergyManagementDataHelper
.loadEnergyConsumptionByPhases(
context,
powerClampUuid: device.uuid,
selectedDate:
context.read<AnalyticsDatePickerBloc>().state.monthlyDate,
selectedDate: context
.read<AnalyticsDatePickerBloc>()
.state
.monthlyDate,
);
},
),
@ -91,7 +94,8 @@ class PowerClampEnergyDataWidget extends StatelessWidget {
),
),
const SizedBox(height: 14),
const Expanded(flex: 3, child: EnergyConsumptionByPhasesChartBox()),
const Expanded(
flex: 3, child: EnergyConsumptionByPhasesChartBox()),
],
),
);

View File

@ -140,9 +140,9 @@ class PowerClampPhasesDataWidget extends StatelessWidget {
String _formatCurrentValue(String? value) {
if (value == null) return '--';
String str = value;
var str = value;
if (str.isEmpty || str == '--') return '--';
str = str.replaceAll(RegExp(r'[^0-9]'), '');
str = str.replaceAll(RegExp('[^0-9]'), '');
if (str.isEmpty) return '--';
if (str.length == 1) return '${str[0]}.0';
return '${str[0]}.${str.substring(1)}';
@ -150,9 +150,9 @@ class PowerClampPhasesDataWidget extends StatelessWidget {
String _formatPowerFactor(String? value) {
if (value == null) return '--';
String str = value;
var str = value;
if (str.isEmpty || str == '--') return '--';
str = str.replaceAll(RegExp(r'[^0-9]'), '');
str = str.replaceAll(RegExp('[^0-9]'), '');
if (str.isEmpty) return '--';
final intValue = int.tryParse(str);
if (intValue == null) return '--';
@ -162,9 +162,9 @@ class PowerClampPhasesDataWidget extends StatelessWidget {
String _formatVoltage(String? value) {
if (value == null) return '--';
String str = value;
var str = value;
if (str.isEmpty || str == '--') return '--';
str = str.replaceAll(RegExp(r'[^0-9]'), '');
str = str.replaceAll(RegExp('[^0-9]'), '');
if (str.isEmpty) return '--';
if (str.length == 1) return '0.${str[0]}';
return '${str.substring(0, str.length - 1)}.${str.substring(str.length - 1)}';

View File

@ -29,7 +29,6 @@ class TotalEnergyConsumptionChart extends StatelessWidget {
),
duration: Duration.zero,
curve: Curves.easeIn,
),
);
}

View File

@ -25,7 +25,8 @@ class TotalEnergyConsumptionChartBox extends StatelessWidget {
Row(
children: [
ChartsLoadingWidget(
isLoading: state.status == TotalEnergyConsumptionStatus.loading,
isLoading:
state.status == TotalEnergyConsumptionStatus.loading,
),
const Expanded(
flex: 3,

View File

@ -23,9 +23,11 @@ class OccupancyBloc extends Bloc<OccupancyEvent, OccupancyState> {
emit(state.copyWith(status: OccupancyStatus.loading));
try {
final chartData = await _occupacyService.load(event.param);
emit(state.copyWith(chartData: chartData, status: OccupancyStatus.loaded));
emit(
state.copyWith(chartData: chartData, status: OccupancyStatus.loaded));
} on APIException catch (e) {
emit(state.copyWith(status: OccupancyStatus.failure, errorMessage: e.message));
emit(state.copyWith(
status: OccupancyStatus.failure, errorMessage: e.message));
} catch (e) {
emit(state.copyWith(status: OccupancyStatus.failure, errorMessage: '$e'));
}

View File

@ -25,15 +25,18 @@ abstract final class FetchOccupancyDataHelper {
final datePickerState = context.read<AnalyticsDatePickerBloc>().state;
loadAnalyticsDevices(context, communityUuid: communityId, spaceUuid: spaceId);
final selectedDevice = context.read<AnalyticsDevicesBloc>().state.selectedDevice;
loadAnalyticsDevices(context,
communityUuid: communityId, spaceUuid: spaceId);
final selectedDevice =
context.read<AnalyticsDevicesBloc>().state.selectedDevice;
loadOccupancyChartData(
context,
spaceUuid: spaceId,
date: datePickerState.monthlyDate,
);
loadHeatMapData(context, spaceUuid: spaceId, year: datePickerState.yearlyDate);
loadHeatMapData(context,
spaceUuid: spaceId, year: datePickerState.yearlyDate);
if (selectedDevice case final AnalyticsDevice device) {
context.read<RealtimeDeviceChangesBloc>()
@ -64,7 +67,8 @@ abstract final class FetchOccupancyDataHelper {
context.read<OccupancyBloc>().add(
LoadOccupancyEvent(
GetOccupancyParam(
monthDate: '${date.year}-${date.month.toString().padLeft(2, '0')}',
monthDate:
'${date.year}-${date.month.toString().padLeft(2, '0')}',
spaceUuid: spaceUuid,
),
),

View File

@ -20,9 +20,12 @@ class AnalyticsOccupancyView extends StatelessWidget {
child: Column(
spacing: 32,
children: [
SizedBox(height: height * 0.46, child: const OccupancyEndSideBar()),
SizedBox(height: height * 0.5, child: const OccupancyChartBox()),
SizedBox(height: height * 0.5, child: const OccupancyHeatMapBox()),
SizedBox(
height: height * 0.46, child: const OccupancyEndSideBar()),
SizedBox(
height: height * 0.5, child: const OccupancyChartBox()),
SizedBox(
height: height * 0.5, child: const OccupancyHeatMapBox()),
],
),
);

View File

@ -41,7 +41,8 @@ class OccupancyChart extends StatelessWidget {
barRods: [
BarChartRodData(
toY: 100.0,
fromY: occupancyValue == 0 ? occupancyValue : occupancyValue + 2.5,
fromY:
occupancyValue == 0 ? occupancyValue : occupancyValue + 2.5,
color: ColorsManager.graysColor,
width: _chartWidth,
borderRadius: BorderRadius.circular(10),
@ -88,8 +89,8 @@ class OccupancyChart extends StatelessWidget {
}) {
final data = chartData;
final occupancyValue = double.parse(data[group.x.toInt()].occupancy);
final percentage = '${(occupancyValue).toStringAsFixed(0)}%';
final occupancyValue = double.parse(data[group.x].occupancy);
final percentage = '${occupancyValue.toStringAsFixed(0)}%';
return BarTooltipItem(
percentage,
@ -116,7 +117,7 @@ class OccupancyChart extends StatelessWidget {
alignment: AlignmentDirectional.centerStart,
fit: BoxFit.scaleDown,
child: Text(
'${(value).toStringAsFixed(0)}%',
'${value.toStringAsFixed(0)}%',
style: context.textTheme.bodySmall?.copyWith(
fontSize: 12,
color: ColorsManager.greyColor,

View File

@ -44,13 +44,15 @@ class OccupancyChartBox extends StatelessWidget {
child: AnalyticsDateFilterButton(
onDateSelected: (DateTime value) {
context.read<AnalyticsDatePickerBloc>().add(
UpdateAnalyticsDatePickerEvent(montlyDate: value),
UpdateAnalyticsDatePickerEvent(
montlyDate: value),
);
if (spaceTreeState.selectedSpaces.isNotEmpty) {
FetchOccupancyDataHelper.loadOccupancyChartData(
context,
spaceUuid:
spaceTreeState.selectedSpaces.firstOrNull ?? '',
spaceTreeState.selectedSpaces.firstOrNull ??
'',
date: value,
);
}

View File

@ -44,13 +44,15 @@ class OccupancyHeatMapBox extends StatelessWidget {
child: AnalyticsDateFilterButton(
onDateSelected: (DateTime value) {
context.read<AnalyticsDatePickerBloc>().add(
UpdateAnalyticsDatePickerEvent(yearlyDate: value),
UpdateAnalyticsDatePickerEvent(
yearlyDate: value),
);
if (spaceTreeState.selectedSpaces.isNotEmpty) {
FetchOccupancyDataHelper.loadHeatMapData(
context,
spaceUuid:
spaceTreeState.selectedSpaces.firstOrNull ?? '',
spaceTreeState.selectedSpaces.firstOrNull ??
'',
year: value,
);
}

View File

@ -28,11 +28,11 @@ class OccupancyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final Paint fillPaint = Paint();
final Paint borderPaint = Paint()
final fillPaint = Paint();
final borderPaint = Paint()
..color = ColorsManager.grayBorder.withValues(alpha: 0.4)
..style = PaintingStyle.stroke;
final Paint hoveredBorderPaint = Paint()
final hoveredBorderPaint = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 1.5;
@ -66,24 +66,24 @@ class OccupancyPainter extends CustomPainter {
);
canvas.drawLine(Offset(x, y), Offset(x, y + cellSize), borderPaint);
canvas.drawLine(Offset(x + cellSize, y), Offset(x + cellSize, y + cellSize),
borderPaint);
canvas.drawLine(Offset(x + cellSize, y),
Offset(x + cellSize, y + cellSize), borderPaint);
}
}
}
void _drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint) {
const double dashWidth = 2.0;
const double dashSpace = 4.0;
final double totalLength = (end - start).distance;
final Offset direction = (end - start) / (end - start).distance;
const dashWidth = 2.0;
const dashSpace = 4.0;
final totalLength = (end - start).distance;
final direction = (end - start) / (end - start).distance;
double currentLength = 0.0;
var currentLength = 0.0;
while (currentLength < totalLength) {
final Offset dashStart = start + direction * currentLength;
final double nextLength = currentLength + dashWidth;
final Offset dashEnd =
start + direction * (nextLength < totalLength ? nextLength : totalLength);
final dashStart = start + direction * currentLength;
final nextLength = currentLength + dashWidth;
final dashEnd = start +
direction * (nextLength < totalLength ? nextLength : totalLength);
canvas.drawLine(dashStart, dashEnd, paint);
currentLength = nextLength + dashSpace;
}