Compare commits

...

19 Commits

Author SHA1 Message Date
4fd46d820d Dev (#335)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket


## Description

hot fix thermostat as requested by Talal

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-07-02 08:38:23 +03:00
8534cb3045 Created decorators for energy management charts to divide values by 100, and modified the intervals. 2025-07-01 18:56:17 +03:00
fcaed3e4e3 Divide energy consumption chart values by hundred (#333)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Divide energy consumption chart values by hundred

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-07-01 16:33:43 +03:00
445d4facab Refactor TotalEnergyConsumptionBloc to use DividedTotalEnergyConsumptionDecorator for adjusted energy values and update chart data handling in TotalEnergyConsumptionChart. 2025-07-01 16:28:52 +03:00
b159c4f052 Dev (#326)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->


## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 15:57:06 +03:00
6afebdfef8 Analytics empty state (#320)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Analytics Empty State.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 15:31:12 +03:00
a24630b3eb Dev (#324)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 15:26:10 +03:00
4768b4a89e fix touch gangs realtime. (#322)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-0000](https://syncrow.atlassian.net/browse/SP-0000)

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 13:58:33 +03:00
11cf992a1a Dev (#319)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 11:57:35 +03:00
774a1533f5 Dev (#314)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Release


## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-29 16:47:14 +03:00
403b45c826 show aqi tab on analytics page. 2025-06-29 10:58:16 +03:00
ed2b91d380 MVP release (#306)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

MVP Release

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-29 10:56:48 +03:00
5bb3688a51 Dev (#276)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->
## Description

analytics hotfixes.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-19 11:26:43 +03:00
d6fcf051c6 Dev (#273)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
remove duplicate Feature from space Management  

## Description

no need for feature of duplicate now

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-19 09:25:51 +03:00
5544430efa Dev (#270)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1661](https://syncrow.atlassian.net/browse/SP-1661)

## Description

Includes a few critical hot fixes.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1661]:
https://syncrow.atlassian.net/browse/SP-1661?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-18 16:02:53 +03:00
ae89a24a4b Dev (#265)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-18 11:01:09 +03:00
ecc01a1eb3 hides air quality tab. (#262)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Hides AQI tab in analytics dashboard for release purposes.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-17 13:30:36 +03:00
921da20d3f hides air quality tab. 2025-06-17 13:28:22 +03:00
2fed2d9de3 Sprint 20 STG Release (#261)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Sprint 20 staging release.
## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-17 13:26:01 +03:00
10 changed files with 155 additions and 20 deletions

View File

@ -22,7 +22,9 @@ import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_en
import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart';
import 'package:syncrow_web/pages/analytics/services/device_location/device_location_details_service_decorator.dart';
import 'package:syncrow_web/pages/analytics/services/device_location/remote_device_location_service.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_value_divider_decorator.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/remote_energy_consumption_by_phases_service.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_value_divider_decorator.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/remote_energy_consumption_per_device_service.dart';
import 'package:syncrow_web/pages/analytics/services/occupacy/remote_occupancy_service.dart';
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/remote_occupancy_heat_map_service.dart';
@ -62,17 +64,23 @@ class _AnalyticsPageState extends State<AnalyticsPage> {
),
BlocProvider(
create: (context) => TotalEnergyConsumptionBloc(
RemoteTotalEnergyConsumptionService(_httpService),
DividedTotalEnergyConsumptionDecorator(
RemoteTotalEnergyConsumptionService(_httpService),
),
),
),
BlocProvider(
create: (context) => EnergyConsumptionByPhasesBloc(
RemoteEnergyConsumptionByPhasesService(_httpService),
EnergyConsumptionByPhasesValueDividerDecorator(
RemoteEnergyConsumptionByPhasesService(_httpService),
),
),
),
BlocProvider(
create: (context) => EnergyConsumptionPerDeviceBloc(
RemoteEnergyConsumptionPerDeviceService(_httpService),
EnergyConsumptionPerDeviceValueDividerDecorator(
RemoteEnergyConsumptionPerDeviceService(_httpService),
),
),
),
BlocProvider(
@ -145,6 +153,7 @@ class _AnalyticsPageFormState extends State<AnalyticsPageForm> {
context.read<SpaceTreeBloc>().add(InitialEvent());
super.initState();
}
@override
Widget build(BuildContext context) {
return WebScaffold(

View File

@ -13,15 +13,15 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
});
final List<PhasesEnergyConsumption> energyData;
static const _kLeftTitlesInterval = 4.0;
@override
Widget build(BuildContext context) {
return BarChart(
BarChartData(
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250,
horizontalInterval: _kLeftTitlesInterval,
),
borderData: EnergyManagementChartsHelper.borderData(),
barTouchData: _barTouchData(context),
@ -100,11 +100,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',
@ -149,7 +149,7 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
FlTitlesData _titlesData(BuildContext context) {
final titlesData = EnergyManagementChartsHelper.titlesData(
context,
leftTitlesInterval: 250,
leftTitlesInterval: _kLeftTitlesInterval,
);
final leftTitles = titlesData.leftTitles.copyWith(

View File

@ -7,6 +7,7 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
const EnergyConsumptionPerDeviceChart({super.key, required this.chartData});
final List<DeviceEnergyDataModel> chartData;
static const _kLeftTitlesInterval = 2.5;
@override
Widget build(BuildContext context) {
@ -15,12 +16,11 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
clipData: const FlClipData.vertical(),
titlesData: EnergyManagementChartsHelper.titlesData(
context,
leftTitlesInterval: 250,
leftTitlesInterval: _kLeftTitlesInterval,
),
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250,
horizontalInterval: _kLeftTitlesInterval,
),
borderData: EnergyManagementChartsHelper.borderData(),
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),

View File

@ -9,22 +9,24 @@ class TotalEnergyConsumptionChart extends StatelessWidget {
final List<EnergyDataModel> chartData;
static const _leftTitlesInterval = 5.0;
@override
Widget build(BuildContext context) {
return Expanded(
child: LineChart(
LineChartData(
maxY: chartData.isEmpty
? null
: chartData.map((e) => e.value).reduce((a, b) => a > b ? a : b) + 250,
maxY: chartData.isNotEmpty
? chartData.map((e) => e.value).reduce((a, b) => a > b ? a : b) +
_leftTitlesInterval
: null,
clipData: const FlClipData.vertical(),
titlesData: EnergyManagementChartsHelper.titlesData(
context,
leftTitlesInterval: 500,
leftTitlesInterval: _leftTitlesInterval,
),
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 500,
horizontalInterval: _leftTitlesInterval,
),
borderData: EnergyManagementChartsHelper.borderData(),
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),

View File

@ -0,0 +1,34 @@
import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_service.dart';
import 'package:syncrow_web/utils/helpers/safe_division_helper.dart';
class EnergyConsumptionByPhasesValueDividerDecorator
implements EnergyConsumptionByPhasesService {
const EnergyConsumptionByPhasesValueDividerDecorator(
this._decoratee, {
this.divider = 100,
});
final EnergyConsumptionByPhasesService _decoratee;
final double divider;
@override
Future<List<PhasesEnergyConsumption>> load(
GetEnergyConsumptionByPhasesParam param) async {
final result = await _decoratee.load(param);
return result.map((e) {
return PhasesEnergyConsumption(
date: e.date,
energyConsumedA: SafeDivisionHelper.divide(e.energyConsumedA, divider),
energyConsumedB: SafeDivisionHelper.divide(e.energyConsumedB, divider),
energyConsumedC: SafeDivisionHelper.divide(e.energyConsumedC, divider),
energyConsumedKw: SafeDivisionHelper.divide(e.energyConsumedKw, divider),
uuid: e.uuid,
createdAt: e.createdAt,
updatedAt: e.updatedAt,
deviceUuid: e.deviceUuid,
);
}).toList();
}
}

View File

@ -0,0 +1,36 @@
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart';
import 'package:syncrow_web/utils/helpers/safe_division_helper.dart';
class EnergyConsumptionPerDeviceValueDividerDecorator
implements EnergyConsumptionPerDeviceService {
const EnergyConsumptionPerDeviceValueDividerDecorator(
this._decoratee, {
this.divider = 100,
});
final EnergyConsumptionPerDeviceService _decoratee;
final double divider;
@override
Future<List<DeviceEnergyDataModel>> load(
GetEnergyConsumptionPerDeviceParam param,
) async {
final result = await _decoratee.load(param);
return result.map((device) {
return DeviceEnergyDataModel(
deviceId: device.deviceId,
deviceName: device.deviceName,
color: device.color,
energy: device.energy.map((e) {
return EnergyDataModel(
date: e.date,
value: SafeDivisionHelper.divide(e.value, divider),
);
}).toList(),
);
}).toList();
}
}

View File

@ -0,0 +1,26 @@
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart';
import 'package:syncrow_web/utils/helpers/safe_division_helper.dart';
class DividedTotalEnergyConsumptionDecorator
implements TotalEnergyConsumptionService {
const DividedTotalEnergyConsumptionDecorator(
this._decoratee, {
this.divider = 100,
});
final TotalEnergyConsumptionService _decoratee;
final double divider;
@override
Future<List<EnergyDataModel>> load(GetTotalEnergyConsumptionParam param) async {
final result = await _decoratee.load(param);
return result.map((e) {
return EnergyDataModel(
date: e.date,
value: SafeDivisionHelper.divide(e.value, divider),
);
}).toList();
}
}

View File

@ -59,3 +59,23 @@ abstract final class _TotalEnergyConsumptionResponseMapper {
}).toList();
}
}
class DividedTotalEnergyConsumptionDecorator
implements TotalEnergyConsumptionService {
const DividedTotalEnergyConsumptionDecorator(this._decoratee);
final TotalEnergyConsumptionService _decoratee;
@override
Future<List<EnergyDataModel>> load(
GetTotalEnergyConsumptionParam param,
) async {
final result = await _decoratee.load(param);
final dividedResult = result.map((e) {
return EnergyDataModel(
date: e.date,
value: e.value / 100,
);
});
return dividedResult.toList();
}
}

View File

@ -105,7 +105,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
color: const Color(0xFF0026A2),
),
HomeItemModel(
title: 'Devices Management',
title: 'Device Management',
icon: Assets.devicesIcon,
active: true,
onPress: (context) {

View File

@ -0,0 +1,8 @@
abstract final class SafeDivisionHelper {
const SafeDivisionHelper._();
static double divide(num value, num divider) {
if (divider == 0) return 0;
return value / divider;
}
}