Compare commits

...
Author SHA1 Message Date
Rafeek-Khoudare b06e4bd2ba hot fix thermostat string 2025-07-02 08:27:09 +03:00
Rafeek-khoudare 0a022d8a8d [FE] On devices management page when we search for a device then select a space that has devices and try to search again it does not work (#327)
<!--
  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-1805](https://syncrow.atlassian.net/browse/SP-1805)

## Description

should reset filters when selecting any community 

## 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 


[SP-1805]:
https://syncrow.atlassian.net/browse/SP-1805?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-07-01 11:34:12 +03:00
mohammadnemer1 8f0eb88567 remove countdownRemaining from ScheduleLoaded state (#330)
<!--
  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
remove countdownRemaining from ScheduleLoaded state
<!--- 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)
- [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-01 11:18:17 +03:00
mohammadnemer1 19739c6e4d Add EnergyConsumptionPage to SmartPowerDeviceControl for enhanced ene… (#329)
…rgy data visualization

<!--
  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 -->
The phases and the chart should be synced.

## 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-01 11:18:00 +03:00
mohammad 9f86b8d638 remove countdownRemaining from ScheduleLoaded state 2025-07-01 11:14:02 +03:00
Faris Armoush 95907661d2 align bar charts to start. (#328)
<!--
  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

Align AQI Distribution, and Occupancy charts bars to start.

## 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 10:44:20 +03:00
Faris Armoush 9c9b7d99dc enhance sizing of energy management view. 2025-07-01 09:55:38 +03:00
mohammad 037895844a Add EnergyConsumptionPage to SmartPowerDeviceControl for enhanced energy data visualization 2025-07-01 09:44:59 +03:00
Faris Armoush c07bae5cbc align bar charts to start. 2025-07-01 09:32:00 +03:00
Rafeek-Khoudare e6fe9f35b0 problem fixed should reset filters when select space or community 2025-07-01 08:41:38 +03:00
Faris Armoush 8cb6c13cd5 Changed timer codes in curtain module to match what the API expects. 2025-06-30 15:53:23 +03:00
Faris Armoush 949c27938a Analytics empty state (#325)
<!--
  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 15:32:12 +03:00
Faris Armoush 4c582b865d Sp 1611 in user management if email address already exists the error message does not go away until the user clicks next the error message should clear if a good email is entered (#321)
<!--
  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-1611
](https://syncrow.atlassian.net/jira/software/projects/SP/boards/5?assignee=712020%3A71e88a7f-7752-44b3-8177-4ab51a950811&selectedIssue=SP-1611)

## Description

use textfield validator on chaging value not only with next button 

## 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-30 15:31:04 +03:00
mohammadnemer1 d7467adeda Add countdown functionality and device type support across device man… (#323)
…agement views

<!--
  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)
- [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:22:28 +03:00
Rafeek-Khoudare 15ee79688d reComite 2025-06-30 13:36:52 +03:00
Rafeek-Khoudare e5e88385e9 change autoValidae mode to userInteraction and give some time to check validate when typing on keyboard with debouncer 2025-06-30 13:31:38 +03:00
Rafeek-Khoudare 62d5bbce7e add isValid to basic step (1) and insure that user can go to another step using next button without filling the form 2025-06-30 13:22:04 +03:00
Faris Armoush 05d784ec11 Merge branch 'dev' of https://github.com/SyncrowIOT/web into analytics-empty-state 2025-06-30 12:53:42 +03:00
Faris Armoush 9ebf474a60 analytics-empty-state. 2025-06-30 12:52:22 +03:00
Faris Armoush db05331e9a update AnalyticsChartEmptyStateWidget to use new icons. 2025-06-30 11:18:08 +03:00
Faris Armoush 44c88fb1c4 added empty charts icons. 2025-06-30 10:54:33 +03:00
Faris Armoush 2f5ad03431 created empty charts widget. 2025-06-29 10:57:18 +03:00
24 changed files with 450 additions and 122 deletions
+8
View File
@@ -0,0 +1,8 @@
<svg width="175" height="134" viewBox="0 0 175 134" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="0.5" y1="2.18557e-08" x2="0.499994" y2="132.759" stroke="#B9C0C5"/>
<line x1="175" y1="133.259" x2="-4.37114e-08" y2="133.259" stroke="#B9C0C5"/>
<rect x="16.0922" y="66.3794" width="28.1609" height="66.3793" fill="#C7CDD1"/>
<rect x="54.3105" y="24.1379" width="28.1609" height="108.621" fill="#ABB4BA"/>
<rect x="92.5288" y="78.4484" width="28.1609" height="54.3103" fill="#C7CDD1"/>
<rect x="130.747" y="48.2759" width="28.1609" height="84.4828" fill="#ABB4BA"/>
</svg>

After

Width:  |  Height:  |  Size: 583 B

@@ -0,0 +1,5 @@
<svg width="175" height="134" viewBox="0 0 175 134" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="0.5" y1="3.05394e-05" x2="0.499994" y2="132.759" stroke="#B9C0C5"/>
<line x1="175" y1="133.259" x2="-4.37114e-08" y2="133.259" stroke="#B9C0C5"/>
<path d="M1.5 132.5C13 132.5 6.58852 66.5 29.5 66.5C46.5 66.5 46.1214 24.9349 68.5 24.5C94.2816 23.999 80.7136 78.5065 106.5 78.5C125.715 78.4952 131.5 48.5 145.5 48.5C159.5 48.5 156.5 96 171.5 96" stroke="#ABB4BA" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 520 B

@@ -0,0 +1,7 @@
<svg width="175" height="134" viewBox="0 0 175 134" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="0.5" y1="2.18557e-08" x2="0.499994" y2="132.759" stroke="#B9C0C5"/>
<line x1="175" y1="133.259" x2="-4.37114e-08" y2="133.259" stroke="#B9C0C5"/>
<path d="M1.5 132.5C13 132.5 6.58852 66.5 29.5 66.5C46.5 66.5 46.1214 24.9348 68.5 24.5C94.2816 23.999 80.7136 78.5064 106.5 78.5C125.715 78.4951 131.5 48.5 145.5 48.5C159.5 48.5 156.5 95.9999 171.5 95.9999" stroke="#ABB4BA" stroke-width="1.5" stroke-linecap="round" stroke-dasharray="4 4"/>
<path d="M1.5 132.5C13 132.5 6.58852 78.4999 29.5 78.4999C46.5 78.4999 45.6214 44.9349 68 44.5C93.7816 43.999 80.7136 27.0065 106.5 27C125.715 26.9952 131.5 63.5 145.5 63.5C159.5 63.5 156.5 113.5 171.5 113.5" stroke="#C7CDD1" stroke-width="1.5" stroke-linecap="round" stroke-dasharray="4 4"/>
<path d="M1.5 132.5C13 132.5 6.58852 85.9999 29.5 85.9999C46.5 85.9999 45.6214 11.9348 68 11.4999C93.7816 10.9989 80.7136 43.5064 106.5 43.4999C125.715 43.4951 131.5 35.4999 145.5 35.4999C159.5 35.4999 156.5 105.5 171.5 105.5" stroke="#D5D5D5" stroke-width="1.5" stroke-linecap="round" stroke-dasharray="4 4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+99
View File
@@ -0,0 +1,99 @@
<svg width="181" height="121" viewBox="0 0 181 121" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="15.5" y1="-2.52181e-08" x2="15.5" y2="120" stroke="#B9B9B9"/>
<line x1="45.5" y1="-2.52181e-08" x2="45.5" y2="120" stroke="#B9B9B9"/>
<line x1="75.5" y1="-2.52181e-08" x2="75.5" y2="120" stroke="#B9B9B9"/>
<line x1="105.5" y1="-2.52181e-08" x2="105.5" y2="120" stroke="#B9B9B9"/>
<line x1="135.5" y1="-2.52181e-08" x2="135.5" y2="120" stroke="#B9B9B9"/>
<line x1="165.5" y1="-2.52181e-08" x2="165.5" y2="120" stroke="#B9B9B9"/>
<line x1="30.5" y1="-2.52181e-08" x2="30.5" y2="120" stroke="#B9B9B9"/>
<line x1="60.5" y1="-2.52181e-08" x2="60.5" y2="120" stroke="#B9B9B9"/>
<line x1="90.5" y1="-2.52181e-08" x2="90.5" y2="120" stroke="#B9B9B9"/>
<line x1="120.5" y1="-2.52181e-08" x2="120.5" y2="120" stroke="#B9B9B9"/>
<line x1="150.5" y1="-2.52181e-08" x2="150.5" y2="120" stroke="#B9B9B9"/>
<line x1="180.5" y1="-2.52181e-08" x2="180.5" y2="120" stroke="#B9B9B9"/>
<line x1="181" y1="120.5" x2="-4.52101e-08" y2="120.5" stroke="#B9B9B9"/>
<line x1="181" y1="60.5" x2="-4.52101e-08" y2="60.5" stroke="#B9B9B9"/>
<line x1="181" y1="90.5" x2="-4.52101e-08" y2="90.5" stroke="#B9B9B9"/>
<line x1="181" y1="30.5" x2="-4.52101e-08" y2="30.5" stroke="#B9B9B9"/>
<line x1="181" y1="105.5" x2="-4.52101e-08" y2="105.5" stroke="#B9B9B9"/>
<line x1="181" y1="45.5" x2="-4.52101e-08" y2="45.5" stroke="#B9B9B9"/>
<line x1="181" y1="75.5" x2="-4.52101e-08" y2="75.5" stroke="#B9B9B9"/>
<line x1="181" y1="15.5" x2="-4.52101e-08" y2="15.5" stroke="#B9B9B9"/>
<rect x="16" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="46" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="61" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="76" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="91" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="106" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="121" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="136" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="151" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="166" y="16" width="14" height="14" fill="#F2F2F2"/>
<rect x="16" y="31" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="46" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="61" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="76" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="91" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="106" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="121" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="136" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="151" y="31" width="14" height="14" fill="#D5D5D5"/>
<rect x="166" y="31" width="14" height="14" fill="#F2F2F2"/>
<rect x="16" y="46" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="46" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="61" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="76" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="91" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="106" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="121" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="136" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="151" y="46" width="14" height="14" fill="#D5D5D5"/>
<rect x="166" y="46" width="14" height="14" fill="#F2F2F2"/>
<rect x="16" y="61" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="61" width="14" height="14" fill="#D5D5D5"/>
<rect x="46" y="61" width="14" height="14" fill="#D5D5D5"/>
<rect x="61" y="61" width="14" height="14" fill="#B1B1B1"/>
<rect x="76" y="61" width="14" height="14" fill="#B1B1B1"/>
<rect x="91" y="61" width="14" height="14" fill="#B1B1B1"/>
<rect x="106" y="61" width="14" height="14" fill="#B1B1B1"/>
<rect x="121" y="61" width="14" height="14" fill="#B1B1B1"/>
<rect x="136" y="61" width="14" height="14" fill="#D5D5D5"/>
<rect x="151" y="61" width="14" height="14" fill="#D5D5D5"/>
<rect x="166" y="61" width="14" height="14" fill="#F2F2F2"/>
<rect x="16" y="76" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="46" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="61" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="76" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="91" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="106" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="121" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="136" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="151" y="76" width="14" height="14" fill="#D5D5D5"/>
<rect x="166" y="76" width="14" height="14" fill="#F2F2F2"/>
<rect x="16" y="91" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="46" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="61" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="76" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="91" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="106" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="121" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="136" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="151" y="91" width="14" height="14" fill="#D5D5D5"/>
<rect x="166" y="91" width="14" height="14" fill="#F2F2F2"/>
<rect x="16" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="31" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="46" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="61" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="76" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="91" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="106" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="121" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="136" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="151" y="106" width="14" height="14" fill="#F2F2F2"/>
<rect x="166" y="106" width="14" height="14" fill="#F2F2F2"/>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

+7
View File
@@ -0,0 +1,7 @@
<svg width="175" height="134" viewBox="0 0 175 134" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="0.5" y1="2.18557e-08" x2="0.499994" y2="132.759" stroke="#B9C0C5"/>
<line x1="175" y1="133.259" x2="-4.37114e-08" y2="133.259" stroke="#B9C0C5"/>
<path d="M1.5 95.9999C13 95.9999 6.58853 66.4999 29.5 66.4999C46.5 66.4999 46.1214 34.9348 68.5 34.4999C94.2816 33.9989 80.7136 65.0065 106.5 65C125.715 64.9952 131.5 50.5 145.5 50.5C159.5 50.5 156.5 70.5 171.5 70.5" stroke="#C7CDD1" stroke-width="2" stroke-linecap="round"/>
<path d="M1.5 106C13 106 6.58853 76.4999 29.5 76.4999C46.5 76.4999 46.1214 44.9348 68.5 44.4999C94.2816 43.9989 80.7136 75.0065 106.5 75C125.715 74.9952 131.5 60.5 145.5 60.5C159.5 60.5 156.5 80.5 171.5 80.5" stroke="#F2F2F2" stroke-width="2" stroke-linecap="round"/>
<path d="M1.5 116C13 116 6.58853 86.4999 29.5 86.4999C46.5 86.4999 46.1214 54.9348 68.5 54.4999C94.2816 53.9989 80.7136 85.0065 106.5 85C125.715 84.9952 131.5 70.5 145.5 70.5C159.5 70.5 156.5 90.5 171.5 90.5" stroke="#ABB4BA" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -20,6 +20,7 @@ class AqiDistributionChart extends StatelessWidget {
return BarChart( return BarChart(
BarChartData( BarChartData(
maxY: 100.1, maxY: 100.1,
alignment: BarChartAlignment.start,
gridData: EnergyManagementChartsHelper.gridData( gridData: EnergyManagementChartsHelper.gridData(
horizontalInterval: 20, horizontalInterval: 20,
), ),
@@ -3,7 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart_title.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart_title.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_chart_empty_state_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class AqiDistributionChartBox extends StatelessWidget { class AqiDistributionChartBox extends StatelessWidget {
@@ -32,8 +34,20 @@ class AqiDistributionChartBox extends StatelessWidget {
const SizedBox(height: 10), const SizedBox(height: 10),
const Divider(), const Divider(),
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded( Visibility(
child: AqiDistributionChart(chartData: state.chartData), visible: state.chartData.isNotEmpty,
replacement: AnalyticsChartEmptyStateWidget(
isLoading: state.status == AirQualityDistributionStatus.loading,
isError: state.status == AirQualityDistributionStatus.failure,
isInitial: state.status == AirQualityDistributionStatus.initial,
errorMessage: state.errorMessage,
iconPath: Assets.emptyBarredChart,
),
child: Expanded(
child: AqiDistributionChart(
chartData: state.chartData,
),
),
), ),
], ],
), ),
@@ -3,7 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/blocs/range_of_aqi/range_of_aqi_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/blocs/range_of_aqi/range_of_aqi_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart_title.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart_title.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_chart_empty_state_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class RangeOfAqiChartBox extends StatelessWidget { class RangeOfAqiChartBox extends StatelessWidget {
@@ -32,10 +34,20 @@ class RangeOfAqiChartBox extends StatelessWidget {
const SizedBox(height: 10), const SizedBox(height: 10),
const Divider(), const Divider(),
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded( Visibility(
child: RangeOfAqiChart( visible: state.filteredRangeOfAqi.isNotEmpty,
chartData: state.filteredRangeOfAqi, replacement: AnalyticsChartEmptyStateWidget(
selectedAqiType: state.selectedAqiType, isLoading: state.status == RangeOfAqiStatus.loading,
isError: state.status == RangeOfAqiStatus.failure,
isInitial: state.status == RangeOfAqiStatus.initial,
errorMessage: state.errorMessage,
iconPath: Assets.emptyRangeOfAqi,
),
child: Expanded(
child: RangeOfAqiChart(
chartData: state.filteredRangeOfAqi,
selectedAqiType: state.selectedAqiType,
),
), ),
), ),
], ],
@@ -38,7 +38,7 @@ class AnalyticsEnergyManagementView extends StatelessWidget {
return SingleChildScrollView( return SingleChildScrollView(
child: Container( child: Container(
padding: _padding, padding: _padding,
height: MediaQuery.sizeOf(context).height * 1, height: MediaQuery.sizeOf(context).height * 1.05,
child: const Column( child: const Column(
children: [ children: [
Expanded( Expanded(
@@ -5,8 +5,10 @@ import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/ener
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/chart_title.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/chart_title.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_devices_list.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_devices_list.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_chart_empty_state_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/charts_loading_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/charts_loading_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class EnergyConsumptionPerDeviceChartBox extends StatelessWidget { class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
@@ -54,8 +56,24 @@ class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
const Divider(height: 0), const Divider(height: 0),
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded( Visibility(
child: EnergyConsumptionPerDeviceChart(chartData: state.chartData), visible: state.chartData.isNotEmpty &&
state.chartData
.every((e) => e.energy.every((e) => e.value != 0)),
replacement: AnalyticsChartEmptyStateWidget(
isLoading:
state.status == EnergyConsumptionPerDeviceStatus.loading,
isError: state.status == EnergyConsumptionPerDeviceStatus.failure,
isInitial:
state.status == EnergyConsumptionPerDeviceStatus.initial,
errorMessage: state.errorMessage,
iconPath: Assets.emptyEnergyManagementPerDevice,
),
child: Expanded(
child: EnergyConsumptionPerDeviceChart(
chartData: state.chartData,
),
),
), ),
], ],
), ),
@@ -3,8 +3,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/chart_title.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/chart_title.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/total_energy_consumption_chart.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/total_energy_consumption_chart.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_chart_empty_state_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/charts_loading_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/charts_loading_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class TotalEnergyConsumptionChartBox extends StatelessWidget { class TotalEnergyConsumptionChartBox extends StatelessWidget {
@@ -41,7 +43,18 @@ class TotalEnergyConsumptionChartBox extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
const Divider(), const Divider(),
const SizedBox(height: 20), const SizedBox(height: 20),
TotalEnergyConsumptionChart(chartData: state.chartData), Visibility(
visible: state.chartData.isNotEmpty &&
state.chartData.every((e) => e.value != 0),
replacement: AnalyticsChartEmptyStateWidget(
isLoading: state.status == TotalEnergyConsumptionStatus.loading,
isError: state.status == TotalEnergyConsumptionStatus.failure,
isInitial: state.status == TotalEnergyConsumptionStatus.initial,
errorMessage: state.errorMessage,
iconPath: Assets.emptyEnergyManagementChart,
),
child: TotalEnergyConsumptionChart(chartData: state.chartData),
),
], ],
), ),
), ),
@@ -18,6 +18,7 @@ class OccupancyChart extends StatelessWidget {
return BarChart( return BarChart(
BarChartData( BarChartData(
maxY: 100.001, maxY: 100.001,
alignment: BarChartAlignment.start,
gridData: EnergyManagementChartsHelper.gridData().copyWith( gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true, checkToShowHorizontalLine: (value) => true,
horizontalInterval: 20, horizontalInterval: 20,
@@ -6,8 +6,10 @@ import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/ch
import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy/occupancy_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy/occupancy_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart';
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_chart.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_chart.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_chart_empty_state_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class OccupancyChartBox extends StatelessWidget { class OccupancyChartBox extends StatelessWidget {
@@ -67,7 +69,24 @@ class OccupancyChartBox extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
const Divider(), const Divider(),
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded(child: OccupancyChart(chartData: state.chartData)), Visibility(
visible: state.chartData.isNotEmpty &&
state.chartData.every(
(e) => e.occupancy.isNotEmpty,
),
replacement: AnalyticsChartEmptyStateWidget(
isLoading: state.status == OccupancyStatus.loading,
isError: state.status == OccupancyStatus.failure,
isInitial: state.status == OccupancyStatus.initial,
errorMessage: state.errorMessage,
iconPath: Assets.emptyBarredChart,
),
child: Expanded(
child: OccupancyChart(
chartData: state.chartData,
),
),
),
], ],
), ),
); );
@@ -6,8 +6,10 @@ import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/ch
import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy_heat_map/occupancy_heat_map_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy_heat_map/occupancy_heat_map_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart';
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_chart_empty_state_widget.dart';
import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_error_widget.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class OccupancyHeatMapBox extends StatelessWidget { class OccupancyHeatMapBox extends StatelessWidget {
@@ -68,16 +70,29 @@ class OccupancyHeatMapBox extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
const Divider(), const Divider(),
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded( Visibility(
child: OccupancyHeatMap( visible: state.heatMapData.isNotEmpty &&
selectedDate: state.heatMapData.every(
context.watch<AnalyticsDatePickerBloc>().state.yearlyDate, (e) => e.countTotalPresenceDetected != 0,
heatMapData: state.heatMapData.asMap().map( ),
(_, value) => MapEntry( replacement: AnalyticsChartEmptyStateWidget(
value.eventDate, isLoading: state.status == OccupancyHeatMapStatus.loading,
value.countTotalPresenceDetected, isError: state.status == OccupancyHeatMapStatus.failure,
isInitial: state.status == OccupancyHeatMapStatus.initial,
errorMessage: state.errorMessage,
iconPath: Assets.emptyHeatmap,
),
child: Expanded(
child: OccupancyHeatMap(
selectedDate:
context.watch<AnalyticsDatePickerBloc>().state.yearlyDate,
heatMapData: state.heatMapData.asMap().map(
(_, value) => MapEntry(
value.eventDate,
value.countTotalPresenceDetected,
),
), ),
), ),
), ),
), ),
], ],
@@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/common/widgets/app_loading_indicator.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class AnalyticsChartEmptyStateWidget extends StatelessWidget {
const AnalyticsChartEmptyStateWidget({
required this.iconPath,
this.isLoading = false,
this.isError = false,
this.isInitial = false,
this.errorMessage,
this.noDataMessage = 'No data to display',
this.initialMessage = 'Please select a space to see data',
super.key,
});
final bool isLoading;
final bool isError;
final bool isInitial;
final String? errorMessage;
final String noDataMessage;
final String initialMessage;
final String iconPath;
@override
Widget build(BuildContext context) {
return Expanded(
child: _buildWidgetBasedOnState(context),
);
}
Widget _buildWidgetBasedOnState(BuildContext context) {
final widgetsMap = {
isLoading: const AppLoadingIndicator(),
isInitial: _buildState(context, initialMessage),
isError: _buildState(context, errorMessage ?? 'Something went wrong'),
};
return widgetsMap[true] ?? _buildState(context, noDataMessage);
}
Widget _buildState(BuildContext context, String message) {
return Center(
child: Column(
spacing: 16,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 16),
Expanded(child: SvgPicture.asset(iconPath, fit: BoxFit.contain)),
SelectableText(
message,
style: isError
? context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.red,
fontSize: 16,
fontWeight: FontWeight.w700,
)
: null,
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
],
),
);
}
}
@@ -15,7 +15,8 @@ import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayout { class AcDeviceBatchControlView extends StatelessWidget
with HelperResponsiveLayout {
const AcDeviceBatchControlView({super.key, required this.devicesIds}); const AcDeviceBatchControlView({super.key, required this.devicesIds});
final List<String> devicesIds; final List<String> devicesIds;
@@ -51,7 +52,7 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
deviceId: devicesIds.first, deviceId: devicesIds.first,
code: 'switch', code: 'switch',
value: state.status.acSwitch, value: state.status.acSwitch,
label: 'ThermoState', label: 'Thermostat',
icon: Assets.ac, icon: Assets.ac,
onChange: (value) { onChange: (value) {
context.read<AcBloc>().add(AcBatchControlEvent( context.read<AcBloc>().add(AcBatchControlEvent(
@@ -100,8 +101,8 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
), ),
Text( Text(
'h', 'h',
style: style: context.textTheme.bodySmall!
context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor), .copyWith(color: ColorsManager.blackColor),
), ),
Text( Text(
'30', '30',
@@ -148,7 +149,8 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
callFactoryReset: () { callFactoryReset: () {
context.read<AcBloc>().add(AcFactoryResetEvent( context.read<AcBloc>().add(AcFactoryResetEvent(
deviceId: state.status.uuid, deviceId: state.status.uuid,
factoryResetModel: FactoryResetModel(devicesUuid: devicesIds), factoryResetModel:
FactoryResetModel(devicesUuid: devicesIds),
)); ));
}, },
), ),
@@ -68,6 +68,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
children: [ children: [
Expanded(child: SpaceTreeView( Expanded(child: SpaceTreeView(
onSelect: () { onSelect: () {
context.read<DeviceManagementBloc>().add(ResetFilters());
context.read<DeviceManagementBloc>().add(FetchDevices(context)); context.read<DeviceManagementBloc>().add(FetchDevices(context));
}, },
)), )),
@@ -62,9 +62,9 @@ class CurtainModuleItems extends StatelessWidget with HelperResponsiveLayout {
BlocProvider.of<CurtainModuleBloc>(context), BlocProvider.of<CurtainModuleBloc>(context),
child: BuildScheduleView( child: BuildScheduleView(
deviceUuid: deviceId, deviceUuid: deviceId,
category: 'timer', category: 'Timer',
code: 'control', code: 'control',
countdownCode: 'timer', countdownCode: 'Timer',
deviceType: 'CUR_2', deviceType: 'CUR_2',
), ),
)); ));
@@ -277,6 +277,32 @@ class SmartPowerDeviceControl extends StatelessWidget
totalConsumption: 10000, totalConsumption: 10000,
date: blocProvider.formattedDate, date: blocProvider.formattedDate,
), ),
EnergyConsumptionPage(
formattedDate:
'${blocProvider.dateTime!.day}/${blocProvider.dateTime!.month}/${blocProvider.dateTime!.year} ${blocProvider.endChartDate}',
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', 6.8),
EnergyData('09:00 AM', 5.6),
EnergyData('10:00 AM', 3.9),
EnergyData('11:00 AM', 4.0),
],
totalConsumption: 10000,
date: blocProvider.formattedDate,
),
], ],
), ),
), ),
@@ -232,7 +232,6 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
selectedDays: List.filled(7, false), selectedDays: List.filled(7, false),
functionOn: false, functionOn: false,
isEditing: false, isEditing: false,
countdownRemaining: Duration.zero,
)); ));
} else { } else {
emit(ScheduleLoaded( emit(ScheduleLoaded(
@@ -455,7 +455,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
Future<void> checkEmail( Future<void> checkEmail(
CheckEmailEvent event, Emitter<UsersState> emit) async { CheckEmailEvent event, Emitter<UsersState> emit) async {
emit(UsersLoadingState()); emit(UsersLoadingState());
String? res = await UserPermissionApi().checkEmail( String? res = await UserPermissionApi().checkEmail(
emailController.text, emailController.text,
); );
checkEmailValid = res!; checkEmailValid = res!;
@@ -34,7 +34,8 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
return Dialog( return Dialog(
child: Container( child: Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))), color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20))),
width: 900, width: 900,
child: Column( child: Column(
children: [ children: [
@@ -63,7 +64,8 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
children: [ children: [
_buildStep1Indicator(1, "Basics", _blocRole), _buildStep1Indicator(1, "Basics", _blocRole),
_buildStep2Indicator(2, "Spaces", _blocRole), _buildStep2Indicator(2, "Spaces", _blocRole),
_buildStep3Indicator(3, "Role & Permissions", _blocRole), _buildStep3Indicator(
3, "Role & Permissions", _blocRole),
], ],
), ),
), ),
@@ -105,18 +107,32 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
), ),
InkWell( InkWell(
onTap: () { onTap: () {
final isBasicsStep = currentStep == 1;
if (isBasicsStep) {
// Validate the form first
final isValid = _blocRole.formKey.currentState
?.validate() ??
false;
if (!isValid)
return; // Stop if form is not valid
}
_blocRole.add(const CheckEmailEvent()); _blocRole.add(const CheckEmailEvent());
setState(() { setState(() {
if (currentStep < 3) { if (currentStep < 3) {
currentStep++; currentStep++;
if (currentStep == 2) { if (currentStep == 2) {
_blocRole.add(const CheckStepStatus(isEditUser: false)); _blocRole.add(const CheckStepStatus(
isEditUser: false));
} else if (currentStep == 3) { } else if (currentStep == 3) {
_blocRole.add(const CheckSpacesStepStatus()); _blocRole
.add(const CheckSpacesStepStatus());
} }
} else { } else {
_blocRole.add(SendInviteUsers(context: context)); _blocRole
.add(SendInviteUsers(context: context));
} }
}); });
}, },
@@ -124,8 +140,11 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
currentStep < 3 ? "Next" : "Save", currentStep < 3 ? "Next" : "Save",
style: TextStyle( style: TextStyle(
color: (_blocRole.isCompleteSpaces == false || color: (_blocRole.isCompleteSpaces == false ||
_blocRole.isCompleteBasics == false || _blocRole.isCompleteBasics ==
_blocRole.isCompleteRolePermissions == false) && false ||
_blocRole
.isCompleteRolePermissions ==
false) &&
currentStep == 3 currentStep == 3
? ColorsManager.grayColor ? ColorsManager.grayColor
: ColorsManager.secondaryColor), : ColorsManager.secondaryColor),
@@ -143,7 +162,7 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
Widget _getFormContent() { Widget _getFormContent() {
switch (currentStep) { switch (currentStep) {
case 1: case 1:
return const BasicsView( return BasicsView(
userId: '', userId: '',
); );
case 2: case 2:
@@ -196,8 +215,12 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, color: currentStep == step
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, ? ColorsManager.blackColor
: ColorsManager.greyColor,
fontWeight: currentStep == step
? FontWeight.bold
: FontWeight.normal,
), ),
), ),
], ],
@@ -260,8 +283,12 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, color: currentStep == step
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, ? ColorsManager.blackColor
: ColorsManager.greyColor,
fontWeight: currentStep == step
? FontWeight.bold
: FontWeight.normal,
), ),
), ),
], ],
@@ -318,8 +345,12 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, color: currentStep == step
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, ? ColorsManager.blackColor
: ColorsManager.greyColor,
fontWeight: currentStep == step
? FontWeight.bold
: FontWeight.normal,
), ),
), ),
], ],
@@ -1,9 +1,12 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl_phone_field/countries.dart'; import 'package:intl_phone_field/countries.dart';
import 'package:intl_phone_field/country_picker_dialog.dart'; import 'package:intl_phone_field/country_picker_dialog.dart';
import 'package:intl_phone_field/intl_phone_field.dart'; import 'package:intl_phone_field/intl_phone_field.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@@ -11,7 +14,9 @@ import 'package:syncrow_web/utils/style.dart';
class BasicsView extends StatelessWidget { class BasicsView extends StatelessWidget {
final String? userId; final String? userId;
const BasicsView({super.key, this.userId = ''}); Timer? _debounce;
BasicsView({super.key, this.userId = ''});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<UsersBloc, UsersState>(builder: (context, state) { return BlocBuilder<UsersBloc, UsersState>(builder: (context, state) {
@@ -21,6 +26,7 @@ class BasicsView extends StatelessWidget {
} }
return Form( return Form(
key: _blocRole.formKey, key: _blocRole.formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: ListView( child: ListView(
shrinkWrap: true, shrinkWrap: true,
children: [ children: [
@@ -208,6 +214,14 @@ class BasicsView extends StatelessWidget {
fontSize: 12, fontSize: 12,
color: ColorsManager.textGray), color: ColorsManager.textGray),
), ),
onChanged: (value) {
if (_debounce?.isActive ?? false) _debounce!.cancel();
_debounce = Timer(const Duration(milliseconds: 800), () {
_blocRole.add(const CheckEmailEvent());
});
},
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Enter Email Address'; return 'Enter Email Address';
+46 -78
View File
@@ -14,8 +14,7 @@ class Assets {
static const String rightLine = 'assets/images/right_line.png'; static const String rightLine = 'assets/images/right_line.png';
static const String google = 'assets/images/google.svg'; static const String google = 'assets/images/google.svg';
static const String facebook = 'assets/images/facebook.svg'; static const String facebook = 'assets/images/facebook.svg';
static const String invisiblePassword = static const String invisiblePassword = 'assets/images/Password_invisible.svg';
'assets/images/Password_invisible.svg';
static const String visiblePassword = 'assets/images/password_visible.svg'; static const String visiblePassword = 'assets/images/password_visible.svg';
static const String accessIcon = 'assets/images/access_icon.svg'; static const String accessIcon = 'assets/images/access_icon.svg';
static const String spaseManagementIcon = static const String spaseManagementIcon =
@@ -34,8 +33,7 @@ class Assets {
static const String emptyTable = 'assets/images/empty_table.svg'; static const String emptyTable = 'assets/images/empty_table.svg';
// General assets // General assets
static const String motionlessDetection = static const String motionlessDetection = 'assets/icons/motionless_detection.svg';
'assets/icons/motionless_detection.svg';
static const String acHeating = 'assets/icons/ac_heating.svg'; static const String acHeating = 'assets/icons/ac_heating.svg';
static const String acPowerOff = 'assets/icons/ac_power_off.svg'; static const String acPowerOff = 'assets/icons/ac_power_off.svg';
static const String acFanMiddle = 'assets/icons/ac_fan_middle.svg'; static const String acFanMiddle = 'assets/icons/ac_fan_middle.svg';
@@ -72,22 +70,19 @@ class Assets {
'assets/icons/automation_functions/temp_password_unlock.svg'; 'assets/icons/automation_functions/temp_password_unlock.svg';
static const String doorlockNormalOpen = static const String doorlockNormalOpen =
'assets/icons/automation_functions/doorlock_normal_open.svg'; 'assets/icons/automation_functions/doorlock_normal_open.svg';
static const String doorbell = static const String doorbell = 'assets/icons/automation_functions/doorbell.svg';
'assets/icons/automation_functions/doorbell.svg';
static const String remoteUnlockViaApp = static const String remoteUnlockViaApp =
'assets/icons/automation_functions/remote_unlock_via_app.svg'; 'assets/icons/automation_functions/remote_unlock_via_app.svg';
static const String doubleLock = static const String doubleLock =
'assets/icons/automation_functions/double_lock.svg'; 'assets/icons/automation_functions/double_lock.svg';
static const String selfTestResult = static const String selfTestResult =
'assets/icons/automation_functions/self_test_result.svg'; 'assets/icons/automation_functions/self_test_result.svg';
static const String lockAlarm = static const String lockAlarm = 'assets/icons/automation_functions/lock_alarm.svg';
'assets/icons/automation_functions/lock_alarm.svg';
static const String presenceState = static const String presenceState =
'assets/icons/automation_functions/presence_state.svg'; 'assets/icons/automation_functions/presence_state.svg';
static const String currentTemp = static const String currentTemp =
'assets/icons/automation_functions/current_temp.svg'; 'assets/icons/automation_functions/current_temp.svg';
static const String presence = static const String presence = 'assets/icons/automation_functions/presence.svg';
'assets/icons/automation_functions/presence.svg';
static const String residualElectricity = static const String residualElectricity =
'assets/icons/automation_functions/residual_electricity.svg'; 'assets/icons/automation_functions/residual_electricity.svg';
static const String hijackAlarm = static const String hijackAlarm =
@@ -104,15 +99,12 @@ class Assets {
// Presence Sensor Assets // Presence Sensor Assets
static const String sensorMotionIcon = 'assets/icons/sensor_motion_ic.svg'; static const String sensorMotionIcon = 'assets/icons/sensor_motion_ic.svg';
static const String sensorPresenceIcon = static const String sensorPresenceIcon = 'assets/icons/sensor_presence_ic.svg';
'assets/icons/sensor_presence_ic.svg';
static const String sensorVacantIcon = 'assets/icons/sensor_vacant_ic.svg'; static const String sensorVacantIcon = 'assets/icons/sensor_vacant_ic.svg';
static const String illuminanceRecordIcon = static const String illuminanceRecordIcon =
'assets/icons/illuminance_record_ic.svg'; 'assets/icons/illuminance_record_ic.svg';
static const String presenceRecordIcon = static const String presenceRecordIcon = 'assets/icons/presence_record_ic.svg';
'assets/icons/presence_record_ic.svg'; static const String helpDescriptionIcon = 'assets/icons/help_description_ic.svg';
static const String helpDescriptionIcon =
'assets/icons/help_description_ic.svg';
static const String lightPulp = 'assets/icons/light_pulb.svg'; static const String lightPulp = 'assets/icons/light_pulb.svg';
static const String acDevice = 'assets/icons/ac_device.svg'; static const String acDevice = 'assets/icons/ac_device.svg';
@@ -166,12 +158,10 @@ class Assets {
static const String unit = 'assets/icons/unit_icon.svg'; static const String unit = 'assets/icons/unit_icon.svg';
static const String villa = 'assets/icons/villa_icon.svg'; static const String villa = 'assets/icons/villa_icon.svg';
static const String iconEdit = 'assets/icons/icon_edit_icon.svg'; static const String iconEdit = 'assets/icons/icon_edit_icon.svg';
static const String textFieldSearch = static const String textFieldSearch = 'assets/icons/textfield_search_icon.svg';
'assets/icons/textfield_search_icon.svg';
static const String roundedAddIcon = 'assets/icons/rounded_add_icon.svg'; static const String roundedAddIcon = 'assets/icons/rounded_add_icon.svg';
static const String addIcon = 'assets/icons/add_icon.svg'; static const String addIcon = 'assets/icons/add_icon.svg';
static const String smartThermostatIcon = static const String smartThermostatIcon = 'assets/icons/smart_thermostat_icon.svg';
'assets/icons/smart_thermostat_icon.svg';
static const String smartLightIcon = 'assets/icons/smart_light_icon.svg'; static const String smartLightIcon = 'assets/icons/smart_light_icon.svg';
static const String presenceSensor = 'assets/icons/presence_sensor.svg'; static const String presenceSensor = 'assets/icons/presence_sensor.svg';
static const String Gang3SwitchIcon = 'assets/icons/3_Gang_switch_icon.svg'; static const String Gang3SwitchIcon = 'assets/icons/3_Gang_switch_icon.svg';
@@ -219,8 +209,7 @@ class Assets {
//assets/icons/water_leak_normal.svg //assets/icons/water_leak_normal.svg
static const String waterLeakNormal = 'assets/icons/water_leak_normal.svg'; static const String waterLeakNormal = 'assets/icons/water_leak_normal.svg';
//assets/icons/water_leak_detected.svg //assets/icons/water_leak_detected.svg
static const String waterLeakDetected = static const String waterLeakDetected = 'assets/icons/water_leak_detected.svg';
'assets/icons/water_leak_detected.svg';
//assets/icons/automation_records.svg //assets/icons/automation_records.svg
static const String automationRecords = 'assets/icons/automation_records.svg'; static const String automationRecords = 'assets/icons/automation_records.svg';
@@ -291,16 +280,13 @@ class Assets {
'assets/icons/functions_icons/sensitivity.svg'; 'assets/icons/functions_icons/sensitivity.svg';
static const String assetsSensitivityOperationIcon = static const String assetsSensitivityOperationIcon =
'assets/icons/functions_icons/sesitivity_operation_icon.svg'; 'assets/icons/functions_icons/sesitivity_operation_icon.svg';
static const String assetsAcPower = static const String assetsAcPower = 'assets/icons/functions_icons/ac_power.svg';
'assets/icons/functions_icons/ac_power.svg';
static const String assetsAcPowerOFF = static const String assetsAcPowerOFF =
'assets/icons/functions_icons/ac_power_off.svg'; 'assets/icons/functions_icons/ac_power_off.svg';
static const String assetsChildLock = static const String assetsChildLock =
'assets/icons/functions_icons/child_lock.svg'; 'assets/icons/functions_icons/child_lock.svg';
static const String assetsFreezing = static const String assetsFreezing = 'assets/icons/functions_icons/freezing.svg';
'assets/icons/functions_icons/freezing.svg'; static const String assetsFanSpeed = 'assets/icons/functions_icons/fan_speed.svg';
static const String assetsFanSpeed =
'assets/icons/functions_icons/fan_speed.svg';
static const String assetsAcCooling = static const String assetsAcCooling =
'assets/icons/functions_icons/ac_cooling.svg'; 'assets/icons/functions_icons/ac_cooling.svg';
static const String assetsAcHeating = static const String assetsAcHeating =
@@ -309,8 +295,7 @@ class Assets {
'assets/icons/functions_icons/celsius_degrees.svg'; 'assets/icons/functions_icons/celsius_degrees.svg';
static const String assetsTempreture = static const String assetsTempreture =
'assets/icons/functions_icons/tempreture.svg'; 'assets/icons/functions_icons/tempreture.svg';
static const String assetsAcFanLow = static const String assetsAcFanLow = 'assets/icons/functions_icons/ac_fan_low.svg';
'assets/icons/functions_icons/ac_fan_low.svg';
static const String assetsAcFanMiddle = static const String assetsAcFanMiddle =
'assets/icons/functions_icons/ac_fan_middle.svg'; 'assets/icons/functions_icons/ac_fan_middle.svg';
static const String assetsAcFanHigh = static const String assetsAcFanHigh =
@@ -329,8 +314,7 @@ class Assets {
'assets/icons/functions_icons/far_detection.svg'; 'assets/icons/functions_icons/far_detection.svg';
static const String assetsFarDetectionFunction = static const String assetsFarDetectionFunction =
'assets/icons/functions_icons/far_detection_function.svg'; 'assets/icons/functions_icons/far_detection_function.svg';
static const String assetsIndicator = static const String assetsIndicator = 'assets/icons/functions_icons/indicator.svg';
'assets/icons/functions_icons/indicator.svg';
static const String assetsMotionDetection = static const String assetsMotionDetection =
'assets/icons/functions_icons/motion_detection.svg'; 'assets/icons/functions_icons/motion_detection.svg';
static const String assetsMotionlessDetection = static const String assetsMotionlessDetection =
@@ -343,8 +327,7 @@ class Assets {
'assets/icons/functions_icons/master_state.svg'; 'assets/icons/functions_icons/master_state.svg';
static const String assetsSwitchAlarmSound = static const String assetsSwitchAlarmSound =
'assets/icons/functions_icons/switch_alarm_sound.svg'; 'assets/icons/functions_icons/switch_alarm_sound.svg';
static const String assetsResetOff = static const String assetsResetOff = 'assets/icons/functions_icons/reset_off.svg';
'assets/icons/functions_icons/reset_off.svg';
// Assets for automation_functions // Assets for automation_functions
static const String assetsCardUnlock = static const String assetsCardUnlock =
@@ -388,15 +371,13 @@ class Assets {
static const String activeUser = 'assets/icons/active_user.svg'; static const String activeUser = 'assets/icons/active_user.svg';
static const String deActiveUser = 'assets/icons/deactive_user.svg'; static const String deActiveUser = 'assets/icons/deactive_user.svg';
static const String invitedIcon = 'assets/icons/invited_icon.svg'; static const String invitedIcon = 'assets/icons/invited_icon.svg';
static const String rectangleCheckBox = static const String rectangleCheckBox = 'assets/icons/rectangle_check_box.png';
'assets/icons/rectangle_check_box.png';
static const String CheckBoxChecked = 'assets/icons/box_checked.png'; static const String CheckBoxChecked = 'assets/icons/box_checked.png';
static const String emptyBox = 'assets/icons/empty_box.png'; static const String emptyBox = 'assets/icons/empty_box.png';
static const String completeProcessIcon = static const String completeProcessIcon =
'assets/icons/compleate_process_icon.svg'; 'assets/icons/compleate_process_icon.svg';
static const String completedDoneIcon = 'assets/images/completed_done.svg'; static const String completedDoneIcon = 'assets/images/completed_done.svg';
static const String currentProcessIcon = static const String currentProcessIcon = 'assets/icons/current_process_icon.svg';
'assets/icons/current_process_icon.svg';
static const String uncomplete_ProcessIcon = static const String uncomplete_ProcessIcon =
'assets/icons/uncompleate_process_icon.svg'; 'assets/icons/uncompleate_process_icon.svg';
static const String wrongProcessIcon = 'assets/icons/wrong_process_icon.svg'; static const String wrongProcessIcon = 'assets/icons/wrong_process_icon.svg';
@@ -417,11 +398,9 @@ class Assets {
static const String successIcon = 'assets/icons/success_icon.svg'; static const String successIcon = 'assets/icons/success_icon.svg';
static const String spaceLocationIcon = 'assets/icons/spaseLocationIcon.svg'; static const String spaceLocationIcon = 'assets/icons/spaseLocationIcon.svg';
static const String scenesPlayIcon = 'assets/icons/scenesPlayIcon.png'; static const String scenesPlayIcon = 'assets/icons/scenesPlayIcon.png';
static const String scenesPlayIconCheck = static const String scenesPlayIconCheck = 'assets/icons/scenesPlayIconCheck.png';
'assets/icons/scenesPlayIconCheck.png';
static const String presenceStateIcon = 'assets/icons/presence_state.svg'; static const String presenceStateIcon = 'assets/icons/presence_state.svg';
static const String currentDistanceIcon = static const String currentDistanceIcon = 'assets/icons/current_distance_icon.svg';
'assets/icons/current_distance_icon.svg';
static const String farDetectionIcon = 'assets/icons/far_detection_icon.svg'; static const String farDetectionIcon = 'assets/icons/far_detection_icon.svg';
static const String motionDetectionSensitivityIcon = static const String motionDetectionSensitivityIcon =
@@ -444,44 +423,29 @@ class Assets {
static const String cpsMode4 = 'assets/icons/cps_mode4.svg'; static const String cpsMode4 = 'assets/icons/cps_mode4.svg';
static const String closeToMotion = 'assets/icons/close_to_motion.svg'; static const String closeToMotion = 'assets/icons/close_to_motion.svg';
static const String farAwayMotion = 'assets/icons/far_away_motion.svg'; static const String farAwayMotion = 'assets/icons/far_away_motion.svg';
static const String communicationFault = static const String communicationFault = 'assets/icons/communication_fault.svg';
'assets/icons/communication_fault.svg';
static const String radarFault = 'assets/icons/radar_fault.svg'; static const String radarFault = 'assets/icons/radar_fault.svg';
static const String selfTestingSuccess = static const String selfTestingSuccess = 'assets/icons/self_testing_success.svg';
'assets/icons/self_testing_success.svg'; static const String selfTestingFailure = 'assets/icons/self_testing_failure.svg';
static const String selfTestingFailure = static const String selfTestingTimeout = 'assets/icons/self_testing_timeout.svg';
'assets/icons/self_testing_failure.svg';
static const String selfTestingTimeout =
'assets/icons/self_testing_timeout.svg';
static const String movingSpeed = 'assets/icons/moving_speed.svg'; static const String movingSpeed = 'assets/icons/moving_speed.svg';
static const String boundary = 'assets/icons/boundary.svg'; static const String boundary = 'assets/icons/boundary.svg';
static const String motionMeter = 'assets/icons/motion_meter.svg'; static const String motionMeter = 'assets/icons/motion_meter.svg';
static const String spatialStaticValue = static const String spatialStaticValue = 'assets/icons/spatial_static_value.svg';
'assets/icons/spatial_static_value.svg'; static const String spatialMotionValue = 'assets/icons/spatial_motion_value.svg';
static const String spatialMotionValue =
'assets/icons/spatial_motion_value.svg';
static const String presenceJudgementThrshold = static const String presenceJudgementThrshold =
'assets/icons/presence_judgement_threshold.svg'; 'assets/icons/presence_judgement_threshold.svg';
static const String spaceType = 'assets/icons/space_type.svg'; static const String spaceType = 'assets/icons/space_type.svg';
static const String sportsPara = 'assets/icons/sports_para.svg'; static const String sportsPara = 'assets/icons/sports_para.svg';
static const String sensitivityFeature1 = static const String sensitivityFeature1 = 'assets/icons/sensitivity_feature_1.svg';
'assets/icons/sensitivity_feature_1.svg'; static const String sensitivityFeature2 = 'assets/icons/sensitivity_feature_2.svg';
static const String sensitivityFeature2 = static const String sensitivityFeature3 = 'assets/icons/sensitivity_feature_3.svg';
'assets/icons/sensitivity_feature_2.svg'; static const String sensitivityFeature4 = 'assets/icons/sensitivity_feature_4.svg';
static const String sensitivityFeature3 = static const String sensitivityFeature5 = 'assets/icons/sensitivity_feature_5.svg';
'assets/icons/sensitivity_feature_3.svg'; static const String sensitivityFeature6 = 'assets/icons/sensitivity_feature_6.svg';
static const String sensitivityFeature4 = static const String sensitivityFeature7 = 'assets/icons/sensitivity_feature_7.svg';
'assets/icons/sensitivity_feature_4.svg'; static const String sensitivityFeature8 = 'assets/icons/sensitivity_feature_8.svg';
static const String sensitivityFeature5 = static const String sensitivityFeature9 = 'assets/icons/sensitivity_feature_9.svg';
'assets/icons/sensitivity_feature_5.svg';
static const String sensitivityFeature6 =
'assets/icons/sensitivity_feature_6.svg';
static const String sensitivityFeature7 =
'assets/icons/sensitivity_feature_7.svg';
static const String sensitivityFeature8 =
'assets/icons/sensitivity_feature_8.svg';
static const String sensitivityFeature9 =
'assets/icons/sensitivity_feature_9.svg';
static const String deviceTagIcon = 'assets/icons/device_tag_ic.svg'; static const String deviceTagIcon = 'assets/icons/device_tag_ic.svg';
static const String targetConfirmTimeIcon = static const String targetConfirmTimeIcon =
'assets/icons/target_confirm_time_icon.svg'; 'assets/icons/target_confirm_time_icon.svg';
@@ -489,13 +453,10 @@ class Assets {
static const String indentLevelIcon = 'assets/icons/indent_level_icon.svg'; static const String indentLevelIcon = 'assets/icons/indent_level_icon.svg';
static const String triggerLevelIcon = 'assets/icons/trigger_level_icon.svg'; static const String triggerLevelIcon = 'assets/icons/trigger_level_icon.svg';
static const String blankCalendar = 'assets/icons/blank_calendar.svg'; static const String blankCalendar = 'assets/icons/blank_calendar.svg';
static const String refreshStatusIcon = static const String refreshStatusIcon = 'assets/icons/refresh_status_icon.svg';
'assets/icons/refresh_status_icon.svg'; static const String energyConsumedIcon = 'assets/icons/energy_consumed_icon.svg';
static const String energyConsumedIcon =
'assets/icons/energy_consumed_icon.svg';
static const String closeSettingsIcon = static const String closeSettingsIcon = 'assets/icons/close_settings_icon.svg';
'assets/icons/close_settings_icon.svg';
static const String editNameIconSettings = static const String editNameIconSettings =
'assets/icons/edit_name_icon_settings.svg'; 'assets/icons/edit_name_icon_settings.svg';
@@ -508,4 +469,11 @@ class Assets {
static const String humidityAqiSidebar = 'assets/icons/humidity.svg'; static const String humidityAqiSidebar = 'assets/icons/humidity.svg';
static const String autocadOccupancyImage = static const String autocadOccupancyImage =
'assets/images/autocad_occupancy_image.png'; 'assets/images/autocad_occupancy_image.png';
static const String emptyBarredChart = 'assets/icons/empty_barred_chart.svg';
static const String emptyEnergyManagementChart =
'assets/icons/empty_energy_management_chart.svg';
static const String emptyEnergyManagementPerDevice =
'assets/icons/empty_energy_management_per_device.svg';
static const String emptyHeatmap = 'assets/icons/empty_heatmap.svg';
static const String emptyRangeOfAqi = 'assets/icons/empty_range_of_aqi.svg';
} }