mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-11 07:38:05 +00:00
Compare commits
42 Commits
SP-1703-fe
...
analytics-
Author | SHA1 | Date | |
---|---|---|---|
05d784ec11 | |||
9ebf474a60 | |||
af48bbead5 | |||
3c80724c1e | |||
db05331e9a | |||
cdc76c2c8e | |||
44c88fb1c4 | |||
dfb120e7cf | |||
8c3861e83c | |||
b90f25f7b0 | |||
4d51321675 | |||
b5e7776ccb | |||
32938404dd | |||
0cfd58d820 | |||
d4625a8f04 | |||
9f24606613 | |||
e87dffd76b | |||
0c220a1f34 | |||
a526fcbeee | |||
172e1d208a | |||
2c254c1a91 | |||
480e183b91 | |||
d8bb234537 | |||
354d61dfa2 | |||
8916efcebb | |||
175d1e662b | |||
57bd4b8527 | |||
df308fd12a | |||
e0cfe541dd | |||
814cbf787f | |||
df8eff895e | |||
9514200892 | |||
cf4bfc41f6 | |||
01f55c14de | |||
388391eec4 | |||
23cfee1490 | |||
2f5ad03431 | |||
6dd3329288 | |||
034a5ef908 | |||
1828ffb87a | |||
bd53388438 | |||
df34ded153 |
8
assets/icons/empty_barred_chart.svg
Normal file
8
assets/icons/empty_barred_chart.svg
Normal 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 |
5
assets/icons/empty_energy_management_chart.svg
Normal file
5
assets/icons/empty_energy_management_chart.svg
Normal file
@ -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 |
7
assets/icons/empty_energy_management_per_device.svg
Normal file
7
assets/icons/empty_energy_management_per_device.svg
Normal 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 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
assets/icons/empty_heatmap.svg
Normal file
99
assets/icons/empty_heatmap.svg
Normal 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
assets/icons/empty_range_of_aqi.svg
Normal file
7
assets/icons/empty_range_of_aqi.svg
Normal 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 |
4
assets/images/completed_done.svg
Normal file
4
assets/images/completed_done.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M37.8033 16.3567C37.2313 15.7848 36.3039 15.7847 35.7318 16.3568L21.5532 30.5353L14.2681 23.2504C13.6962 22.6784 12.7686 22.6783 12.1966 23.2505C11.6246 23.8226 11.6246 24.75 12.1966 25.3221L20.5174 33.6427C20.8034 33.9287 21.1783 34.0717 21.5531 34.0717C21.928 34.0717 22.3029 33.9287 22.5888 33.6426L37.8033 18.4283C38.3754 17.8563 38.3754 16.9288 37.8033 16.3567Z" fill="#023DFE" fill-opacity="0.7"/>
|
||||
<path d="M42.6776 7.32236C37.9558 2.60049 31.6776 0 25 0C18.3223 0 12.0442 2.60049 7.32236 7.32236C2.60039 12.0443 0 18.3224 0 25C0 31.6778 2.60039 37.9559 7.32236 42.6777C12.0441 47.3996 18.3223 50 25 50C31.6777 50 37.9558 47.3996 42.6776 42.6777C47.3995 37.9559 50 31.6778 50 25C50 18.3224 47.3995 12.0443 42.6776 7.32236ZM25 47.0703C12.8304 47.0703 2.92969 37.1696 2.92969 25C2.92969 12.8304 12.8304 2.92969 25 2.92969C37.1696 2.92969 47.0703 12.8304 47.0703 25C47.0703 37.1696 37.1696 47.0703 25 47.0703Z" fill="#023DFE" fill-opacity="0.7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -39,8 +39,12 @@ class AnalyticsDevice {
|
||||
? ProductDevice.fromJson(json['productDevice'] as Map<String, dynamic>)
|
||||
: null,
|
||||
spaceUuid: json['spaceUuid'] as String?,
|
||||
latitude: json['lat'] != null ? double.parse(json['lat'] as String? ?? '0.0') : null,
|
||||
longitude: json['lon'] != null ? double.parse(json['lon'] as String? ?? '0.0') : null,
|
||||
latitude: json['lat'] != null && json['lat'] != ''
|
||||
? double.tryParse(json['lat']?.toString() ?? '0.0')
|
||||
: null,
|
||||
longitude: json['lon'] != null && json['lon'] != ''
|
||||
? double.tryParse(json['lon']?.toString() ?? '0.0')
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -46,11 +46,11 @@ class AirQualityDistributionBloc
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onClearAirQualityDistribution(
|
||||
void _onClearAirQualityDistribution(
|
||||
ClearAirQualityDistribution event,
|
||||
Emitter<AirQualityDistributionState> emit,
|
||||
) async {
|
||||
emit(const AirQualityDistributionState());
|
||||
) {
|
||||
emit(AirQualityDistributionState(selectedAqiType: state.selectedAqiType));
|
||||
}
|
||||
|
||||
void _onUpdateAqiTypeEvent(
|
||||
|
@ -75,6 +75,6 @@ class RangeOfAqiBloc extends Bloc<RangeOfAqiEvent, RangeOfAqiState> {
|
||||
ClearRangeOfAqiEvent event,
|
||||
Emitter<RangeOfAqiState> emit,
|
||||
) {
|
||||
emit(const RangeOfAqiState());
|
||||
emit(RangeOfAqiState(selectedAqiType: state.selectedAqiType));
|
||||
}
|
||||
}
|
||||
|
@ -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/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/widgets/analytics_chart_empty_state_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';
|
||||
|
||||
class AqiDistributionChartBox extends StatelessWidget {
|
||||
@ -32,8 +34,20 @@ class AqiDistributionChartBox extends StatelessWidget {
|
||||
const SizedBox(height: 10),
|
||||
const Divider(),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: AqiDistributionChart(chartData: state.chartData),
|
||||
Visibility(
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -34,6 +34,7 @@ class AqiDistributionChartTitle extends StatelessWidget {
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
fit: BoxFit.scaleDown,
|
||||
child: AqiTypeDropdown(
|
||||
selectedAqiType: context.watch<AirQualityDistributionBloc>().state.selectedAqiType,
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
final bloc = context.read<AirQualityDistributionBloc>();
|
||||
|
@ -18,19 +18,20 @@ enum AqiType {
|
||||
}
|
||||
|
||||
class AqiTypeDropdown extends StatefulWidget {
|
||||
const AqiTypeDropdown({super.key, required this.onChanged});
|
||||
const AqiTypeDropdown({
|
||||
required this.onChanged,
|
||||
this.selectedAqiType,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final ValueChanged<AqiType?> onChanged;
|
||||
final AqiType? selectedAqiType;
|
||||
|
||||
@override
|
||||
State<AqiTypeDropdown> createState() => _AqiTypeDropdownState();
|
||||
}
|
||||
|
||||
class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
|
||||
AqiType? _selectedItem = AqiType.aqi;
|
||||
|
||||
void _updateSelectedItem(AqiType? item) => setState(() => _selectedItem = item);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
@ -41,8 +42,8 @@ class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: DropdownButton<AqiType?>(
|
||||
value: _selectedItem,
|
||||
child: DropdownButton<AqiType>(
|
||||
value: widget.selectedAqiType,
|
||||
isDense: true,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
dropdownColor: ColorsManager.whiteColors,
|
||||
@ -59,10 +60,7 @@ class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
|
||||
items: AqiType.values
|
||||
.map((e) => DropdownMenuItem(value: e, child: Text(e.value)))
|
||||
.toList(),
|
||||
onChanged: (value) {
|
||||
_updateSelectedItem(value);
|
||||
widget.onChanged(value);
|
||||
},
|
||||
onChanged: widget.onChanged,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -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/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/widgets/analytics_chart_empty_state_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';
|
||||
|
||||
class RangeOfAqiChartBox extends StatelessWidget {
|
||||
@ -32,12 +34,22 @@ class RangeOfAqiChartBox extends StatelessWidget {
|
||||
const SizedBox(height: 10),
|
||||
const Divider(),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
Visibility(
|
||||
visible: state.filteredRangeOfAqi.isNotEmpty,
|
||||
replacement: AnalyticsChartEmptyStateWidget(
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -63,15 +63,15 @@ class RangeOfAqiChartTitle extends StatelessWidget {
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
child: AqiTypeDropdown(
|
||||
selectedAqiType: context.watch<RangeOfAqiBloc>().state.selectedAqiType,
|
||||
onChanged: (value) {
|
||||
final spaceTreeState = context.read<SpaceTreeBloc>().state;
|
||||
final spaceUuid = spaceTreeState.selectedSpaces.firstOrNull;
|
||||
|
||||
if (spaceUuid == null) return;
|
||||
|
||||
if (value != null) {
|
||||
context.read<RangeOfAqiBloc>().add(UpdateAqiTypeEvent(value));
|
||||
}
|
||||
|
||||
if (spaceUuid == null) return;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -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/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/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/charts_loading_widget.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
|
||||
@ -54,8 +56,24 @@ class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
|
||||
const SizedBox(height: 20),
|
||||
const Divider(height: 0),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: EnergyConsumptionPerDeviceChart(chartData: state.chartData),
|
||||
Visibility(
|
||||
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/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/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/charts_loading_widget.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class TotalEnergyConsumptionChartBox extends StatelessWidget {
|
||||
@ -41,7 +43,18 @@ class TotalEnergyConsumptionChartBox extends StatelessWidget {
|
||||
const SizedBox(height: 20),
|
||||
const Divider(),
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -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/helpers/fetch_occupancy_data_helper.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/space_tree/bloc/space_tree_bloc.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class OccupancyChartBox extends StatelessWidget {
|
||||
@ -67,7 +69,24 @@ class OccupancyChartBox extends StatelessWidget {
|
||||
const SizedBox(height: 20),
|
||||
const Divider(),
|
||||
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/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/widgets/analytics_chart_empty_state_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/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class OccupancyHeatMapBox extends StatelessWidget {
|
||||
@ -68,7 +70,19 @@ class OccupancyHeatMapBox extends StatelessWidget {
|
||||
const SizedBox(height: 20),
|
||||
const Divider(),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
Visibility(
|
||||
visible: state.heatMapData.isNotEmpty &&
|
||||
state.heatMapData.every(
|
||||
(e) => e.countTotalPresenceDetected != 0,
|
||||
),
|
||||
replacement: AnalyticsChartEmptyStateWidget(
|
||||
isLoading: state.status == OccupancyHeatMapStatus.loading,
|
||||
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,
|
||||
@ -80,6 +94,7 @@ class OccupancyHeatMapBox extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -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),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -16,11 +16,12 @@ class DeviceManagementBloc
|
||||
int _onlineCount = 0;
|
||||
int _offlineCount = 0;
|
||||
int _lowBatteryCount = 0;
|
||||
List<AllDevicesModel> _selectedDevices = [];
|
||||
final List<AllDevicesModel> _selectedDevices = [];
|
||||
List<AllDevicesModel> _filteredDevices = [];
|
||||
String currentProductName = '';
|
||||
String? currentCommunity;
|
||||
String? currentUnitName;
|
||||
String subSpaceName = '';
|
||||
|
||||
DeviceManagementBloc() : super(DeviceManagementInitial()) {
|
||||
on<FetchDevices>(_onFetchDevices);
|
||||
@ -31,25 +32,26 @@ class DeviceManagementBloc
|
||||
on<ResetFilters>(_onResetFilters);
|
||||
on<ResetSelectedDevices>(_onResetSelectedDevices);
|
||||
on<UpdateSelection>(_onUpdateSelection);
|
||||
on<UpdateDeviceName>(_onUpdateDeviceName);
|
||||
on<UpdateSubSpaceName>(_onUpdateSubSpaceName);
|
||||
}
|
||||
|
||||
Future<void> _onFetchDevices(
|
||||
FetchDevices event, Emitter<DeviceManagementState> emit) async {
|
||||
emit(DeviceManagementLoading());
|
||||
try {
|
||||
List<AllDevicesModel> devices = [];
|
||||
var devices = <AllDevicesModel>[];
|
||||
_devices.clear();
|
||||
var spaceBloc = event.context.read<SpaceTreeBloc>();
|
||||
final spaceBloc = event.context.read<SpaceTreeBloc>();
|
||||
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||
|
||||
if (spaceBloc.state.selectedCommunities.isEmpty) {
|
||||
devices =
|
||||
await DevicesManagementApi().fetchDevices('', '', projectUuid);
|
||||
devices = await DevicesManagementApi().fetchDevices('', '', projectUuid);
|
||||
} else {
|
||||
for (var community in spaceBloc.state.selectedCommunities) {
|
||||
List<String> spacesList =
|
||||
for (final community in spaceBloc.state.selectedCommunities) {
|
||||
final spacesList =
|
||||
spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
|
||||
for (var space in spacesList) {
|
||||
for (final space in spacesList) {
|
||||
devices.addAll(await DevicesManagementApi()
|
||||
.fetchDevices(community, space, projectUuid));
|
||||
}
|
||||
@ -74,7 +76,7 @@ class DeviceManagementBloc
|
||||
}
|
||||
}
|
||||
|
||||
void _onFilterDevices(
|
||||
Future<void> _onFilterDevices(
|
||||
FilterDevices event, Emitter<DeviceManagementState> emit) async {
|
||||
if (_devices.isNotEmpty) {
|
||||
_filteredDevices = List.from(_devices.where((device) {
|
||||
@ -156,8 +158,7 @@ class DeviceManagementBloc
|
||||
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
||||
}
|
||||
|
||||
void _onSelectDevice(
|
||||
SelectDevice event, Emitter<DeviceManagementState> emit) {
|
||||
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
|
||||
final selectedUuid = event.selectedDevice.uuid;
|
||||
|
||||
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
||||
@ -166,9 +167,9 @@ class DeviceManagementBloc
|
||||
_selectedDevices.add(event.selectedDevice);
|
||||
}
|
||||
|
||||
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
|
||||
final clonedSelectedDevices = List<AllDevicesModel>.from(_selectedDevices);
|
||||
|
||||
bool isControlButtonEnabled =
|
||||
final isControlButtonEnabled =
|
||||
_checkIfControlButtonEnabled(clonedSelectedDevices);
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
@ -198,8 +199,8 @@ class DeviceManagementBloc
|
||||
|
||||
void _onUpdateSelection(
|
||||
UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
||||
List<AllDevicesModel> selectedDevices = [];
|
||||
List<AllDevicesModel> devicesToSelectFrom = [];
|
||||
final selectedDevices = <AllDevicesModel>[];
|
||||
var devicesToSelectFrom = <AllDevicesModel>[];
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
devicesToSelectFrom = (state as DeviceManagementLoaded).devices;
|
||||
@ -207,7 +208,7 @@ class DeviceManagementBloc
|
||||
devicesToSelectFrom = (state as DeviceManagementFiltered).filteredDevices;
|
||||
}
|
||||
|
||||
for (int i = 0; i < event.selectedRows.length; i++) {
|
||||
for (var i = 0; i < event.selectedRows.length; i++) {
|
||||
if (event.selectedRows[i]) {
|
||||
selectedDevices.add(devicesToSelectFrom[i]);
|
||||
}
|
||||
@ -253,8 +254,7 @@ class DeviceManagementBloc
|
||||
_onlineCount = _devices.where((device) => device.online == true).length;
|
||||
_offlineCount = _devices.where((device) => device.online == false).length;
|
||||
_lowBatteryCount = _devices
|
||||
.where((device) =>
|
||||
device.batteryLevel != null && device.batteryLevel! < 20)
|
||||
.where((device) => device.batteryLevel != null && device.batteryLevel! < 20)
|
||||
.length;
|
||||
}
|
||||
|
||||
@ -270,8 +270,8 @@ class DeviceManagementBloc
|
||||
return 'All';
|
||||
}
|
||||
}
|
||||
void _onSearchDevices(
|
||||
SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||
|
||||
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||
if ((event.community == null || event.community!.isEmpty) &&
|
||||
(event.unitName == null || event.unitName!.isEmpty) &&
|
||||
(event.deviceNameOrProductName == null ||
|
||||
@ -300,7 +300,7 @@ class DeviceManagementBloc
|
||||
currentCommunity = event.community;
|
||||
currentUnitName = event.unitName;
|
||||
|
||||
List<AllDevicesModel> devicesToSearch = _devices;
|
||||
final devicesToSearch = _devices;
|
||||
|
||||
if (devicesToSearch.isNotEmpty) {
|
||||
final searchText = event.deviceNameOrProductName?.toLowerCase() ?? '';
|
||||
@ -343,5 +343,134 @@ class DeviceManagementBloc
|
||||
}
|
||||
}
|
||||
|
||||
void _onUpdateDeviceName(
|
||||
UpdateDeviceName event, Emitter<DeviceManagementState> emit) {
|
||||
final devices = _devices.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
final modifiedDevice = device.copyWith(name: event.newName);
|
||||
_selectedDevices.removeWhere((device) => device.uuid == event.deviceId);
|
||||
_selectedDevices.add(modifiedDevice);
|
||||
return modifiedDevice;
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
|
||||
final filteredDevices = _filteredDevices.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
final modifiedDevice = device.copyWith(name: event.newName);
|
||||
_selectedDevices.removeWhere((device) => device.uuid == event.deviceId);
|
||||
_selectedDevices.add(modifiedDevice);
|
||||
return modifiedDevice;
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
|
||||
_devices = devices;
|
||||
_filteredDevices = filteredDevices;
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
final loaded = state as DeviceManagementLoaded;
|
||||
final selectedDevices01 = _selectedDevices.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
final modifiedDevice = device.copyWith(name: event.newName);
|
||||
return modifiedDevice;
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: devices,
|
||||
selectedIndex: loaded.selectedIndex,
|
||||
onlineCount: loaded.onlineCount,
|
||||
offlineCount: loaded.offlineCount,
|
||||
lowBatteryCount: loaded.lowBatteryCount,
|
||||
selectedDevice: selectedDevices01,
|
||||
isControlButtonEnabled: loaded.isControlButtonEnabled,
|
||||
));
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
final filtered = state as DeviceManagementFiltered;
|
||||
final selectedDevices01 = filtered.selectedDevice?.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
final modifiedDevice = device.copyWith(name: event.newName);
|
||||
return modifiedDevice;
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
emit(DeviceManagementFiltered(
|
||||
filteredDevices: filteredDevices,
|
||||
selectedIndex: filtered.selectedIndex,
|
||||
onlineCount: filtered.onlineCount,
|
||||
offlineCount: filtered.offlineCount,
|
||||
lowBatteryCount: filtered.lowBatteryCount,
|
||||
selectedDevice: selectedDevices01,
|
||||
isControlButtonEnabled: filtered.isControlButtonEnabled,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _onUpdateSubSpaceName(
|
||||
UpdateSubSpaceName event, Emitter<DeviceManagementState> emit) {
|
||||
final devices = _devices.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
return device.copyWith(
|
||||
subspace:
|
||||
device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
|
||||
final filteredDevices = _filteredDevices.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
return device.copyWith(
|
||||
subspace:
|
||||
device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
|
||||
_devices = devices;
|
||||
_filteredDevices = filteredDevices;
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
final loaded = state as DeviceManagementLoaded;
|
||||
final selectedDevices = loaded.selectedDevice?.map((device) {
|
||||
if (device.uuid == event.deviceId) {
|
||||
return device.copyWith(
|
||||
subspace:
|
||||
device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
|
||||
}
|
||||
return device;
|
||||
}).toList();
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: _devices,
|
||||
selectedIndex: loaded.selectedIndex,
|
||||
onlineCount: loaded.onlineCount,
|
||||
offlineCount: loaded.offlineCount,
|
||||
lowBatteryCount: loaded.lowBatteryCount,
|
||||
selectedDevice: selectedDevices,
|
||||
isControlButtonEnabled: loaded.isControlButtonEnabled,
|
||||
));
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
// final filtered = state as DeviceManagementFiltered;
|
||||
// emit(DeviceManagementFiltered(
|
||||
// filteredDevices: _filteredDevices,
|
||||
// selectedIndex: filtered.selectedIndex,
|
||||
// onlineCount: filtered.onlineCount,
|
||||
// offlineCount: filtered.offlineCount,
|
||||
// lowBatteryCount: filtered.lowBatteryCount,
|
||||
// selectedDevice: filtered.selectedDevice,
|
||||
// isControlButtonEnabled: filtered.isControlButtonEnabled,
|
||||
// ));
|
||||
}
|
||||
}
|
||||
|
||||
void changeSubspaceName(
|
||||
String deviceId, String newSubSpaceName, String subspaceId) {
|
||||
add(UpdateSubSpaceName(
|
||||
deviceId: deviceId,
|
||||
newSubSpaceName: newSubSpaceName,
|
||||
subspaceId: subspaceId,
|
||||
));
|
||||
}
|
||||
|
||||
List<AllDevicesModel> get selectedDevices => _selectedDevices;
|
||||
}
|
||||
|
@ -70,3 +70,21 @@ class UpdateSelection extends DeviceManagementEvent {
|
||||
|
||||
const UpdateSelection(this.selectedRows);
|
||||
}
|
||||
|
||||
class UpdateDeviceName extends DeviceManagementEvent {
|
||||
final String deviceId;
|
||||
final String newName;
|
||||
|
||||
const UpdateDeviceName({required this.deviceId, required this.newName});
|
||||
}
|
||||
|
||||
class UpdateSubSpaceName extends DeviceManagementEvent {
|
||||
final String deviceId;
|
||||
final String newSubSpaceName;
|
||||
final String subspaceId;
|
||||
|
||||
const UpdateSubSpaceName(
|
||||
{required this.deviceId,
|
||||
required this.newSubSpaceName,
|
||||
required this.subspaceId});
|
||||
}
|
||||
|
@ -57,6 +57,16 @@ class Status {
|
||||
};
|
||||
}
|
||||
|
||||
Status copyWith({
|
||||
String? code,
|
||||
dynamic value,
|
||||
}) {
|
||||
return Status(
|
||||
code: code ?? this.code,
|
||||
value: value ?? this.value,
|
||||
);
|
||||
}
|
||||
|
||||
factory Status.fromJson(String source) => Status.fromMap(json.decode(source));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
@ -44,4 +44,20 @@ class DeviceSubspace {
|
||||
static List<Map<String, dynamic>> listToJson(List<DeviceSubspace> subspaces) {
|
||||
return subspaces.map((subspace) => subspace.toJson()).toList();
|
||||
}
|
||||
|
||||
DeviceSubspace copyWith({
|
||||
String? uuid,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
String? subspaceName,
|
||||
bool? disabled,
|
||||
}) {
|
||||
return DeviceSubspace(
|
||||
uuid: uuid ?? this.uuid,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
subspaceName: subspaceName ?? this.subspaceName,
|
||||
disabled: disabled ?? this.disabled,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -588,4 +588,72 @@ SOS
|
||||
"NCPS": DeviceType.NCPS,
|
||||
"PC": DeviceType.PC,
|
||||
};
|
||||
|
||||
AllDevicesModel copyWith({
|
||||
DevicesModelRoom? room,
|
||||
DeviceSubspace? subspace,
|
||||
DevicesModelUnit? unit,
|
||||
DeviceCommunityModel? community,
|
||||
String? productUuid,
|
||||
String? productType,
|
||||
String? permissionType,
|
||||
int? activeTime,
|
||||
String? category,
|
||||
String? categoryName,
|
||||
int? createTime,
|
||||
String? gatewayId,
|
||||
String? icon,
|
||||
String? ip,
|
||||
String? lat,
|
||||
String? localKey,
|
||||
String? lon,
|
||||
String? model,
|
||||
String? name,
|
||||
String? nodeId,
|
||||
bool? online,
|
||||
String? ownerId,
|
||||
bool? sub,
|
||||
String? timeZone,
|
||||
int? updateTime,
|
||||
String? uuid,
|
||||
int? batteryLevel,
|
||||
String? productName,
|
||||
List<DeviceSpaceModel>? spaces,
|
||||
List<DeviceTagModel>? deviceTags,
|
||||
DeviceSubSpace? deviceSubSpace,
|
||||
}) {
|
||||
return AllDevicesModel(
|
||||
room: room ?? this.room,
|
||||
subspace: subspace ?? this.subspace,
|
||||
unit: unit ?? this.unit,
|
||||
community: community ?? this.community,
|
||||
productUuid: productUuid ?? this.productUuid,
|
||||
productType: productType ?? this.productType,
|
||||
permissionType: permissionType ?? this.permissionType,
|
||||
activeTime: activeTime ?? this.activeTime,
|
||||
category: category ?? this.category,
|
||||
categoryName: categoryName ?? this.categoryName,
|
||||
createTime: createTime ?? this.createTime,
|
||||
gatewayId: gatewayId ?? this.gatewayId,
|
||||
icon: icon ?? this.icon,
|
||||
ip: ip ?? this.ip,
|
||||
lat: lat ?? this.lat,
|
||||
localKey: localKey ?? this.localKey,
|
||||
lon: lon ?? this.lon,
|
||||
model: model ?? this.model,
|
||||
name: name ?? this.name,
|
||||
nodeId: nodeId ?? this.nodeId,
|
||||
online: online ?? this.online,
|
||||
ownerId: ownerId ?? this.ownerId,
|
||||
sub: sub ?? this.sub,
|
||||
timeZone: timeZone ?? this.timeZone,
|
||||
updateTime: updateTime ?? this.updateTime,
|
||||
uuid: uuid ?? this.uuid,
|
||||
batteryLevel: batteryLevel ?? this.batteryLevel,
|
||||
productName: productName ?? this.productName,
|
||||
spaces: spaces ?? this.spaces,
|
||||
deviceTags: deviceTags ?? this.deviceTags,
|
||||
deviceSubSpace: deviceSubSpace ?? this.deviceSubSpace,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
||||
buildWhen: (previous, current) => previous != current,
|
||||
builder: (context, state) {
|
||||
List<AllDevicesModel> devicesToShow = [];
|
||||
int selectedIndex = 0;
|
||||
@ -31,7 +32,6 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
int lowBatteryCount = 0;
|
||||
bool isControlButtonEnabled = false;
|
||||
List<AllDevicesModel> selectedDevices = [];
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
devicesToShow = state.devices;
|
||||
selectedIndex = state.selectedIndex;
|
||||
@ -111,6 +111,8 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
onPressed: isControlButtonEnabled
|
||||
? () {
|
||||
if (isAnyDeviceOffline) {
|
||||
ScaffoldMessenger.of(context)
|
||||
.clearSnackBars();
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(
|
||||
const SnackBar(
|
||||
@ -190,7 +192,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
'Product Name',
|
||||
'Device ID',
|
||||
'Space Name',
|
||||
'location',
|
||||
'Location',
|
||||
'Battery Level',
|
||||
'Installation Date and Time',
|
||||
'Status',
|
||||
@ -242,7 +244,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
.map((device) => device.uuid!)
|
||||
.toList(),
|
||||
isEmpty: devicesToShow.isEmpty,
|
||||
onSettingsPressed: (rowIndex) {
|
||||
onSettingsPressed: (rowIndex) async {
|
||||
final device = devicesToShow[rowIndex];
|
||||
showDeviceSettingsSidebar(context, device);
|
||||
},
|
||||
@ -264,7 +266,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
barrierDismissible: true,
|
||||
barrierLabel: "Device Settings",
|
||||
transitionDuration: const Duration(milliseconds: 300),
|
||||
pageBuilder: (context, anim1, anim2) {
|
||||
pageBuilder: (_, anim1, anim2) {
|
||||
return Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Material(
|
||||
@ -274,6 +276,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
child: DeviceSettingsPanel(
|
||||
device: device,
|
||||
onClose: () => Navigator.of(context).pop(),
|
||||
deviceManagementBloc: context.read<DeviceManagementBloc>(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_m
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class AccurteCalibratingDialog extends StatelessWidget {
|
||||
final String deviceId;
|
||||
@ -17,14 +18,15 @@ class AccurteCalibratingDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(_) {
|
||||
return AlertDialog(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: AccurateDialogWidget(
|
||||
title: 'Calibrating',
|
||||
body: const NormalTextBodyForDialog(
|
||||
title: '',
|
||||
step1:
|
||||
'1. Click Close Button to make the Curtain run to Full Close and Position.',
|
||||
step2: '2. click Next to complete the Calibration.',
|
||||
'Click Close Button to make the Curtain run to Full Close and Position.',
|
||||
step2: 'click Next to complete the Calibration.',
|
||||
),
|
||||
leftOnTap: () => Navigator.of(parentContext).pop(),
|
||||
rightOnTap: () {
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class AccurateCalibrationDialog extends StatelessWidget {
|
||||
final String deviceId;
|
||||
@ -15,13 +16,14 @@ class AccurateCalibrationDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(_) {
|
||||
return AlertDialog(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: AccurateDialogWidget(
|
||||
title: 'Accurate Calibration',
|
||||
body: const NormalTextBodyForDialog(
|
||||
title: 'Prepare Calibration:',
|
||||
step1: '1. Run The Curtain to the Fully Open Position,and pause.',
|
||||
step2: '2. click Next to Start accurate calibration.',
|
||||
step1: 'Run The Curtain to the Fully Open Position,and pause.',
|
||||
step2: 'click Next to Start accurate calibration.',
|
||||
),
|
||||
leftOnTap: () => Navigator.of(parentContext).pop(),
|
||||
rightOnTap: () {
|
||||
|
@ -17,40 +17,52 @@ class AccurateDialogWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 300,
|
||||
width: 400,
|
||||
height: 250,
|
||||
width: 500,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorsManager.blueColor,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
const Divider(
|
||||
indent: 10,
|
||||
endIndent: 10,
|
||||
indent: 60,
|
||||
endIndent: 60,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: body,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Spacer(),
|
||||
const Divider(),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
const Expanded(child: Divider()),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(26),
|
||||
),
|
||||
onTap: leftOnTap,
|
||||
child: Container(
|
||||
height: 60,
|
||||
height: 40,
|
||||
alignment: Alignment.center,
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
@ -58,6 +70,9 @@ class AccurateDialogWidget extends StatelessWidget {
|
||||
color: ColorsManager.grayBorder,
|
||||
),
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(26),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Cancel',
|
||||
@ -68,9 +83,12 @@ class AccurateDialogWidget extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomRight: Radius.circular(26),
|
||||
),
|
||||
onTap: rightOnTap,
|
||||
child: Container(
|
||||
height: 60,
|
||||
height: 40,
|
||||
alignment: Alignment.center,
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
@ -78,6 +96,9 @@ class AccurateDialogWidget extends StatelessWidget {
|
||||
color: ColorsManager.grayBorder,
|
||||
),
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomRight: Radius.circular(26),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Next',
|
||||
@ -92,6 +113,9 @@ class AccurateDialogWidget extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class CalibrateCompletedDialog extends StatelessWidget {
|
||||
final BuildContext parentContext;
|
||||
@ -21,14 +23,17 @@ class CalibrateCompletedDialog extends StatelessWidget {
|
||||
width: 400,
|
||||
child: Column(
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Text(
|
||||
'Calibration Completed',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorsManager.blueColor,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -37,12 +42,16 @@ class CalibrateCompletedDialog extends StatelessWidget {
|
||||
indent: 10,
|
||||
endIndent: 10,
|
||||
),
|
||||
const Icon(
|
||||
Icons.check_circle,
|
||||
size: 100,
|
||||
color: ColorsManager.blueColor,
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
),
|
||||
Expanded(
|
||||
child: SvgPicture.asset(Assets.completedDoneIcon),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
const Divider(
|
||||
indent: 10,
|
||||
endIndent: 10,
|
||||
@ -71,6 +80,9 @@ class CalibrateCompletedDialog extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -15,28 +15,72 @@ class NormalTextBodyForDialog extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
return Padding(
|
||||
padding: EdgeInsetsGeometry.only(left: 15),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
if (title.isEmpty)
|
||||
const SizedBox()
|
||||
else
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
const Text('1. ',
|
||||
style: TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 15,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 450,
|
||||
child: Text(
|
||||
step1,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
const Text('2. ',
|
||||
style: TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 15,
|
||||
)),
|
||||
Text(
|
||||
step2,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class NumberInputField extends StatelessWidget {
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontSize: 15,
|
||||
color: ColorsManager.blackColor,
|
||||
),
|
||||
);
|
||||
|
@ -18,7 +18,7 @@ class PrefReversCardWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultContainer(
|
||||
padding: const EdgeInsets.all(12),
|
||||
padding: const EdgeInsets.all(18),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -23,12 +23,12 @@ class CurtainModulePrefrencesDialog extends StatelessWidget {
|
||||
Widget build(_) {
|
||||
return AlertDialog(
|
||||
backgroundColor: ColorsManager.CircleImageBackground,
|
||||
contentPadding: const EdgeInsets.all(30),
|
||||
title: const Center(
|
||||
contentPadding: const EdgeInsets.all(20),
|
||||
title: Center(
|
||||
child: Text(
|
||||
'Preferences',
|
||||
style: TextStyle(
|
||||
color: ColorsManager.blueColor,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
@ -63,37 +63,51 @@ class _QuickCalibratingDialogState extends State<QuickCalibratingDialog> {
|
||||
@override
|
||||
Widget build(_) {
|
||||
return AlertDialog(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: AccurateDialogWidget(
|
||||
title: 'Calibrating',
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'1. please Enter the Travel Time:',
|
||||
style: TextStyle(color: ColorsManager.grayBorder),
|
||||
const Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 75),
|
||||
child: Text(
|
||||
'1.please Enter the Travel Time:',
|
||||
style: TextStyle(color: ColorsManager.lightGrayColor),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: 150,
|
||||
height: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
width: 130,
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
color: ColorsManager.neutralGray.withValues(
|
||||
alpha: 0.5,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: NumberInputField(controller: _controller),
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsGeometry.only(left: 5),
|
||||
child: NumberInputField(controller: _controller)),
|
||||
),
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Text(
|
||||
'seconds',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: ColorsManager.blueColor,
|
||||
fontSize: 12,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@ -101,8 +115,11 @@ class _QuickCalibratingDialogState extends State<QuickCalibratingDialog> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_errorText != null)
|
||||
Padding(
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
_errorText!,
|
||||
@ -112,6 +129,16 @@ class _QuickCalibratingDialogState extends State<QuickCalibratingDialog> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Text(
|
||||
'2.click Next to Complete the calibration',
|
||||
style: TextStyle(color: ColorsManager.lightGrayColor),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
leftOnTap: () => Navigator.of(widget.parentContext).pop(),
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class QuickCalibrationDialog extends StatelessWidget {
|
||||
final int timControl;
|
||||
@ -17,14 +18,15 @@ class QuickCalibrationDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(_) {
|
||||
return AlertDialog(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: AccurateDialogWidget(
|
||||
title: 'Quick Calibration',
|
||||
body: const NormalTextBodyForDialog(
|
||||
title: 'Prepare Calibration:',
|
||||
step1:
|
||||
'1. Confirm that the curtain is in the fully closed and suspended state.',
|
||||
step2: '2. click Next to Start calibration.',
|
||||
'Confirm that the curtain is in the fully closed and suspended state.',
|
||||
step2: 'click Next to Start calibration.',
|
||||
),
|
||||
leftOnTap: () => Navigator.of(parentContext).pop(),
|
||||
rightOnTap: () {
|
||||
|
@ -19,11 +19,14 @@ class DeviceManagementContent extends StatelessWidget {
|
||||
required this.device,
|
||||
required this.subSpaces,
|
||||
required this.deviceInfo,
|
||||
required this.deviceManagementBloc,
|
||||
});
|
||||
|
||||
final AllDevicesModel device;
|
||||
final List<SubSpaceModel> subSpaces;
|
||||
final DeviceInfoModel deviceInfo;
|
||||
final DeviceManagementBloc deviceManagementBloc;
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -87,6 +90,11 @@ class DeviceManagementContent extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
deviceManagementBloc.add(UpdateSubSpaceName(
|
||||
subspaceId: selectedSubSpace.id!,
|
||||
deviceId: device.uuid!,
|
||||
newSubSpaceName: selectedSubSpace.name ?? ''));
|
||||
}
|
||||
},
|
||||
child: infoRow(
|
||||
|
@ -1,13 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_state.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/device_icon_type_helper.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/device_management_content.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/remove_device_widget.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/device_info_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_state.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/sub_space_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
@ -17,7 +19,13 @@ import 'package:syncrow_web/web_layout/default_container.dart';
|
||||
class DeviceSettingsPanel extends StatelessWidget {
|
||||
final VoidCallback? onClose;
|
||||
final AllDevicesModel device;
|
||||
const DeviceSettingsPanel({super.key, this.onClose, required this.device});
|
||||
final DeviceManagementBloc deviceManagementBloc;
|
||||
const DeviceSettingsPanel({
|
||||
super.key,
|
||||
this.onClose,
|
||||
required this.device,
|
||||
required this.deviceManagementBloc,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -134,8 +142,14 @@ class DeviceSettingsPanel extends StatelessWidget {
|
||||
onFieldSubmitted: (value) {
|
||||
_bloc.add(const ChangeNameEvent(
|
||||
value: false));
|
||||
deviceManagementBloc
|
||||
..add(UpdateDeviceName(
|
||||
deviceId: device.uuid!,
|
||||
newName: _bloc
|
||||
.nameController
|
||||
.text))..add(ResetSelectedDevices());
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
decoration:const InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
border: InputBorder.none,
|
||||
@ -190,6 +204,7 @@ class DeviceSettingsPanel extends StatelessWidget {
|
||||
device: device,
|
||||
subSpaces: subSpaces.cast<SubSpaceModel>(),
|
||||
deviceInfo: deviceInfo,
|
||||
deviceManagementBloc: deviceManagementBloc,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
RemoveDeviceWidget(bloc: _bloc),
|
||||
|
@ -286,11 +286,20 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
try {
|
||||
if (state is ScheduleLoaded) {
|
||||
final dateTime = DateTime.parse(event.time);
|
||||
Status status = Status(code: '', value: '');
|
||||
if (event.category == 'CUR_2') {
|
||||
status = status.copyWith(
|
||||
code: 'control',
|
||||
value: event.functionOn == true ? 'open' : 'close');
|
||||
} else {
|
||||
status =
|
||||
status.copyWith(code: event.category, value: event.functionOn);
|
||||
}
|
||||
final updatedSchedule = ScheduleEntry(
|
||||
scheduleId: event.scheduleId,
|
||||
category: event.category,
|
||||
time: getTimeStampWithoutSeconds(dateTime).toString(),
|
||||
function: Status(code: event.category, value: event.functionOn),
|
||||
function: status,
|
||||
days: event.selectedDays,
|
||||
);
|
||||
final success = await DevicesManagementApi().editScheduleRecord(
|
||||
|
@ -52,6 +52,9 @@ class BuildScheduleView extends StatelessWidget {
|
||||
children: [
|
||||
const ScheduleHeader(),
|
||||
const SizedBox(height: 20),
|
||||
if (category == 'CUR_2')
|
||||
const SizedBox()
|
||||
else
|
||||
ScheduleModeSelector(
|
||||
currentMode: state.scheduleMode,
|
||||
),
|
||||
|
@ -212,12 +212,20 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
isEdit: true,
|
||||
).then((updatedSchedule) {
|
||||
if (updatedSchedule != null) {
|
||||
bool temp;
|
||||
if (schedule.category == 'CUR_2') {
|
||||
updatedSchedule.function.value == 'open'
|
||||
? temp = true
|
||||
: temp = false;
|
||||
} else {
|
||||
temp = updatedSchedule.function.value;
|
||||
}
|
||||
context.read<ScheduleBloc>().add(
|
||||
ScheduleEditEvent(
|
||||
scheduleId: schedule.scheduleId,
|
||||
category: schedule.category,
|
||||
time: updatedSchedule.time,
|
||||
functionOn: updatedSchedule.function.value,
|
||||
functionOn: temp,
|
||||
selectedDays: updatedSchedule.days),
|
||||
);
|
||||
}
|
||||
|
@ -58,7 +58,9 @@ class CurtainHelper {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const DialogHeader('AC Functions'),
|
||||
DialogHeader(dialogType == 'THEN'
|
||||
? 'Curtain Functions'
|
||||
: 'Curtain Conditions'),
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -58,11 +58,14 @@ class ProductModel {
|
||||
'3G': Assets.Gang3SwitchIcon,
|
||||
'3GT': Assets.threeTouchSwitch,
|
||||
'CUR': Assets.curtain,
|
||||
'CUR_2': Assets.curtain,
|
||||
'GD': Assets.garageDoor,
|
||||
'GW': Assets.SmartGatewayIcon,
|
||||
'DL': Assets.DoorLockIcon,
|
||||
'WL': Assets.waterLeakSensor,
|
||||
'WH': Assets.waterHeater,
|
||||
'WM': Assets.waterLeakSensor,
|
||||
'SOS': Assets.sos,
|
||||
'AC': Assets.ac,
|
||||
'CPS': Assets.presenceSensor,
|
||||
'PC': Assets.powerClamp,
|
||||
|
@ -2,10 +2,8 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
||||
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||
@ -23,8 +21,8 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
var text = Theme.of(context)
|
||||
final size = MediaQuery.of(context).size;
|
||||
final text = Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(color: Colors.black, fontSize: 13);
|
||||
@ -41,8 +39,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
title: 'Sent Successfully',
|
||||
widgeta: Column(
|
||||
children: [
|
||||
if (visitorBloc
|
||||
.passwordStatus!.failedOperations.isNotEmpty)
|
||||
if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
const Text('Failed Devices'),
|
||||
@ -56,22 +53,19 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
.passwordStatus!.failedOperations.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
margin: EdgeInsets.all(5),
|
||||
margin: const EdgeInsets.all(5),
|
||||
decoration: containerDecoration,
|
||||
height: 45,
|
||||
child: Center(
|
||||
child: Text(visitorBloc
|
||||
.passwordStatus!
|
||||
.failedOperations[index]
|
||||
.deviceName)),
|
||||
child: Text(visitorBloc.passwordStatus!
|
||||
.failedOperations[index].deviceName)),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (visitorBloc
|
||||
.passwordStatus!.successOperations.isNotEmpty)
|
||||
if (visitorBloc.passwordStatus!.successOperations.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
const Text('Success Devices'),
|
||||
@ -85,14 +79,12 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
.passwordStatus!.successOperations.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
margin: EdgeInsets.all(5),
|
||||
margin: const EdgeInsets.all(5),
|
||||
decoration: containerDecoration,
|
||||
height: 45,
|
||||
child: Center(
|
||||
child: Text(visitorBloc
|
||||
.passwordStatus!
|
||||
.successOperations[index]
|
||||
.deviceName)),
|
||||
child: Text(visitorBloc.passwordStatus!
|
||||
.successOperations[index].deviceName)),
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -115,16 +107,14 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||
builder: (BuildContext context, VisitorPasswordState state) {
|
||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||
bool isRepeat =
|
||||
final isRepeat =
|
||||
state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
title: Text(
|
||||
'Create visitor password',
|
||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 24,
|
||||
color: Colors.black),
|
||||
fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black),
|
||||
),
|
||||
content: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
@ -310,11 +300,9 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password') {
|
||||
visitorBloc.add(SelectTimeEvent(
|
||||
context: context,
|
||||
isEffective: false));
|
||||
context: context, isEffective: false));
|
||||
} else {
|
||||
visitorBloc.add(
|
||||
SelectTimeVisitorPassword(
|
||||
visitorBloc.add(SelectTimeVisitorPassword(
|
||||
context: context,
|
||||
isStart: false,
|
||||
isRepeat: false));
|
||||
@ -326,31 +314,28 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password') {
|
||||
visitorBloc.add(SelectTimeEvent(
|
||||
context: context,
|
||||
isEffective: true));
|
||||
context: context, isEffective: true));
|
||||
} else {
|
||||
visitorBloc.add(
|
||||
SelectTimeVisitorPassword(
|
||||
visitorBloc.add(SelectTimeVisitorPassword(
|
||||
context: context,
|
||||
isStart: true,
|
||||
isRepeat: false));
|
||||
}
|
||||
},
|
||||
firstString: (visitorBloc
|
||||
.usageFrequencySelected ==
|
||||
firstString:
|
||||
(visitorBloc.usageFrequencySelected ==
|
||||
'Periodic' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password')
|
||||
? visitorBloc.effectiveTime
|
||||
: visitorBloc.startTimeAccess
|
||||
.toString(),
|
||||
: visitorBloc.startTimeAccess,
|
||||
secondString: (visitorBloc
|
||||
.usageFrequencySelected ==
|
||||
'Periodic' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password')
|
||||
? visitorBloc.expirationTime
|
||||
: visitorBloc.endTimeAccess.toString(),
|
||||
: visitorBloc.endTimeAccess,
|
||||
icon: Assets.calendarIcon),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
@ -410,8 +395,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
child: CupertinoSwitch(
|
||||
value: visitorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
visitorBloc
|
||||
.add(ToggleRepeatEvent());
|
||||
visitorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
@ -442,8 +426,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
},
|
||||
).then((listDevice) {
|
||||
if (listDevice != null) {
|
||||
visitorBloc.selectedDevices =
|
||||
listDevice;
|
||||
visitorBloc.selectedDevices = listDevice;
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -455,8 +438,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
.bodySmall!
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color:
|
||||
ColorsManager.whiteColors,
|
||||
color: ColorsManager.whiteColors,
|
||||
fontSize: 12),
|
||||
),
|
||||
),
|
||||
@ -495,37 +477,30 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
onPressed: () {
|
||||
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||
if (visitorBloc.selectedDevices.isNotEmpty) {
|
||||
if (visitorBloc.usageFrequencySelected ==
|
||||
'One-Time' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password') {
|
||||
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
setPasswordFunction(context, size, visitorBloc);
|
||||
} else if (visitorBloc.usageFrequencySelected ==
|
||||
'Periodic' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password') {
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
if (visitorBloc.expirationTime != 'End Time' &&
|
||||
visitorBloc.effectiveTime != 'Start Time') {
|
||||
setPasswordFunction(context, size, visitorBloc);
|
||||
} else {
|
||||
visitorBloc.stateDialog(
|
||||
context: context,
|
||||
message:
|
||||
'Please select Access Period to continue',
|
||||
message: 'Please select Access Period to continue',
|
||||
title: 'Access Period');
|
||||
}
|
||||
} else if (visitorBloc.endTimeAccess.toString() !=
|
||||
'End Time' &&
|
||||
visitorBloc.startTimeAccess.toString() !=
|
||||
'Start Time') {
|
||||
} else if (visitorBloc.endTimeAccess != 'End Time' &&
|
||||
visitorBloc.startTimeAccess != 'Start Time') {
|
||||
if (visitorBloc.effectiveTimeTimeStamp != null &&
|
||||
visitorBloc.expirationTimeTimeStamp != null) {
|
||||
if (isRepeat == true) {
|
||||
if (visitorBloc.expirationTime != 'End Time' &&
|
||||
visitorBloc.effectiveTime != 'Start Time' &&
|
||||
visitorBloc.selectedDays.isNotEmpty) {
|
||||
setPasswordFunction(
|
||||
context, size, visitorBloc);
|
||||
setPasswordFunction(context, size, visitorBloc);
|
||||
} else {
|
||||
visitorBloc.stateDialog(
|
||||
context: context,
|
||||
@ -539,15 +514,13 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
} else {
|
||||
visitorBloc.stateDialog(
|
||||
context: context,
|
||||
message:
|
||||
'Please select Access Period to continue',
|
||||
message: 'Please select Access Period to continue',
|
||||
title: 'Access Period');
|
||||
}
|
||||
} else {
|
||||
visitorBloc.stateDialog(
|
||||
context: context,
|
||||
message:
|
||||
'Please select Access Period to continue',
|
||||
message: 'Please select Access Period to continue',
|
||||
title: 'Access Period');
|
||||
}
|
||||
} else {
|
||||
@ -593,17 +566,17 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
alignment: Alignment.center,
|
||||
content: SizedBox(
|
||||
height: size.height * 0.25,
|
||||
child: Center(
|
||||
child:
|
||||
CircularProgressIndicator(), // Display a loading spinner
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(), // Display a loading spinner
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return AlertDialog(
|
||||
alignment: Alignment.center,
|
||||
backgroundColor: Colors.white,
|
||||
content: SizedBox(
|
||||
height: size.height * 0.25,
|
||||
height: size.height * 0.13,
|
||||
child: Column(
|
||||
children: [
|
||||
Column(
|
||||
@ -617,13 +590,16 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
width: 35,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
'Set Password',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headlineLarge!
|
||||
.copyWith(
|
||||
fontSize: 30,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
),
|
||||
@ -631,15 +607,6 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -668,12 +635,12 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.1,
|
||||
child: DefaultButton(
|
||||
backgroundColor: Color(0xff023DFE),
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Online Password') {
|
||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||
visitorBloc.add(OnlineOneTimePasswordEvent(
|
||||
context: context,
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
@ -681,8 +648,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected ==
|
||||
'Periodic' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Online Password') {
|
||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
@ -693,8 +659,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected ==
|
||||
'One-Time' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password') {
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
visitorBloc.add(OfflineOneTimePasswordEvent(
|
||||
context: context,
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
@ -702,8 +667,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected ==
|
||||
'Periodic' &&
|
||||
visitorBloc.accessTypeSelected ==
|
||||
'Offline Password') {
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
visitorBloc.add(OfflineMultipleTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
@ -715,7 +679,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'Ok',
|
||||
'Confirm',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,
|
||||
|
@ -416,4 +416,5 @@ class DevicesManagementApi {
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -84,6 +84,4 @@ abstract class ColorsManager {
|
||||
static const Color minBlue = Color(0xFF93AAFD);
|
||||
static const Color minBlueDot = Color(0xFF023DFE);
|
||||
static const Color grey25 = Color(0xFFF9F9F9);
|
||||
|
||||
|
||||
}
|
||||
|
@ -14,8 +14,7 @@ class Assets {
|
||||
static const String rightLine = 'assets/images/right_line.png';
|
||||
static const String google = 'assets/images/google.svg';
|
||||
static const String facebook = 'assets/images/facebook.svg';
|
||||
static const String invisiblePassword =
|
||||
'assets/images/Password_invisible.svg';
|
||||
static const String invisiblePassword = 'assets/images/Password_invisible.svg';
|
||||
static const String visiblePassword = 'assets/images/password_visible.svg';
|
||||
static const String accessIcon = 'assets/images/access_icon.svg';
|
||||
static const String spaseManagementIcon =
|
||||
@ -34,8 +33,7 @@ class Assets {
|
||||
static const String emptyTable = 'assets/images/empty_table.svg';
|
||||
|
||||
// General assets
|
||||
static const String motionlessDetection =
|
||||
'assets/icons/motionless_detection.svg';
|
||||
static const String motionlessDetection = 'assets/icons/motionless_detection.svg';
|
||||
static const String acHeating = 'assets/icons/ac_heating.svg';
|
||||
static const String acPowerOff = 'assets/icons/ac_power_off.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';
|
||||
static const String doorlockNormalOpen =
|
||||
'assets/icons/automation_functions/doorlock_normal_open.svg';
|
||||
static const String doorbell =
|
||||
'assets/icons/automation_functions/doorbell.svg';
|
||||
static const String doorbell = 'assets/icons/automation_functions/doorbell.svg';
|
||||
static const String remoteUnlockViaApp =
|
||||
'assets/icons/automation_functions/remote_unlock_via_app.svg';
|
||||
static const String doubleLock =
|
||||
'assets/icons/automation_functions/double_lock.svg';
|
||||
static const String selfTestResult =
|
||||
'assets/icons/automation_functions/self_test_result.svg';
|
||||
static const String lockAlarm =
|
||||
'assets/icons/automation_functions/lock_alarm.svg';
|
||||
static const String lockAlarm = 'assets/icons/automation_functions/lock_alarm.svg';
|
||||
static const String presenceState =
|
||||
'assets/icons/automation_functions/presence_state.svg';
|
||||
static const String currentTemp =
|
||||
'assets/icons/automation_functions/current_temp.svg';
|
||||
static const String presence =
|
||||
'assets/icons/automation_functions/presence.svg';
|
||||
static const String presence = 'assets/icons/automation_functions/presence.svg';
|
||||
static const String residualElectricity =
|
||||
'assets/icons/automation_functions/residual_electricity.svg';
|
||||
static const String hijackAlarm =
|
||||
@ -104,15 +99,12 @@ class Assets {
|
||||
|
||||
// Presence Sensor Assets
|
||||
static const String sensorMotionIcon = 'assets/icons/sensor_motion_ic.svg';
|
||||
static const String sensorPresenceIcon =
|
||||
'assets/icons/sensor_presence_ic.svg';
|
||||
static const String sensorPresenceIcon = 'assets/icons/sensor_presence_ic.svg';
|
||||
static const String sensorVacantIcon = 'assets/icons/sensor_vacant_ic.svg';
|
||||
static const String illuminanceRecordIcon =
|
||||
'assets/icons/illuminance_record_ic.svg';
|
||||
static const String presenceRecordIcon =
|
||||
'assets/icons/presence_record_ic.svg';
|
||||
static const String helpDescriptionIcon =
|
||||
'assets/icons/help_description_ic.svg';
|
||||
static const String presenceRecordIcon = 'assets/icons/presence_record_ic.svg';
|
||||
static const String helpDescriptionIcon = 'assets/icons/help_description_ic.svg';
|
||||
|
||||
static const String lightPulp = 'assets/icons/light_pulb.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 villa = 'assets/icons/villa_icon.svg';
|
||||
static const String iconEdit = 'assets/icons/icon_edit_icon.svg';
|
||||
static const String textFieldSearch =
|
||||
'assets/icons/textfield_search_icon.svg';
|
||||
static const String textFieldSearch = 'assets/icons/textfield_search_icon.svg';
|
||||
static const String roundedAddIcon = 'assets/icons/rounded_add_icon.svg';
|
||||
static const String addIcon = 'assets/icons/add_icon.svg';
|
||||
static const String smartThermostatIcon =
|
||||
'assets/icons/smart_thermostat_icon.svg';
|
||||
static const String smartThermostatIcon = 'assets/icons/smart_thermostat_icon.svg';
|
||||
static const String smartLightIcon = 'assets/icons/smart_light_icon.svg';
|
||||
static const String presenceSensor = 'assets/icons/presence_sensor.svg';
|
||||
static const String Gang3SwitchIcon = 'assets/icons/3_Gang_switch_icon.svg';
|
||||
@ -219,8 +209,7 @@ class Assets {
|
||||
//assets/icons/water_leak_normal.svg
|
||||
static const String waterLeakNormal = 'assets/icons/water_leak_normal.svg';
|
||||
//assets/icons/water_leak_detected.svg
|
||||
static const String waterLeakDetected =
|
||||
'assets/icons/water_leak_detected.svg';
|
||||
static const String waterLeakDetected = 'assets/icons/water_leak_detected.svg';
|
||||
|
||||
//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';
|
||||
static const String assetsSensitivityOperationIcon =
|
||||
'assets/icons/functions_icons/sesitivity_operation_icon.svg';
|
||||
static const String assetsAcPower =
|
||||
'assets/icons/functions_icons/ac_power.svg';
|
||||
static const String assetsAcPower = 'assets/icons/functions_icons/ac_power.svg';
|
||||
static const String assetsAcPowerOFF =
|
||||
'assets/icons/functions_icons/ac_power_off.svg';
|
||||
static const String assetsChildLock =
|
||||
'assets/icons/functions_icons/child_lock.svg';
|
||||
static const String assetsFreezing =
|
||||
'assets/icons/functions_icons/freezing.svg';
|
||||
static const String assetsFanSpeed =
|
||||
'assets/icons/functions_icons/fan_speed.svg';
|
||||
static const String assetsFreezing = 'assets/icons/functions_icons/freezing.svg';
|
||||
static const String assetsFanSpeed = 'assets/icons/functions_icons/fan_speed.svg';
|
||||
static const String assetsAcCooling =
|
||||
'assets/icons/functions_icons/ac_cooling.svg';
|
||||
static const String assetsAcHeating =
|
||||
@ -309,8 +295,7 @@ class Assets {
|
||||
'assets/icons/functions_icons/celsius_degrees.svg';
|
||||
static const String assetsTempreture =
|
||||
'assets/icons/functions_icons/tempreture.svg';
|
||||
static const String assetsAcFanLow =
|
||||
'assets/icons/functions_icons/ac_fan_low.svg';
|
||||
static const String assetsAcFanLow = 'assets/icons/functions_icons/ac_fan_low.svg';
|
||||
static const String assetsAcFanMiddle =
|
||||
'assets/icons/functions_icons/ac_fan_middle.svg';
|
||||
static const String assetsAcFanHigh =
|
||||
@ -329,8 +314,7 @@ class Assets {
|
||||
'assets/icons/functions_icons/far_detection.svg';
|
||||
static const String assetsFarDetectionFunction =
|
||||
'assets/icons/functions_icons/far_detection_function.svg';
|
||||
static const String assetsIndicator =
|
||||
'assets/icons/functions_icons/indicator.svg';
|
||||
static const String assetsIndicator = 'assets/icons/functions_icons/indicator.svg';
|
||||
static const String assetsMotionDetection =
|
||||
'assets/icons/functions_icons/motion_detection.svg';
|
||||
static const String assetsMotionlessDetection =
|
||||
@ -343,8 +327,7 @@ class Assets {
|
||||
'assets/icons/functions_icons/master_state.svg';
|
||||
static const String assetsSwitchAlarmSound =
|
||||
'assets/icons/functions_icons/switch_alarm_sound.svg';
|
||||
static const String assetsResetOff =
|
||||
'assets/icons/functions_icons/reset_off.svg';
|
||||
static const String assetsResetOff = 'assets/icons/functions_icons/reset_off.svg';
|
||||
|
||||
// Assets for automation_functions
|
||||
static const String assetsCardUnlock =
|
||||
@ -388,14 +371,13 @@ class Assets {
|
||||
static const String activeUser = 'assets/icons/active_user.svg';
|
||||
static const String deActiveUser = 'assets/icons/deactive_user.svg';
|
||||
static const String invitedIcon = 'assets/icons/invited_icon.svg';
|
||||
static const String rectangleCheckBox =
|
||||
'assets/icons/rectangle_check_box.png';
|
||||
static const String rectangleCheckBox = 'assets/icons/rectangle_check_box.png';
|
||||
static const String CheckBoxChecked = 'assets/icons/box_checked.png';
|
||||
static const String emptyBox = 'assets/icons/empty_box.png';
|
||||
static const String completeProcessIcon =
|
||||
'assets/icons/compleate_process_icon.svg';
|
||||
static const String currentProcessIcon =
|
||||
'assets/icons/current_process_icon.svg';
|
||||
static const String completedDoneIcon = 'assets/images/completed_done.svg';
|
||||
static const String currentProcessIcon = 'assets/icons/current_process_icon.svg';
|
||||
static const String uncomplete_ProcessIcon =
|
||||
'assets/icons/uncompleate_process_icon.svg';
|
||||
static const String wrongProcessIcon = 'assets/icons/wrong_process_icon.svg';
|
||||
@ -416,11 +398,9 @@ class Assets {
|
||||
static const String successIcon = 'assets/icons/success_icon.svg';
|
||||
static const String spaceLocationIcon = 'assets/icons/spaseLocationIcon.svg';
|
||||
static const String scenesPlayIcon = 'assets/icons/scenesPlayIcon.png';
|
||||
static const String scenesPlayIconCheck =
|
||||
'assets/icons/scenesPlayIconCheck.png';
|
||||
static const String scenesPlayIconCheck = 'assets/icons/scenesPlayIconCheck.png';
|
||||
static const String presenceStateIcon = 'assets/icons/presence_state.svg';
|
||||
static const String currentDistanceIcon =
|
||||
'assets/icons/current_distance_icon.svg';
|
||||
static const String currentDistanceIcon = 'assets/icons/current_distance_icon.svg';
|
||||
|
||||
static const String farDetectionIcon = 'assets/icons/far_detection_icon.svg';
|
||||
static const String motionDetectionSensitivityIcon =
|
||||
@ -443,44 +423,29 @@ class Assets {
|
||||
static const String cpsMode4 = 'assets/icons/cps_mode4.svg';
|
||||
static const String closeToMotion = 'assets/icons/close_to_motion.svg';
|
||||
static const String farAwayMotion = 'assets/icons/far_away_motion.svg';
|
||||
static const String communicationFault =
|
||||
'assets/icons/communication_fault.svg';
|
||||
static const String communicationFault = 'assets/icons/communication_fault.svg';
|
||||
static const String radarFault = 'assets/icons/radar_fault.svg';
|
||||
static const String selfTestingSuccess =
|
||||
'assets/icons/self_testing_success.svg';
|
||||
static const String selfTestingFailure =
|
||||
'assets/icons/self_testing_failure.svg';
|
||||
static const String selfTestingTimeout =
|
||||
'assets/icons/self_testing_timeout.svg';
|
||||
static const String selfTestingSuccess = 'assets/icons/self_testing_success.svg';
|
||||
static const String selfTestingFailure = '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 boundary = 'assets/icons/boundary.svg';
|
||||
static const String motionMeter = 'assets/icons/motion_meter.svg';
|
||||
static const String spatialStaticValue =
|
||||
'assets/icons/spatial_static_value.svg';
|
||||
static const String spatialMotionValue =
|
||||
'assets/icons/spatial_motion_value.svg';
|
||||
static const String spatialStaticValue = 'assets/icons/spatial_static_value.svg';
|
||||
static const String spatialMotionValue = 'assets/icons/spatial_motion_value.svg';
|
||||
static const String presenceJudgementThrshold =
|
||||
'assets/icons/presence_judgement_threshold.svg';
|
||||
static const String spaceType = 'assets/icons/space_type.svg';
|
||||
static const String sportsPara = 'assets/icons/sports_para.svg';
|
||||
static const String sensitivityFeature1 =
|
||||
'assets/icons/sensitivity_feature_1.svg';
|
||||
static const String sensitivityFeature2 =
|
||||
'assets/icons/sensitivity_feature_2.svg';
|
||||
static const String sensitivityFeature3 =
|
||||
'assets/icons/sensitivity_feature_3.svg';
|
||||
static const String sensitivityFeature4 =
|
||||
'assets/icons/sensitivity_feature_4.svg';
|
||||
static const String sensitivityFeature5 =
|
||||
'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 sensitivityFeature1 = 'assets/icons/sensitivity_feature_1.svg';
|
||||
static const String sensitivityFeature2 = 'assets/icons/sensitivity_feature_2.svg';
|
||||
static const String sensitivityFeature3 = 'assets/icons/sensitivity_feature_3.svg';
|
||||
static const String sensitivityFeature4 = 'assets/icons/sensitivity_feature_4.svg';
|
||||
static const String sensitivityFeature5 = '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 targetConfirmTimeIcon =
|
||||
'assets/icons/target_confirm_time_icon.svg';
|
||||
@ -488,13 +453,10 @@ class Assets {
|
||||
static const String indentLevelIcon = 'assets/icons/indent_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 refreshStatusIcon =
|
||||
'assets/icons/refresh_status_icon.svg';
|
||||
static const String energyConsumedIcon =
|
||||
'assets/icons/energy_consumed_icon.svg';
|
||||
static const String refreshStatusIcon = 'assets/icons/refresh_status_icon.svg';
|
||||
static const String energyConsumedIcon = 'assets/icons/energy_consumed_icon.svg';
|
||||
|
||||
static const String closeSettingsIcon =
|
||||
'assets/icons/close_settings_icon.svg';
|
||||
static const String closeSettingsIcon = 'assets/icons/close_settings_icon.svg';
|
||||
|
||||
static const String editNameIconSettings =
|
||||
'assets/icons/edit_name_icon_settings.svg';
|
||||
@ -505,5 +467,13 @@ class Assets {
|
||||
static const String aqiAirQuality = 'assets/icons/aqi_air_quality.svg';
|
||||
static const String temperatureAqiSidebar = 'assets/icons/thermometer.svg';
|
||||
static const String humidityAqiSidebar = 'assets/icons/humidity.svg';
|
||||
static const String autocadOccupancyImage = 'assets/images/autocad_occupancy_image.png';
|
||||
static const String autocadOccupancyImage =
|
||||
'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';
|
||||
}
|
||||
|
Reference in New Issue
Block a user