mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-11-26 23:54:55 +00:00
Compare commits
16 Commits
garage_wat
...
access_bug
| Author | SHA1 | Date | |
|---|---|---|---|
| 3102c3823a | |||
| d5395f4fe7 | |||
| 13e90abf76 | |||
| 308c8a44c5 | |||
| 7ca6e60d02 | |||
| 853cccbcce | |||
| 03dfeabde4 | |||
| 62e03bac27 | |||
| 79ec890244 | |||
| 4653c519c4 | |||
| 66f6b1cba9 | |||
| c06f3d5a58 | |||
| 813f2f2693 | |||
| d05328e998 | |||
| ab22e15736 | |||
| 889d3dbd02 |
5
assets/icons/1gang.svg
Normal file
5
assets/icons/1gang.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M38.0142 39.2553L35.3682 40H20.9308H19.9999H19.0691H1.24111C0.555643 40 0 39.4444 0 38.7589V1.24111C0 0.555643 0.555643 0 1.24111 0H19.0682H20.1226H20.9543H35.4255L38.2625 1.24111C38.9479 1.24111 39.5036 1.79675 39.5036 2.48221L39.2553 38.0142C39.2553 38.6997 38.6997 39.2553 38.0142 39.2553Z" fill="#E9E9E9"/>
|
||||||
|
<path d="M38.7589 0H35.0356C35.721 0 36.2767 0.555643 36.2767 1.24111V38.7589C36.2767 39.4444 35.721 40 35.0356 40H38.7589C39.4444 40 40 39.4444 40 38.7589V1.24111C40 0.555643 39.4444 0 38.7589 0Z" fill="#D1D1D1"/>
|
||||||
|
<path opacity="0.6" d="M21.375 31.8319V33.3213C21.375 34.0067 20.9553 34.5624 20.4375 34.5624H16.3125C15.7947 34.5624 15.375 34.0067 15.375 33.3213V31.8319C15.375 31.1465 15.7947 30.5908 16.3125 30.5908H20.4375C20.9553 30.5908 21.375 31.1465 21.375 31.8319Z" fill="#023DFE" fill-opacity="0.5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 933 B |
7
assets/icons/2gang.svg
Normal file
7
assets/icons/2gang.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M38.0142 39.2553L35.3682 40H20.9308H19.9999H19.0691H1.24111C0.555643 40 0 39.4444 0 38.7589V1.24111C0 0.555643 0.555643 0 1.24111 0H19.0682H20.1226H20.9543H35.4255L38.2625 1.24111C38.9479 1.24111 39.5036 1.79675 39.5036 2.48221L39.2553 38.0142C39.2553 38.6997 38.6997 39.2553 38.0142 39.2553Z" fill="#E9E9E9"/>
|
||||||
|
<path d="M38.7589 0H35.0356C35.721 0 36.2767 0.555643 36.2767 1.24111V38.7589C36.2767 39.4444 35.721 40 35.0356 40H38.7589C39.4444 40 40 39.4444 40 38.7589V1.24111C40 0.555643 39.4444 0 38.7589 0Z" fill="#D1D1D1"/>
|
||||||
|
<path opacity="0.6" d="M12.0284 31.8319V33.3213C12.0284 34.0067 11.6087 34.5624 11.0909 34.5624H6.96594C6.44816 34.5624 6.02844 34.0067 6.02844 33.3213V31.8319C6.02844 31.1465 6.44816 30.5908 6.96594 30.5908H11.0909C11.6087 30.5908 12.0284 31.1465 12.0284 31.8319Z" fill="#023DFE" fill-opacity="0.5"/>
|
||||||
|
<path opacity="0.6" d="M26.0285 31.8319V33.3213C26.0285 34.0067 26.4482 34.5624 26.966 34.5624H31.091C31.6088 34.5624 32.0285 34.0067 32.0285 33.3213V31.8319C32.0285 31.1465 31.6088 30.5908 31.091 30.5908H26.966C26.4482 30.5908 26.0285 31.1465 26.0285 31.8319Z" fill="#023DFE" fill-opacity="0.5"/>
|
||||||
|
<path d="M19.0691 0H20.9308V40H19.0691V0Z" fill="#D1D1D1"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -5,7 +5,6 @@ import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
|||||||
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
||||||
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
||||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
@ -64,13 +63,15 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> selectTime(
|
||||||
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit,) async {
|
SelectTime event,
|
||||||
|
Emitter<AccessState> emit,
|
||||||
|
) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
firstDate: DateTime.now().add(const Duration(days: -5095)),
|
firstDate: DateTime.now().add(const Duration(days: -5095)),
|
||||||
lastDate: DateTime.now().add(const Duration(days: 2095)),
|
lastDate: DateTime.now().add(const Duration(days: 2095)),
|
||||||
);
|
);
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
@ -97,7 +98,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Expiration Time cannot be earlier than Effective Time.');
|
||||||
} else {
|
} else {
|
||||||
endTime = selectedDateTime.toString().split('.').first;
|
endTime = selectedDateTime.toString().split('.').first;
|
||||||
expirationTimeTimeStamp = selectedTimestamp;
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
@ -106,14 +108,11 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
try {
|
try {
|
||||||
print(event.emailAuthorizer?.toLowerCase());
|
|
||||||
// Convert search text to lower case for case-insensitive search
|
// Convert search text to lower case for case-insensitive search
|
||||||
final searchText = event.passwordName?.toLowerCase() ?? '';
|
final searchText = event.passwordName?.toLowerCase() ?? '';
|
||||||
final searchEmailText = event.emailAuthorizer?.toLowerCase() ?? '';
|
final searchEmailText = event.emailAuthorizer?.toLowerCase() ?? '';
|
||||||
@ -121,15 +120,17 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
bool matchesCriteria = true;
|
bool matchesCriteria = true;
|
||||||
// Convert timestamp to DateTime and extract date component
|
// Convert timestamp to DateTime and extract date component
|
||||||
DateTime effectiveDate =
|
DateTime effectiveDate =
|
||||||
DateTime.fromMillisecondsSinceEpoch(int.parse(item.effectiveTime.toString()) * 1000)
|
DateTime.fromMillisecondsSinceEpoch(int.parse(item.effectiveTime.toString()) * 1000)
|
||||||
.toUtc()
|
.toUtc()
|
||||||
.toLocal();
|
.toLocal();
|
||||||
DateTime invalidDate =
|
DateTime invalidDate =
|
||||||
DateTime.fromMillisecondsSinceEpoch(int.parse(item.invalidTime.toString()) * 1000)
|
DateTime.fromMillisecondsSinceEpoch(int.parse(item.invalidTime.toString()) * 1000)
|
||||||
.toUtc()
|
.toUtc()
|
||||||
.toLocal();
|
.toLocal();
|
||||||
DateTime effectiveDateAndTime = DateTime(effectiveDate.year, effectiveDate.month, effectiveDate.day,effectiveDate.hour,effectiveDate.minute);
|
DateTime effectiveDateAndTime = DateTime(effectiveDate.year, effectiveDate.month,
|
||||||
DateTime invalidDateAndTime = DateTime(invalidDate.year, invalidDate.month, invalidDate.day,invalidDate.hour,invalidDate.minute);
|
effectiveDate.day, effectiveDate.hour, effectiveDate.minute);
|
||||||
|
DateTime invalidDateAndTime = DateTime(invalidDate.year, invalidDate.month, invalidDate.day,
|
||||||
|
invalidDate.hour, invalidDate.minute);
|
||||||
|
|
||||||
// Filter by password name, making the search case-insensitive
|
// Filter by password name, making the search case-insensitive
|
||||||
if (searchText.isNotEmpty) {
|
if (searchText.isNotEmpty) {
|
||||||
@ -139,7 +140,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (searchEmailText.isNotEmpty) {
|
if (searchEmailText.isNotEmpty) {
|
||||||
final bool matchesName = item.authorizerEmail.toString().toLowerCase().contains(searchEmailText);
|
final bool matchesName =
|
||||||
|
item.authorizerEmail.toString().toLowerCase().contains(searchEmailText);
|
||||||
if (!matchesName) {
|
if (!matchesName) {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
@ -147,13 +149,9 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
// Filter by start date only
|
// Filter by start date only
|
||||||
if (event.startTime != null && event.endTime == null) {
|
if (event.startTime != null && event.endTime == null) {
|
||||||
DateTime startDateTime =
|
DateTime startDateTime =
|
||||||
DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
|
DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
|
||||||
startDateTime = DateTime(
|
startDateTime = DateTime(startDateTime.year, startDateTime.month, startDateTime.day,
|
||||||
startDateTime.year,
|
startDateTime.hour, startDateTime.minute);
|
||||||
startDateTime.month,
|
|
||||||
startDateTime.day,
|
|
||||||
startDateTime.hour,
|
|
||||||
startDateTime.minute);
|
|
||||||
if (effectiveDateAndTime.isBefore(startDateTime)) {
|
if (effectiveDateAndTime.isBefore(startDateTime)) {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
@ -161,14 +159,9 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
// Filter by end date only
|
// Filter by end date only
|
||||||
if (event.endTime != null && event.startTime == null) {
|
if (event.endTime != null && event.startTime == null) {
|
||||||
DateTime startDateTime =
|
DateTime startDateTime =
|
||||||
DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
|
DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
|
||||||
startDateTime = DateTime(
|
startDateTime = DateTime(startDateTime.year, startDateTime.month, startDateTime.day,
|
||||||
startDateTime.year,
|
startDateTime.hour, startDateTime.minute);
|
||||||
startDateTime.month,
|
|
||||||
startDateTime.day,
|
|
||||||
startDateTime.hour,
|
|
||||||
startDateTime.minute
|
|
||||||
);
|
|
||||||
if (invalidDateAndTime.isAfter(startDateTime)) {
|
if (invalidDateAndTime.isAfter(startDateTime)) {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
@ -177,12 +170,15 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
// Filter by both start date and end date
|
// Filter by both start date and end date
|
||||||
if (event.startTime != null && event.endTime != null) {
|
if (event.startTime != null && event.endTime != null) {
|
||||||
DateTime startDateTime =
|
DateTime startDateTime =
|
||||||
DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
|
DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
|
||||||
DateTime endDateTime =
|
DateTime endDateTime =
|
||||||
DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
|
DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
|
||||||
startDateTime = DateTime(startDateTime.year, startDateTime.month, startDateTime.day,startDateTime.hour,startDateTime.minute);
|
startDateTime = DateTime(startDateTime.year, startDateTime.month, startDateTime.day,
|
||||||
endDateTime = DateTime(endDateTime.year, endDateTime.month, endDateTime.day,endDateTime.hour,endDateTime.minute);
|
startDateTime.hour, startDateTime.minute);
|
||||||
if (effectiveDateAndTime.isBefore(startDateTime) || invalidDateAndTime.isAfter(endDateTime)) {
|
endDateTime = DateTime(endDateTime.year, endDateTime.month, endDateTime.day,
|
||||||
|
endDateTime.hour, endDateTime.minute);
|
||||||
|
if (effectiveDateAndTime.isBefore(startDateTime) ||
|
||||||
|
invalidDateAndTime.isAfter(endDateTime)) {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,7 +201,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
resetSearch(ResetSearch event, Emitter<AccessState> emit) async {
|
resetSearch(ResetSearch event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
startTime = 'Start Time';
|
startTime = 'Start Time';
|
||||||
@ -224,7 +219,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
" ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}";
|
" ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> onTabChanged(TabChangedEvent event, Emitter<AccessState> emit) async {
|
Future<void> onTabChanged(TabChangedEvent event, Emitter<AccessState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
@ -257,6 +251,4 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,6 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
final isLargeScreen = isLargeScreenSize(context);
|
final isLargeScreen = isLargeScreenSize(context);
|
||||||
final isSmallScreen = isSmallScreenSize(context);
|
final isSmallScreen = isSmallScreenSize(context);
|
||||||
final isHalfMediumScreen = isHafMediumScreenSize(context);
|
final isHalfMediumScreen = isHafMediumScreenSize(context);
|
||||||
@ -86,7 +85,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
_buildVisitorAdminPasswords(context, accessBloc),
|
_buildVisitorAdminPasswords(context, accessBloc),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: DynamicTable(
|
child: DynamicTable(
|
||||||
tableName: 'AccessManagement',
|
tableName: 'AccessManagement',
|
||||||
uuidIndex: 1,
|
uuidIndex: 1,
|
||||||
withSelectAll: true,
|
withSelectAll: true,
|
||||||
@ -169,7 +168,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Row _buildNormalSearchWidgets(BuildContext context, AccessBloc accessBloc) {
|
Row _buildNormalSearchWidgets(BuildContext context, AccessBloc accessBloc) {
|
||||||
TimeOfDay _selectedTime = TimeOfDay.now();
|
// TimeOfDay _selectedTime = TimeOfDay.now();
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -205,7 +204,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
title: 'Access Time',
|
title: 'Access Time',
|
||||||
size: MediaQuery.of(context).size,
|
size: MediaQuery.of(context).size,
|
||||||
endTime: () {
|
endTime: () {
|
||||||
accessBloc.add(SelectTime(context: context, isStart: false));
|
accessBloc.add(SelectTime(context: context, isStart: false));
|
||||||
},
|
},
|
||||||
startTime: () {
|
startTime: () {
|
||||||
accessBloc.add(SelectTime(context: context, isStart: true));
|
accessBloc.add(SelectTime(context: context, isStart: true));
|
||||||
@ -218,7 +217,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
SearchResetButtons(
|
SearchResetButtons(
|
||||||
onSearch: () {
|
onSearch: () {
|
||||||
accessBloc.add(FilterDataEvent(
|
accessBloc.add(FilterDataEvent(
|
||||||
emailAuthorizer:accessBloc.emailAuthorizer.text.toLowerCase() ,
|
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
|
||||||
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
|
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
|
||||||
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
||||||
startTime: accessBloc.effectiveTimeTimeStamp,
|
startTime: accessBloc.effectiveTimeTimeStamp,
|
||||||
@ -264,12 +263,11 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
SearchResetButtons(
|
SearchResetButtons(
|
||||||
onSearch: () {
|
onSearch: () {
|
||||||
accessBloc.add(FilterDataEvent(
|
accessBloc.add(FilterDataEvent(
|
||||||
emailAuthorizer:accessBloc.emailAuthorizer.text.toLowerCase() ,
|
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
|
||||||
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
|
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
|
||||||
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
||||||
startTime: accessBloc.effectiveTimeTimeStamp,
|
startTime: accessBloc.effectiveTimeTimeStamp,
|
||||||
endTime: accessBloc.expirationTimeTimeStamp
|
endTime: accessBloc.expirationTimeTimeStamp));
|
||||||
));
|
|
||||||
},
|
},
|
||||||
onReset: () {
|
onReset: () {
|
||||||
accessBloc.add(ResetSearch());
|
accessBloc.add(ResetSearch());
|
||||||
@ -278,6 +276,4 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,35 +96,22 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
|
|
||||||
Future<void> changePassword(ChangePasswordEvent event, Emitter<AuthState> emit) async {
|
Future<void> changePassword(ChangePasswordEvent event, Emitter<AuthState> emit) async {
|
||||||
emit(LoadingForgetState());
|
emit(LoadingForgetState());
|
||||||
try {
|
try {
|
||||||
var response = await AuthenticationAPI.verifyOtp(
|
var response = await AuthenticationAPI.verifyOtp(
|
||||||
email: forgetEmailController.text, otpCode: forgetOtp.text);
|
email: forgetEmailController.text, otpCode: forgetOtp.text);
|
||||||
if (response == true) {
|
if (response == true) {
|
||||||
await AuthenticationAPI.forgetPassword(
|
await AuthenticationAPI.forgetPassword(
|
||||||
password: forgetPasswordController.text,
|
password: forgetPasswordController.text, email: forgetEmailController.text);
|
||||||
email: forgetEmailController.text);
|
_timer?.cancel();
|
||||||
_timer?.cancel();
|
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
|
||||||
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
|
emit(SuccessForgetState());
|
||||||
emit(SuccessForgetState());
|
|
||||||
}
|
|
||||||
} on DioException catch (e) {
|
|
||||||
final errorData = e.response!.data;
|
|
||||||
String errorMessage = errorData['message'];
|
|
||||||
if (errorMessage == 'this email is not registered') {
|
|
||||||
validate = 'Invalid Credentials!';
|
|
||||||
emit(AuthInitialState());
|
|
||||||
} else if (errorMessage == "You entered wrong otp") {
|
|
||||||
forgetValidate = 'Wrong one time password.';
|
|
||||||
emit(AuthInitialState());
|
|
||||||
} else if (errorMessage == "OTP expired") {
|
|
||||||
forgetValidate = 'One time password has been expired.';
|
|
||||||
emit(AuthInitialState());
|
|
||||||
} else {
|
|
||||||
validate = '';
|
|
||||||
emit(AuthInitialState());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['error']['message'] ?? 'something went wrong';
|
||||||
|
validate = errorMessage;
|
||||||
|
emit(AuthInitialState());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String? validateCode(String? value) {
|
String? validateCode(String? value) {
|
||||||
|
|||||||
@ -48,8 +48,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
late ScrollController _scrollController;
|
late ScrollController _scrollController;
|
||||||
_scrollController = ScrollController();
|
_scrollController = ScrollController();
|
||||||
void _scrollToCenter() {
|
void _scrollToCenter() {
|
||||||
final double middlePosition =
|
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
|
||||||
_scrollController.position.maxScrollExtent / 2;
|
|
||||||
_scrollController.animateTo(
|
_scrollController.animateTo(
|
||||||
middlePosition,
|
middlePosition,
|
||||||
duration: const Duration(seconds: 1),
|
duration: const Duration(seconds: 1),
|
||||||
@ -66,8 +65,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
second: Center(
|
second: Center(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (state is AuthLoading)
|
if (state is AuthLoading) const Center(child: CircularProgressIndicator()),
|
||||||
const Center(child: CircularProgressIndicator()),
|
|
||||||
ListView(
|
ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
@ -97,21 +95,16 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withOpacity(0.1),
|
color: Colors.white.withOpacity(0.1),
|
||||||
borderRadius:
|
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
||||||
const BorderRadius.all(Radius.circular(30)),
|
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)),
|
||||||
border: Border.all(
|
|
||||||
color:
|
|
||||||
ColorsManager.graysColor.withOpacity(0.2)),
|
|
||||||
),
|
),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: forgetBloc.forgetFormKey,
|
key: forgetBloc.forgetFormKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: size.width * 0.02,
|
horizontal: size.width * 0.02, vertical: size.width * 0.003),
|
||||||
vertical: size.width * 0.003),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
MainAxisAlignment.spaceEvenly,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
@ -128,66 +121,55 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodySmall!
|
.bodySmall!
|
||||||
.copyWith(
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Form(
|
Form(
|
||||||
key: forgetBloc.forgetRegionKey,
|
key: forgetBloc.forgetRegionKey,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
child: _buildDropdownField(
|
child:
|
||||||
context, forgetBloc, size)))
|
_buildDropdownField(context, forgetBloc, size)))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Form(
|
Form(
|
||||||
key: forgetBloc.forgetEmailKey,
|
key: forgetBloc.forgetEmailKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Account",
|
"Account",
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
.textTheme
|
fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
.bodySmall!
|
|
||||||
.copyWith(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight:
|
|
||||||
FontWeight.w400),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: forgetBloc.forgetEmailController,
|
controller: forgetBloc.forgetEmailController,
|
||||||
validator: forgetBloc.validateEmail,
|
validator: forgetBloc.validateEmail,
|
||||||
decoration:
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
textBoxDecoration()!.copyWith(
|
|
||||||
hintText: 'Enter your email',
|
hintText: 'Enter your email',
|
||||||
hintStyle: Theme.of(context)
|
hintStyle: Theme.of(context)
|
||||||
.textTheme.bodySmall!.copyWith(
|
.textTheme
|
||||||
color: ColorsManager.grayColor,
|
.bodySmall!
|
||||||
fontWeight: FontWeight.w400),
|
.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
style: const TextStyle(
|
style: const TextStyle(color: Colors.black),
|
||||||
color: Colors.black),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
@ -195,35 +177,40 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodySmall!
|
.bodySmall!
|
||||||
.copyWith(
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
validator: forgetBloc.validateCode,
|
validator: forgetBloc.validateCode,
|
||||||
keyboardType:
|
keyboardType: TextInputType.visiblePassword,
|
||||||
TextInputType.visiblePassword,
|
|
||||||
controller: forgetBloc.forgetOtp,
|
controller: forgetBloc.forgetOtp,
|
||||||
decoration:
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
textBoxDecoration()!.copyWith(
|
|
||||||
hintText: 'Enter Code',
|
hintText: 'Enter Code',
|
||||||
hintStyle: Theme.of(context).textTheme
|
hintStyle: Theme.of(context)
|
||||||
.bodySmall!.copyWith(
|
.textTheme
|
||||||
color: ColorsManager.grayColor,
|
.bodySmall!
|
||||||
fontWeight: FontWeight.w400),
|
.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
suffixIcon: SizedBox(
|
suffixIcon: SizedBox(
|
||||||
width: 100,
|
width: 100,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: state is TimerState &&
|
onTap: state is TimerState &&
|
||||||
!state.isButtonEnabled &&
|
!state.isButtonEnabled &&
|
||||||
state.remainingTime != 1
|
state.remainingTime != 1
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
if (forgetBloc.forgetEmailKey.currentState!.validate()||forgetBloc.forgetRegionKey.currentState!.validate()) {
|
if (forgetBloc
|
||||||
if(forgetBloc.forgetRegionKey.currentState!.validate()){
|
.forgetEmailKey.currentState!
|
||||||
|
.validate() ||
|
||||||
|
forgetBloc
|
||||||
|
.forgetRegionKey.currentState!
|
||||||
|
.validate()) {
|
||||||
|
if (forgetBloc
|
||||||
|
.forgetRegionKey.currentState!
|
||||||
|
.validate()) {
|
||||||
forgetBloc.add(StartTimerEvent());
|
forgetBloc.add(StartTimerEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,28 +218,23 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
|
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: state
|
color: state is TimerState &&
|
||||||
is TimerState &&
|
!state.isButtonEnabled
|
||||||
!state
|
|
||||||
.isButtonEnabled
|
|
||||||
? Colors.grey
|
? Colors.grey
|
||||||
: ColorsManager
|
: ColorsManager.btnColor,
|
||||||
.btnColor,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: const TextStyle(
|
style: const TextStyle(color: Colors.black),
|
||||||
color: Colors.black),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (forgetBloc.forgetValidate !=
|
if (forgetBloc.forgetValidate !=
|
||||||
'') // Check if there is a validation message
|
'') // Check if there is a validation message
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
const EdgeInsets.only(top: 8.0),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
forgetBloc.forgetValidate,
|
forgetBloc.forgetValidate,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
@ -265,8 +247,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
@ -274,35 +255,26 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodySmall!
|
.bodySmall!
|
||||||
.copyWith(
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
obscureText: forgetBloc.obscureText,
|
obscureText: forgetBloc.obscureText,
|
||||||
keyboardType:
|
keyboardType: TextInputType.visiblePassword,
|
||||||
TextInputType.visiblePassword,
|
validator: forgetBloc.passwordValidator,
|
||||||
validator:
|
controller: forgetBloc.forgetPasswordController,
|
||||||
forgetBloc.passwordValidator,
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
controller: forgetBloc
|
|
||||||
.forgetPasswordController,
|
|
||||||
decoration:
|
|
||||||
textBoxDecoration()!.copyWith(
|
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
forgetBloc.add(
|
forgetBloc.add(PasswordVisibleEvent(
|
||||||
PasswordVisibleEvent(
|
newValue: forgetBloc.obscureText));
|
||||||
newValue: forgetBloc
|
|
||||||
.obscureText));
|
|
||||||
},
|
},
|
||||||
icon: SizedBox(
|
icon: SizedBox(
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
forgetBloc.obscureText
|
forgetBloc.obscureText
|
||||||
? Assets.visiblePassword
|
? Assets.visiblePassword
|
||||||
: Assets
|
: Assets.invisiblePassword,
|
||||||
.invisiblePassword,
|
|
||||||
height: 15,
|
height: 15,
|
||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
@ -313,13 +285,10 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
.textTheme
|
.textTheme
|
||||||
.bodySmall!
|
.bodySmall!
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color:
|
color: ColorsManager.grayColor,
|
||||||
ColorsManager.grayColor,
|
fontWeight: FontWeight.w400),
|
||||||
fontWeight:
|
|
||||||
FontWeight.w400),
|
|
||||||
),
|
),
|
||||||
style: const TextStyle(
|
style: const TextStyle(color: Colors.black),
|
||||||
color: Colors.black),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -329,21 +298,22 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
CrossAxisAlignment.center,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
backgroundColor:
|
backgroundColor: ColorsManager.btnColor,
|
||||||
ColorsManager.btnColor,
|
|
||||||
child: const Text('Submit'),
|
child: const Text('Submit'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (forgetBloc.forgetFormKey.currentState!.validate() ||
|
if (forgetBloc.forgetFormKey.currentState!.validate() ||
|
||||||
forgetBloc.forgetEmailKey.currentState!.validate() ) {
|
forgetBloc.forgetEmailKey.currentState!
|
||||||
if( forgetBloc.forgetEmailKey.currentState!.validate()
|
.validate()) {
|
||||||
&&forgetBloc.forgetFormKey.currentState!.validate() ){
|
if (forgetBloc.forgetEmailKey.currentState!
|
||||||
|
.validate() &&
|
||||||
|
forgetBloc.forgetFormKey.currentState!
|
||||||
|
.validate()) {
|
||||||
forgetBloc.add(ChangePasswordEvent());
|
forgetBloc.add(ChangePasswordEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,8 +328,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
forgetBloc.validate,
|
forgetBloc.validate,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700, color: ColorsManager.red),
|
||||||
color: ColorsManager.red),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -372,8 +341,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
"Do you have an account? ",
|
"Do you have an account? ",
|
||||||
style:
|
style: TextStyle(color: Colors.white),
|
||||||
TextStyle(color: Colors.white),
|
|
||||||
),
|
),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -407,8 +375,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDropdownField(
|
Widget _buildDropdownField(BuildContext context, AuthBloc loginBloc, Size size) {
|
||||||
BuildContext context, AuthBloc loginBloc, Size size) {
|
|
||||||
final TextEditingController textEditingController = TextEditingController();
|
final TextEditingController textEditingController = TextEditingController();
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -434,13 +401,10 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
builder: (FormFieldState<String> field) {
|
builder: (FormFieldState<String> field) {
|
||||||
return InputDecorator(
|
return InputDecorator(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding:
|
contentPadding: const EdgeInsets.symmetric(horizontal: 2, vertical: 10),
|
||||||
const EdgeInsets.symmetric(horizontal: 2, vertical: 10),
|
|
||||||
errorText: field.errorText,
|
errorText: field.errorText,
|
||||||
filled:
|
filled: true, // Ensure the dropdown is filled with the background color
|
||||||
true, // Ensure the dropdown is filled with the background color
|
fillColor: ColorsManager.boxColor, // Match the dropdown container color
|
||||||
fillColor: ColorsManager
|
|
||||||
.boxColor, // Match the dropdown container color
|
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
@ -451,22 +415,20 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color: field.hasError ? Colors.red : ColorsManager.grayColor,
|
||||||
field.hasError ? Colors.red : ColorsManager.grayColor,
|
|
||||||
width: 1.5,
|
width: 1.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color: field.hasError ? Colors.red : ColorsManager.grayColor,
|
||||||
field.hasError ? Colors.red : ColorsManager.grayColor,
|
|
||||||
width: 1.5,
|
width: 1.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
errorBorder: OutlineInputBorder(
|
errorBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
borderSide: BorderSide(
|
borderSide: const BorderSide(
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
width: 1.5,
|
width: 1.5,
|
||||||
),
|
),
|
||||||
@ -488,24 +450,22 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
value: region.id,
|
value: region.id,
|
||||||
child: Text(
|
child: Text(
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
region.name,
|
region.name,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
value: loginBloc.regionList!
|
value: loginBloc.regionList!.any((region) => region.id == loginBloc.regionUuid)
|
||||||
.any((region) => region.id == loginBloc.regionUuid)
|
|
||||||
? loginBloc.regionUuid
|
? loginBloc.regionUuid
|
||||||
: null,
|
: null,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
loginBloc.add(SelectRegionEvent(val: value));
|
loginBloc.add(SelectRegionEvent(val: value));
|
||||||
field.didChange(
|
field.didChange(value); // Notify the form field of the change
|
||||||
value); // Notify the form field of the change
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
buttonStyleData: const ButtonStyleData(
|
buttonStyleData: const ButtonStyleData(
|
||||||
@ -529,8 +489,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
searchInnerWidgetHeight: 50,
|
searchInnerWidgetHeight: 50,
|
||||||
searchInnerWidget: Container(
|
searchInnerWidget: Container(
|
||||||
height: 50,
|
height: 50,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
horizontal: 8, vertical: 4),
|
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
@ -544,8 +503,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
searchMatchFn: (item, searchValue) {
|
searchMatchFn: (item, searchValue) {
|
||||||
final regionName =
|
final regionName = (item.child as Text).data?.toLowerCase() ?? '';
|
||||||
(item.child as Text).data?.toLowerCase() ?? '';
|
|
||||||
final search = searchValue.toLowerCase().trim();
|
final search = searchValue.toLowerCase().trim();
|
||||||
return regionName.contains(search);
|
return regionName.contains(search);
|
||||||
},
|
},
|
||||||
@ -564,6 +522,4 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,7 @@ class LoginWebPage extends StatefulWidget {
|
|||||||
State<LoginWebPage> createState() => _LoginWebPageState();
|
State<LoginWebPage> createState() => _LoginWebPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LoginWebPageState extends State<LoginWebPage>
|
class _LoginWebPageState extends State<LoginWebPage> with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -60,8 +59,7 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
_scrollController = ScrollController();
|
_scrollController = ScrollController();
|
||||||
|
|
||||||
void _scrollToCenter() {
|
void _scrollToCenter() {
|
||||||
final double middlePosition =
|
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
|
||||||
_scrollController.position.maxScrollExtent / 2;
|
|
||||||
_scrollController.animateTo(
|
_scrollController.animateTo(
|
||||||
middlePosition,
|
middlePosition,
|
||||||
duration: const Duration(seconds: 1),
|
duration: const Duration(seconds: 1),
|
||||||
@ -123,8 +121,7 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
const Spacer(),
|
const Spacer(),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: _buildLoginFormFields(
|
child: _buildLoginFormFields(context, loginBloc, size),
|
||||||
context, loginBloc, size),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
@ -135,14 +132,12 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state is AuthLoading)
|
if (state is AuthLoading) const Center(child: CircularProgressIndicator())
|
||||||
const Center(child: CircularProgressIndicator())
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLoginFormFields(
|
Widget _buildLoginFormFields(BuildContext context, AuthBloc loginBloc, Size size) {
|
||||||
BuildContext context, AuthBloc loginBloc, Size size) {
|
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withOpacity(0.1),
|
color: Colors.white.withOpacity(0.1),
|
||||||
@ -152,8 +147,8 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
child: Form(
|
child: Form(
|
||||||
key: loginBloc.loginFormKey,
|
key: loginBloc.loginFormKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding:
|
||||||
horizontal: size.width * 0.02, vertical: size.width * 0.003),
|
EdgeInsets.symmetric(horizontal: size.width * 0.02, vertical: size.width * 0.003),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -181,9 +176,7 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildDropdownField(BuildContext context, AuthBloc loginBloc, Size size) {
|
||||||
Widget _buildDropdownField(
|
|
||||||
BuildContext context, AuthBloc loginBloc, Size size) {
|
|
||||||
final TextEditingController textEditingController = TextEditingController();
|
final TextEditingController textEditingController = TextEditingController();
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -192,9 +185,9 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
Text(
|
Text(
|
||||||
"Country/Region",
|
"Country/Region",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Container(
|
Container(
|
||||||
@ -211,9 +204,9 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
hint: Text(
|
hint: Text(
|
||||||
'Select your region/country',
|
'Select your region/country',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
color: ColorsManager.grayColor,
|
color: ColorsManager.grayColor,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
items: loginBloc.regionList!.map((RegionModel region) {
|
items: loginBloc.regionList!.map((RegionModel region) {
|
||||||
@ -227,7 +220,8 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
value: loginBloc.regionList!.any(
|
value: loginBloc.regionList!.any(
|
||||||
(region) => region.id == loginBloc.regionUuid,)
|
(region) => region.id == loginBloc.regionUuid,
|
||||||
|
)
|
||||||
? loginBloc.regionUuid
|
? loginBloc.regionUuid
|
||||||
: null,
|
: null,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
@ -286,7 +280,6 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Widget _buildEmailField(BuildContext context, AuthBloc loginBloc) {
|
Widget _buildEmailField(BuildContext context, AuthBloc loginBloc) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -310,9 +303,10 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
decoration: textBoxDecoration()!.copyWith(
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
errorStyle: const TextStyle(height: 0),
|
errorStyle: const TextStyle(height: 0),
|
||||||
hintText: 'Enter your email address',
|
hintText: 'Enter your email address',
|
||||||
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
hintStyle: Theme.of(context)
|
||||||
color: ColorsManager.grayColor,
|
.textTheme
|
||||||
fontWeight: FontWeight.w400)),
|
.bodySmall!
|
||||||
|
.copyWith(color: ColorsManager.grayColor, fontWeight: FontWeight.w400)),
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -344,18 +338,17 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
controller: loginBloc.loginPasswordController,
|
controller: loginBloc.loginPasswordController,
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
hintText: 'At least 8 characters',
|
hintText: 'At least 8 characters',
|
||||||
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
hintStyle: Theme.of(context)
|
||||||
color: ColorsManager.grayColor, fontWeight: FontWeight.w400),
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(color: ColorsManager.grayColor, fontWeight: FontWeight.w400),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
loginBloc.add(
|
loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText));
|
||||||
PasswordVisibleEvent(newValue: loginBloc.obscureText));
|
|
||||||
},
|
},
|
||||||
icon: SizedBox(
|
icon: SizedBox(
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
loginBloc.obscureText
|
loginBloc.obscureText ? Assets.visiblePassword : Assets.invisiblePassword,
|
||||||
? Assets.visiblePassword
|
|
||||||
: Assets.invisiblePassword,
|
|
||||||
height: 15,
|
height: 15,
|
||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
@ -383,10 +376,10 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Forgot Password?",
|
"Forgot Password?",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context)
|
||||||
color: Colors.black,
|
.textTheme
|
||||||
fontSize: 14,
|
.bodySmall!
|
||||||
fontWeight: FontWeight.w400),
|
.copyWith(color: Colors.black, fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -450,8 +443,7 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSignInButton(
|
Widget _buildSignInButton(BuildContext context, AuthBloc loginBloc, Size size) {
|
||||||
BuildContext context, AuthBloc loginBloc, Size size) {
|
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -492,8 +484,7 @@ class _LoginWebPageState extends State<LoginWebPage>
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
loginBloc.validate,
|
loginBloc.validate,
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontWeight: FontWeight.w700, color: ColorsManager.red),
|
||||||
fontWeight: FontWeight.w700, color: ColorsManager.red),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
304
lib/pages/common/access_device_table.dart
Normal file
304
lib/pages/common/access_device_table.dart
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
|
class AccessDeviceTable extends StatefulWidget {
|
||||||
|
final List<String> headers;
|
||||||
|
final String? tableName;
|
||||||
|
final List<List<dynamic>> data;
|
||||||
|
final BoxDecoration? headerDecoration;
|
||||||
|
final BoxDecoration? cellDecoration;
|
||||||
|
final Size size;
|
||||||
|
final bool withCheckBox;
|
||||||
|
final bool withSelectAll;
|
||||||
|
final bool isEmpty;
|
||||||
|
final void Function(bool?)? selectAll;
|
||||||
|
final void Function(int, bool, dynamic)? onRowSelected;
|
||||||
|
final List<String>? initialSelectedIds;
|
||||||
|
final int uuidIndex;
|
||||||
|
const AccessDeviceTable({
|
||||||
|
super.key,
|
||||||
|
required this.headers,
|
||||||
|
required this.data,
|
||||||
|
required this.size,
|
||||||
|
this.tableName,
|
||||||
|
required this.isEmpty,
|
||||||
|
required this.withCheckBox,
|
||||||
|
required this.withSelectAll,
|
||||||
|
this.headerDecoration,
|
||||||
|
this.cellDecoration,
|
||||||
|
this.selectAll,
|
||||||
|
this.onRowSelected,
|
||||||
|
this.initialSelectedIds,
|
||||||
|
required this.uuidIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DynamicTableState createState() => _DynamicTableState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DynamicTableState extends State<AccessDeviceTable> {
|
||||||
|
late List<bool> _selected;
|
||||||
|
bool _selectAll = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_initializeSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(AccessDeviceTable oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.data != widget.data) {
|
||||||
|
_initializeSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _initializeSelection() {
|
||||||
|
if (widget.data.isEmpty) {
|
||||||
|
_selected = [];
|
||||||
|
_selectAll = false;
|
||||||
|
} else {
|
||||||
|
_selected = List<bool>.generate(widget.data.length, (index) {
|
||||||
|
// Check if the initialSelectedIds contains the deviceUuid
|
||||||
|
// uuidIndex is the index of the column containing the deviceUuid
|
||||||
|
final deviceUuid = widget.data[index][widget.uuidIndex];
|
||||||
|
return widget.initialSelectedIds != null &&
|
||||||
|
widget.initialSelectedIds!.contains(deviceUuid);
|
||||||
|
});
|
||||||
|
_selectAll = _selected.every((element) => element == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleRowSelection(int index) {
|
||||||
|
setState(() {
|
||||||
|
_selected[index] = !_selected[index];
|
||||||
|
|
||||||
|
if (widget.onRowSelected != null) {
|
||||||
|
widget.onRowSelected!(index, _selected[index], widget.data[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleSelectAll(bool? value) {
|
||||||
|
setState(() {
|
||||||
|
_selectAll = value ?? false;
|
||||||
|
_selected = List<bool>.filled(widget.data.length, _selectAll);
|
||||||
|
if (widget.selectAll != null) {
|
||||||
|
widget.selectAll!(_selectAll);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: widget.cellDecoration,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: SizedBox(
|
||||||
|
width: widget.size.width,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: widget.headerDecoration ??
|
||||||
|
BoxDecoration(color: Colors.grey[200]),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
if (widget.withCheckBox) _buildSelectAllCheckbox(),
|
||||||
|
...widget.headers
|
||||||
|
.map((header) => _buildTableHeaderCell(header)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
widget.isEmpty
|
||||||
|
? Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(Assets.emptyTable),
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
// no password
|
||||||
|
widget.tableName == 'AccessManagement'
|
||||||
|
? 'No Password '
|
||||||
|
: 'No Devices',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: ColorsManager.grayColor),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: widget.data.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final row = widget.data[index];
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
if (widget.withCheckBox)
|
||||||
|
_buildRowCheckbox(
|
||||||
|
index, widget.size.height * 0.10),
|
||||||
|
...row.map((cell) => _buildTableCell(
|
||||||
|
cell.toString(),
|
||||||
|
widget.size.height * 0.10)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSelectAllCheckbox() {
|
||||||
|
return Container(
|
||||||
|
width: 50,
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border.symmetric(
|
||||||
|
vertical: BorderSide(color: ColorsManager.boxDivider),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Checkbox(
|
||||||
|
value: widget.data.isNotEmpty &&
|
||||||
|
_selected.every((element) => element == true),
|
||||||
|
onChanged: widget.withSelectAll && widget.data.isNotEmpty
|
||||||
|
? _toggleSelectAll
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRowCheckbox(int index, double size) {
|
||||||
|
return Container(
|
||||||
|
width: 50,
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
height: size,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: ColorsManager.boxDivider,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Center(
|
||||||
|
child: Checkbox(
|
||||||
|
value: _selected[index],
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
_toggleRowSelection(index);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTableHeaderCell(String title) {
|
||||||
|
return Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border.symmetric(
|
||||||
|
vertical: BorderSide(color: ColorsManager.boxDivider),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 13,
|
||||||
|
color: Color(0xFF999999),
|
||||||
|
),
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTableCell(String content, double size) {
|
||||||
|
bool isBatteryLevel = content.endsWith('%');
|
||||||
|
double? batteryLevel;
|
||||||
|
|
||||||
|
if (isBatteryLevel) {
|
||||||
|
batteryLevel = double.tryParse(content.replaceAll('%', '').trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
Color? statusColor;
|
||||||
|
switch (content) {
|
||||||
|
case 'Effective':
|
||||||
|
statusColor = ColorsManager.textGreen;
|
||||||
|
break;
|
||||||
|
case 'Expired':
|
||||||
|
statusColor = ColorsManager.red;
|
||||||
|
break;
|
||||||
|
case 'To be effective':
|
||||||
|
statusColor = ColorsManager.yaGreen;
|
||||||
|
break;
|
||||||
|
case 'Online':
|
||||||
|
statusColor = ColorsManager.green;
|
||||||
|
break;
|
||||||
|
case 'Offline':
|
||||||
|
statusColor = ColorsManager.red;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statusColor = Colors.black;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
child: Container(
|
||||||
|
height: size,
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: ColorsManager.boxDivider,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
content,
|
||||||
|
style: TextStyle(
|
||||||
|
color: (batteryLevel != null && batteryLevel < 20)
|
||||||
|
? ColorsManager.red
|
||||||
|
: (batteryLevel != null && batteryLevel > 20)
|
||||||
|
? ColorsManager.green
|
||||||
|
: statusColor,
|
||||||
|
fontSize: 10,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
@ -22,13 +22,7 @@ class CurtainToggle extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
@ -53,30 +55,47 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(DynamicTable oldWidget) {
|
void didUpdateWidget(DynamicTable oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (oldWidget.data.length != widget.data.length) {
|
if (!_compareListOfLists(oldWidget.data, widget.data)) {
|
||||||
_initializeSelection();
|
_initializeSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _compareListOfLists(List<List<dynamic>> oldList, List<List<dynamic>> newList) {
|
||||||
|
// Check if the old and new lists are the same
|
||||||
|
if (oldList.length != newList.length) return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < oldList.length; i++) {
|
||||||
|
if (oldList[i].length != newList[i].length) return false;
|
||||||
|
|
||||||
|
for (int j = 0; j < oldList[i].length; j++) {
|
||||||
|
if (oldList[i][j] != newList[i][j]) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void _initializeSelection() {
|
void _initializeSelection() {
|
||||||
_selectedRows = List<bool>.filled(widget.data.length, false);
|
_selectedRows = List<bool>.filled(widget.data.length, false);
|
||||||
_selectAll = false;
|
_selectAll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _toggleSelectAll(bool? value) {
|
|
||||||
setState(() {
|
|
||||||
_selectAll = value ?? false;
|
|
||||||
_selectedRows = List<bool>.filled(widget.data.length, _selectAll);
|
|
||||||
});
|
|
||||||
widget.onSelectionChanged?.call(_selectedRows);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _toggleRowSelection(int index) {
|
void _toggleRowSelection(int index) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedRows[index] = !_selectedRows[index];
|
_selectedRows[index] = !_selectedRows[index];
|
||||||
_selectAll = _selectedRows.every((isSelected) => isSelected);
|
_selectAll = _selectedRows.every((isSelected) => isSelected);
|
||||||
});
|
});
|
||||||
widget.onSelectionChanged?.call(_selectedRows);
|
widget.onSelectionChanged?.call(_selectedRows);
|
||||||
|
context.read<DeviceManagementBloc>().add(UpdateSelection(_selectedRows));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleSelectAll(bool? value) {
|
||||||
|
setState(() {
|
||||||
|
_selectAll = value ?? false;
|
||||||
|
_selectedRows = List<bool>.filled(widget.data.length, _selectAll);
|
||||||
|
});
|
||||||
|
widget.onSelectionChanged?.call(_selectedRows);
|
||||||
|
context.read<DeviceManagementBloc>().add(UpdateSelection(_selectedRows));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -90,13 +109,11 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
decoration: widget.headerDecoration ??
|
decoration: widget.headerDecoration ?? BoxDecoration(color: Colors.grey[200]),
|
||||||
BoxDecoration(color: Colors.grey[200]),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
if (widget.withCheckBox) _buildSelectAllCheckbox(),
|
if (widget.withCheckBox) _buildSelectAllCheckbox(),
|
||||||
...widget.headers
|
...widget.headers.map((header) => _buildTableHeaderCell(header)),
|
||||||
.map((header) => _buildTableHeaderCell(header)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -117,14 +134,9 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
// no password
|
// no password
|
||||||
widget.tableName == 'AccessManagement'
|
widget.tableName == 'AccessManagement' ? 'No Password ' : 'No Devices',
|
||||||
? 'No Password '
|
style:
|
||||||
: 'No Devices',
|
Theme.of(context).textTheme.bodySmall!.copyWith(color: ColorsManager.grayColor),
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodySmall!
|
|
||||||
.copyWith(
|
|
||||||
color: ColorsManager.grayColor),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -143,12 +155,8 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
final row = widget.data[index];
|
final row = widget.data[index];
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
if (widget.withCheckBox)
|
if (widget.withCheckBox) _buildRowCheckbox(index, widget.size.height * 0.10),
|
||||||
_buildRowCheckbox(
|
...row.map((cell) => _buildTableCell(cell.toString(), widget.size.height * 0.10)),
|
||||||
index, widget.size.height * 0.10),
|
|
||||||
...row.map((cell) => _buildTableCell(
|
|
||||||
cell.toString(),
|
|
||||||
widget.size.height * 0.10)),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -173,9 +181,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
),
|
),
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
value: _selectAll,
|
value: _selectAll,
|
||||||
onChanged: widget.withSelectAll && widget.data.isNotEmpty
|
onChanged: widget.withSelectAll && widget.data.isNotEmpty ? _toggleSelectAll : null,
|
||||||
? _toggleSelectAll
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,20 +2,21 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
class StatefulTextField extends StatefulWidget {
|
class StatefulTextField extends StatefulWidget {
|
||||||
const StatefulTextField({
|
const StatefulTextField(
|
||||||
super.key,
|
{super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
this.hintText = 'Please enter',
|
this.hintText = 'Please enter',
|
||||||
required this.width,
|
required this.width,
|
||||||
this.elevation = 0,
|
this.elevation = 0,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
});
|
this.onSubmitted});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final String hintText;
|
final String hintText;
|
||||||
final double width;
|
final double width;
|
||||||
final double elevation;
|
final double elevation;
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
|
final Function? onSubmitted;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulTextField> createState() => _StatefulTextFieldState();
|
State<StatefulTextField> createState() => _StatefulTextFieldState();
|
||||||
@ -25,30 +26,31 @@ class _StatefulTextFieldState extends State<StatefulTextField> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomTextField(
|
return CustomTextField(
|
||||||
title: widget.title,
|
title: widget.title,
|
||||||
controller: widget.controller,
|
controller: widget.controller,
|
||||||
hintText: widget.hintText,
|
hintText: widget.hintText,
|
||||||
width: widget.width,
|
width: widget.width,
|
||||||
elevation: widget.elevation,
|
elevation: widget.elevation,
|
||||||
);
|
onSubmittedFun: widget.onSubmitted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomTextField extends StatelessWidget {
|
class CustomTextField extends StatelessWidget {
|
||||||
const CustomTextField({
|
const CustomTextField(
|
||||||
super.key,
|
{super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.hintText = 'Please enter',
|
this.hintText = 'Please enter',
|
||||||
required this.width,
|
required this.width,
|
||||||
this.elevation = 0,
|
this.elevation = 0,
|
||||||
});
|
this.onSubmittedFun});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
final String hintText;
|
final String hintText;
|
||||||
final double width;
|
final double width;
|
||||||
final double elevation;
|
final double elevation;
|
||||||
|
final Function? onSubmittedFun;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -81,10 +83,12 @@ class CustomTextField extends StatelessWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: hintText,
|
hintText: hintText,
|
||||||
hintStyle: const TextStyle(fontSize: 12),
|
hintStyle: const TextStyle(fontSize: 12),
|
||||||
contentPadding:
|
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
),
|
),
|
||||||
|
onFieldSubmitted: (_) {
|
||||||
|
onSubmittedFun!();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -15,8 +15,7 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
|||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
class AcDeviceBatchControlView extends StatelessWidget
|
class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
const AcDeviceBatchControlView({super.key, required this.devicesIds});
|
const AcDeviceBatchControlView({super.key, required this.devicesIds});
|
||||||
|
|
||||||
final List<String> devicesIds;
|
final List<String> devicesIds;
|
||||||
@ -27,8 +26,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
final isLarge = isLargeScreenSize(context);
|
final isLarge = isLargeScreenSize(context);
|
||||||
final isMedium = isMediumScreenSize(context);
|
final isMedium = isMediumScreenSize(context);
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => AcBloc(deviceId: devicesIds.first)
|
create: (context) => AcBloc(deviceId: devicesIds.first)..add(AcFetchBatchStatusEvent(devicesIds)),
|
||||||
..add(AcFetchBatchStatusEvent(devicesIds)),
|
|
||||||
child: BlocBuilder<AcBloc, AcsState>(
|
child: BlocBuilder<AcBloc, AcsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is ACStatusLoaded) {
|
if (state is ACStatusLoaded) {
|
||||||
@ -66,6 +64,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
tempSet: state.status.tempSet,
|
tempSet: state.status.tempSet,
|
||||||
code: 'temp_set',
|
code: 'temp_set',
|
||||||
devicesIds: devicesIds,
|
devicesIds: devicesIds,
|
||||||
|
isBatch: true,
|
||||||
),
|
),
|
||||||
BatchAcMode(
|
BatchAcMode(
|
||||||
value: state.status.acMode,
|
value: state.status.acMode,
|
||||||
@ -99,8 +98,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'h',
|
'h',
|
||||||
style: context.textTheme.bodySmall!
|
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor),
|
||||||
.copyWith(color: ColorsManager.blackColor),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'30',
|
'30',
|
||||||
@ -109,9 +107,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('m',
|
Text('m', style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor)),
|
||||||
style: context.textTheme.bodySmall!
|
|
||||||
.copyWith(color: ColorsManager.blackColor)),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
@ -133,7 +129,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
code: 'child_lock',
|
code: 'child_lock',
|
||||||
value: state.status.childLock,
|
value: state.status.childLock,
|
||||||
label: 'Child Lock',
|
label: 'Child Lock',
|
||||||
icon: state.status.childLock ? Assets.unlock : Assets.acLock,
|
icon: state.status.childLock ? Assets.acLock : Assets.unlock,
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<AcBloc>().add(AcBatchControlEvent(
|
context.read<AcBloc>().add(AcBatchControlEvent(
|
||||||
devicesIds: devicesIds,
|
devicesIds: devicesIds,
|
||||||
@ -147,8 +143,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
callFactoryReset: () {
|
callFactoryReset: () {
|
||||||
context.read<AcBloc>().add(AcFactoryResetEvent(
|
context.read<AcBloc>().add(AcFactoryResetEvent(
|
||||||
deviceId: state.status.uuid,
|
deviceId: state.status.uuid,
|
||||||
factoryResetModel:
|
factoryResetModel: FactoryResetModel(devicesUuid: devicesIds),
|
||||||
FactoryResetModel(devicesUuid: devicesIds),
|
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -24,8 +24,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
final isLarge = isLargeScreenSize(context);
|
final isLarge = isLargeScreenSize(context);
|
||||||
final isMedium = isMediumScreenSize(context);
|
final isMedium = isMediumScreenSize(context);
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => AcBloc(deviceId: device.uuid!)
|
create: (context) => AcBloc(deviceId: device.uuid!)..add(AcFetchDeviceStatusEvent(device.uuid!)),
|
||||||
..add(AcFetchDeviceStatusEvent(device.uuid!)),
|
|
||||||
child: BlocBuilder<AcBloc, AcsState>(
|
child: BlocBuilder<AcBloc, AcsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is ACStatusLoaded) {
|
if (state is ACStatusLoaded) {
|
||||||
@ -98,8 +97,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'h',
|
'h',
|
||||||
style: context.textTheme.bodySmall!
|
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor),
|
||||||
.copyWith(color: ColorsManager.blackColor),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'30',
|
'30',
|
||||||
@ -108,9 +106,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('m',
|
Text('m', style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor)),
|
||||||
style: context.textTheme.bodySmall!
|
|
||||||
.copyWith(color: ColorsManager.blackColor)),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
@ -132,7 +128,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
code: 'child_lock',
|
code: 'child_lock',
|
||||||
value: state.status.childLock,
|
value: state.status.childLock,
|
||||||
label: 'Child Lock',
|
label: 'Child Lock',
|
||||||
icon: state.status.childLock ? Assets.unlock : Assets.acLock,
|
icon: state.status.childLock ? Assets.acLock : Assets.unlock,
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<AcBloc>().add(
|
context.read<AcBloc>().add(
|
||||||
AcControlEvent(
|
AcControlEvent(
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class BatchAcMode extends StatelessWidget {
|
class BatchAcMode extends StatelessWidget {
|
||||||
const BatchAcMode({
|
const BatchAcMode({
|
||||||
@ -21,30 +22,20 @@ class BatchAcMode extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildIconContainer(context, TempModes.cold, Assets.freezing,
|
_buildIconContainer(context, TempModes.cold, Assets.freezing, value == TempModes.cold),
|
||||||
value == TempModes.cold),
|
_buildIconContainer(context, TempModes.hot, Assets.acSun, value == TempModes.hot),
|
||||||
_buildIconContainer(
|
_buildIconContainer(context, TempModes.wind, Assets.acAirConditioner, value == TempModes.wind),
|
||||||
context, TempModes.hot, Assets.acSun, value == TempModes.hot),
|
|
||||||
_buildIconContainer(context, TempModes.wind, Assets.acAirConditioner,
|
|
||||||
value == TempModes.wind),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildIconContainer(
|
Widget _buildIconContainer(BuildContext context, TempModes mode, String assetPath, bool isSelected) {
|
||||||
BuildContext context, TempModes mode, String assetPath, bool isSelected) {
|
|
||||||
return Flexible(
|
return Flexible(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/celciuse_symbol.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/celciuse_symbol.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
|
||||||
|
|
||||||
class BatchCurrentTemp extends StatefulWidget {
|
class BatchCurrentTemp extends StatefulWidget {
|
||||||
const BatchCurrentTemp({
|
const BatchCurrentTemp({
|
||||||
@ -14,12 +16,14 @@ class BatchCurrentTemp extends StatefulWidget {
|
|||||||
required this.devicesIds,
|
required this.devicesIds,
|
||||||
required this.currentTemp,
|
required this.currentTemp,
|
||||||
required this.tempSet,
|
required this.tempSet,
|
||||||
|
this.isBatch,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String code;
|
final String code;
|
||||||
final List<String> devicesIds;
|
final List<String> devicesIds;
|
||||||
final int currentTemp;
|
final int currentTemp;
|
||||||
final int tempSet;
|
final int tempSet;
|
||||||
|
final bool? isBatch;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<BatchCurrentTemp> createState() => _CurrentTempState();
|
State<BatchCurrentTemp> createState() => _CurrentTempState();
|
||||||
@ -67,49 +71,39 @@ class _CurrentTempState extends State<BatchCurrentTemp> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
widget.isBatch == true
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
? Text(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
'Set Temperature',
|
||||||
children: [
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
|
||||||
Text(
|
)
|
||||||
'Current Temperature',
|
: Column(
|
||||||
style: Theme.of(context)
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
.textTheme
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
.bodySmall!
|
children: [
|
||||||
.copyWith(color: Colors.grey),
|
Text(
|
||||||
),
|
'Current Temperature',
|
||||||
const SizedBox(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
|
||||||
height: 5,
|
),
|
||||||
),
|
const SizedBox(
|
||||||
Row(
|
height: 5,
|
||||||
children: [
|
),
|
||||||
Text(
|
Row(
|
||||||
(widget.currentTemp > 99
|
children: [
|
||||||
? widget.currentTemp / 10
|
Text(
|
||||||
: widget.currentTemp)
|
(widget.currentTemp > 99 ? widget.currentTemp / 10 : widget.currentTemp).toString(),
|
||||||
.toString(),
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
|
||||||
style: Theme.of(context)
|
),
|
||||||
.textTheme
|
const CelsiusSymbol(
|
||||||
.bodySmall!
|
color: Colors.grey,
|
||||||
.copyWith(color: Colors.grey),
|
)
|
||||||
),
|
],
|
||||||
const CelsiusSymbol(
|
),
|
||||||
color: Colors.grey,
|
],
|
||||||
)
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
IncrementDecrementWidget(
|
IncrementDecrementWidget(
|
||||||
value: _adjustedValue.toString(),
|
value: _adjustedValue.toString(),
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class BatchFanSpeedControl extends StatelessWidget {
|
class BatchFanSpeedControl extends StatelessWidget {
|
||||||
const BatchFanSpeedControl({
|
const BatchFanSpeedControl({
|
||||||
@ -21,23 +22,16 @@ class BatchFanSpeedControl extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
padding: 8,
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Wrap(
|
Wrap(
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
_buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto,
|
_buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto, value == FanSpeeds.auto),
|
||||||
value == FanSpeeds.auto),
|
_buildIconContainer(context, FanSpeeds.low, Assets.acFanLow, value == FanSpeeds.low),
|
||||||
_buildIconContainer(context, FanSpeeds.low, Assets.acFanLow,
|
|
||||||
value == FanSpeeds.low),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -45,10 +39,8 @@ class BatchFanSpeedControl extends StatelessWidget {
|
|||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
_buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle,
|
_buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle, value == FanSpeeds.middle),
|
||||||
value == FanSpeeds.middle),
|
_buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh, value == FanSpeeds.high),
|
||||||
_buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh,
|
|
||||||
value == FanSpeeds.high),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -56,8 +48,7 @@ class BatchFanSpeedControl extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildIconContainer(BuildContext context, FanSpeeds speed,
|
Widget _buildIconContainer(BuildContext context, FanSpeeds speed, String assetPath, bool isSelected) {
|
||||||
String assetPath, bool isSelected) {
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<AcBloc>().add(
|
context.read<AcBloc>().add(
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class AcMode extends StatelessWidget {
|
class AcMode extends StatelessWidget {
|
||||||
const AcMode({
|
const AcMode({
|
||||||
@ -21,30 +22,20 @@ class AcMode extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildIconContainer(context, TempModes.cold, Assets.freezing,
|
_buildIconContainer(context, TempModes.cold, Assets.freezing, value == TempModes.cold),
|
||||||
value == TempModes.cold),
|
_buildIconContainer(context, TempModes.hot, Assets.acSun, value == TempModes.hot),
|
||||||
_buildIconContainer(
|
_buildIconContainer(context, TempModes.wind, Assets.acAirConditioner, value == TempModes.wind),
|
||||||
context, TempModes.hot, Assets.acSun, value == TempModes.hot),
|
|
||||||
_buildIconContainer(context, TempModes.wind, Assets.acAirConditioner,
|
|
||||||
value == TempModes.wind),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildIconContainer(
|
Widget _buildIconContainer(BuildContext context, TempModes mode, String assetPath, bool isSelected) {
|
||||||
BuildContext context, TempModes mode, String assetPath, bool isSelected) {
|
|
||||||
return Flexible(
|
return Flexible(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
@ -25,13 +25,7 @@ class AcToggle extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/celciuse_symbol.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/celciuse_symbol.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
|
||||||
|
|
||||||
class CurrentTemp extends StatefulWidget {
|
class CurrentTemp extends StatefulWidget {
|
||||||
const CurrentTemp({
|
const CurrentTemp({
|
||||||
@ -67,13 +69,7 @@ class _CurrentTempState extends State<CurrentTemp> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -83,10 +79,7 @@ class _CurrentTempState extends State<CurrentTemp> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Current Temperature',
|
'Current Temperature',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
|
||||||
.textTheme
|
|
||||||
.bodySmall!
|
|
||||||
.copyWith(color: Colors.grey),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 5,
|
height: 5,
|
||||||
@ -94,14 +87,8 @@ class _CurrentTempState extends State<CurrentTemp> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
(widget.currentTemp > 99
|
(widget.currentTemp > 99 ? widget.currentTemp / 10 : widget.currentTemp).toString(),
|
||||||
? widget.currentTemp / 10
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
|
||||||
: widget.currentTemp)
|
|
||||||
.toString(),
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodySmall!
|
|
||||||
.copyWith(color: Colors.grey),
|
|
||||||
),
|
),
|
||||||
const CelsiusSymbol(
|
const CelsiusSymbol(
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class FanSpeedControl extends StatelessWidget {
|
class FanSpeedControl extends StatelessWidget {
|
||||||
const FanSpeedControl({
|
const FanSpeedControl({
|
||||||
@ -21,23 +22,15 @@ class FanSpeedControl extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Wrap(
|
Wrap(
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
_buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto,
|
_buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto, value == FanSpeeds.auto),
|
||||||
value == FanSpeeds.auto),
|
_buildIconContainer(context, FanSpeeds.low, Assets.acFanLow, value == FanSpeeds.low),
|
||||||
_buildIconContainer(context, FanSpeeds.low, Assets.acFanLow,
|
|
||||||
value == FanSpeeds.low),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -45,10 +38,8 @@ class FanSpeedControl extends StatelessWidget {
|
|||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
_buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle,
|
_buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle, value == FanSpeeds.middle),
|
||||||
value == FanSpeeds.middle),
|
_buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh, value == FanSpeeds.high),
|
||||||
_buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh,
|
|
||||||
value == FanSpeeds.high),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -56,8 +47,7 @@ class FanSpeedControl extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildIconContainer(BuildContext context, FanSpeeds speed,
|
Widget _buildIconContainer(BuildContext context, FanSpeeds speed, String assetPath, bool isSelected) {
|
||||||
String assetPath, bool isSelected) {
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<AcBloc>().add(
|
context.read<AcBloc>().add(
|
||||||
|
|||||||
@ -6,8 +6,7 @@ import 'package:syncrow_web/services/devices_mang_api.dart';
|
|||||||
part 'device_managment_event.dart';
|
part 'device_managment_event.dart';
|
||||||
part 'device_managment_state.dart';
|
part 'device_managment_state.dart';
|
||||||
|
|
||||||
class DeviceManagementBloc
|
class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementState> {
|
||||||
extends Bloc<DeviceManagementEvent, DeviceManagementState> {
|
|
||||||
int _selectedIndex = 0;
|
int _selectedIndex = 0;
|
||||||
List<AllDevicesModel> _devices = [];
|
List<AllDevicesModel> _devices = [];
|
||||||
int _onlineCount = 0;
|
int _onlineCount = 0;
|
||||||
@ -15,7 +14,9 @@ class DeviceManagementBloc
|
|||||||
int _lowBatteryCount = 0;
|
int _lowBatteryCount = 0;
|
||||||
List<AllDevicesModel> _selectedDevices = [];
|
List<AllDevicesModel> _selectedDevices = [];
|
||||||
List<AllDevicesModel> _filteredDevices = [];
|
List<AllDevicesModel> _filteredDevices = [];
|
||||||
String productName = '';
|
String currentProductName = '';
|
||||||
|
String? currentCommunity;
|
||||||
|
String? currentUnitName;
|
||||||
|
|
||||||
DeviceManagementBloc() : super(DeviceManagementInitial()) {
|
DeviceManagementBloc() : super(DeviceManagementInitial()) {
|
||||||
on<FetchDevices>(_onFetchDevices);
|
on<FetchDevices>(_onFetchDevices);
|
||||||
@ -28,8 +29,7 @@ class DeviceManagementBloc
|
|||||||
on<UpdateSelection>(_onUpdateSelection);
|
on<UpdateSelection>(_onUpdateSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchDevices(
|
Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async {
|
||||||
FetchDevices event, Emitter<DeviceManagementState> emit) async {
|
|
||||||
emit(DeviceManagementLoading());
|
emit(DeviceManagementLoading());
|
||||||
try {
|
try {
|
||||||
final devices = await DevicesManagementApi().fetchDevices();
|
final devices = await DevicesManagementApi().fetchDevices();
|
||||||
@ -51,8 +51,7 @@ class DeviceManagementBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onFilterDevices(
|
void _onFilterDevices(FilterDevices event, Emitter<DeviceManagementState> emit) async {
|
||||||
FilterDevices event, Emitter<DeviceManagementState> emit) async {
|
|
||||||
if (_devices.isNotEmpty) {
|
if (_devices.isNotEmpty) {
|
||||||
_filteredDevices = List.from(_devices.where((device) {
|
_filteredDevices = List.from(_devices.where((device) {
|
||||||
switch (event.filter) {
|
switch (event.filter) {
|
||||||
@ -77,15 +76,14 @@ class DeviceManagementBloc
|
|||||||
isControlButtonEnabled: _selectedDevices.isNotEmpty,
|
isControlButtonEnabled: _selectedDevices.isNotEmpty,
|
||||||
));
|
));
|
||||||
|
|
||||||
if (productName.isNotEmpty) {
|
if (currentProductName.isNotEmpty) {
|
||||||
add(SearchDevices(productName: productName));
|
add(SearchDevices(productName: currentProductName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onResetFilters(
|
Future<void> _onResetFilters(ResetFilters event, Emitter<DeviceManagementState> emit) async {
|
||||||
ResetFilters event, Emitter<DeviceManagementState> emit) async {
|
currentProductName = '';
|
||||||
productName = '';
|
|
||||||
_selectedDevices.clear();
|
_selectedDevices.clear();
|
||||||
_filteredDevices = List.from(_devices);
|
_filteredDevices = List.from(_devices);
|
||||||
_selectedIndex = 0;
|
_selectedIndex = 0;
|
||||||
@ -100,8 +98,7 @@ class DeviceManagementBloc
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onResetSelectedDevices(
|
void _onResetSelectedDevices(ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
|
||||||
ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
|
|
||||||
_selectedDevices.clear();
|
_selectedDevices.clear();
|
||||||
|
|
||||||
if (state is DeviceManagementLoaded) {
|
if (state is DeviceManagementLoaded) {
|
||||||
@ -127,14 +124,12 @@ class DeviceManagementBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelectedFilterChanged(
|
void _onSelectedFilterChanged(SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
|
||||||
SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
|
|
||||||
_selectedIndex = event.selectedIndex;
|
_selectedIndex = event.selectedIndex;
|
||||||
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelectDevice(
|
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
|
||||||
SelectDevice event, Emitter<DeviceManagementState> emit) {
|
|
||||||
final selectedUuid = event.selectedDevice.uuid;
|
final selectedUuid = event.selectedDevice.uuid;
|
||||||
|
|
||||||
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
||||||
@ -145,8 +140,7 @@ class DeviceManagementBloc
|
|||||||
|
|
||||||
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
|
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
|
||||||
|
|
||||||
bool isControlButtonEnabled =
|
bool isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices);
|
||||||
_checkIfControlButtonEnabled(clonedSelectedDevices);
|
|
||||||
|
|
||||||
if (state is DeviceManagementLoaded) {
|
if (state is DeviceManagementLoaded) {
|
||||||
emit(DeviceManagementLoaded(
|
emit(DeviceManagementLoaded(
|
||||||
@ -155,8 +149,7 @@ class DeviceManagementBloc
|
|||||||
onlineCount: _onlineCount,
|
onlineCount: _onlineCount,
|
||||||
offlineCount: _offlineCount,
|
offlineCount: _offlineCount,
|
||||||
lowBatteryCount: _lowBatteryCount,
|
lowBatteryCount: _lowBatteryCount,
|
||||||
selectedDevice:
|
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
||||||
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
|
||||||
isControlButtonEnabled: isControlButtonEnabled,
|
isControlButtonEnabled: isControlButtonEnabled,
|
||||||
));
|
));
|
||||||
} else if (state is DeviceManagementFiltered) {
|
} else if (state is DeviceManagementFiltered) {
|
||||||
@ -166,15 +159,13 @@ class DeviceManagementBloc
|
|||||||
onlineCount: _onlineCount,
|
onlineCount: _onlineCount,
|
||||||
offlineCount: _offlineCount,
|
offlineCount: _offlineCount,
|
||||||
lowBatteryCount: _lowBatteryCount,
|
lowBatteryCount: _lowBatteryCount,
|
||||||
selectedDevice:
|
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
||||||
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
|
||||||
isControlButtonEnabled: isControlButtonEnabled,
|
isControlButtonEnabled: isControlButtonEnabled,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateSelection(
|
void _onUpdateSelection(UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
||||||
UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
|
||||||
List<AllDevicesModel> selectedDevices = [];
|
List<AllDevicesModel> selectedDevices = [];
|
||||||
List<AllDevicesModel> devicesToSelectFrom = [];
|
List<AllDevicesModel> devicesToSelectFrom = [];
|
||||||
|
|
||||||
@ -217,8 +208,7 @@ class DeviceManagementBloc
|
|||||||
|
|
||||||
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
||||||
if (selectedDevices.length > 1) {
|
if (selectedDevices.length > 1) {
|
||||||
final productTypes =
|
final productTypes = selectedDevices.map((device) => device.productType).toSet();
|
||||||
selectedDevices.map((device) => device.productType).toSet();
|
|
||||||
return productTypes.length == 1;
|
return productTypes.length == 1;
|
||||||
} else if (selectedDevices.length == 1) {
|
} else if (selectedDevices.length == 1) {
|
||||||
return true;
|
return true;
|
||||||
@ -229,10 +219,8 @@ class DeviceManagementBloc
|
|||||||
void _calculateDeviceCounts() {
|
void _calculateDeviceCounts() {
|
||||||
_onlineCount = _devices.where((device) => device.online == true).length;
|
_onlineCount = _devices.where((device) => device.online == true).length;
|
||||||
_offlineCount = _devices.where((device) => device.online == false).length;
|
_offlineCount = _devices.where((device) => device.online == false).length;
|
||||||
_lowBatteryCount = _devices
|
_lowBatteryCount =
|
||||||
.where((device) =>
|
_devices.where((device) => device.batteryLevel != null && device.batteryLevel! < 20).length;
|
||||||
device.batteryLevel != null && device.batteryLevel! < 20)
|
|
||||||
.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getFilterFromIndex(int index) {
|
String _getFilterFromIndex(int index) {
|
||||||
@ -248,53 +236,48 @@ class DeviceManagementBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSearchDevices(
|
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||||
SearchDevices event, Emitter<DeviceManagementState> emit) {
|
|
||||||
if ((event.community == null || event.community!.isEmpty) &&
|
if ((event.community == null || event.community!.isEmpty) &&
|
||||||
(event.unitName == null || event.unitName!.isEmpty) &&
|
(event.unitName == null || event.unitName!.isEmpty) &&
|
||||||
(event.productName == null || event.productName!.isEmpty)) {
|
(event.productName == null || event.productName!.isEmpty)) {
|
||||||
productName = '';
|
currentProductName = '';
|
||||||
if (state is DeviceManagementFiltered) {
|
if (state is DeviceManagementFiltered) {
|
||||||
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
productName = event.productName ?? '';
|
if (event.productName == currentProductName &&
|
||||||
|
event.community == currentCommunity &&
|
||||||
|
event.unitName == currentUnitName &&
|
||||||
|
event.searchField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProductName = event.productName ?? '';
|
||||||
|
currentCommunity = event.community;
|
||||||
|
currentUnitName = event.unitName;
|
||||||
|
|
||||||
List<AllDevicesModel> devicesToSearch = _filteredDevices;
|
List<AllDevicesModel> devicesToSearch = _filteredDevices;
|
||||||
|
|
||||||
if (devicesToSearch.isNotEmpty) {
|
if (devicesToSearch.isNotEmpty) {
|
||||||
_selectedDevices.clear();
|
|
||||||
_selectedIndex = _selectedIndex;
|
|
||||||
|
|
||||||
final filteredDevices = devicesToSearch.where((device) {
|
final filteredDevices = devicesToSearch.where((device) {
|
||||||
final matchesCommunity = event.community == null ||
|
final matchesCommunity = event.community == null ||
|
||||||
event.community!.isEmpty ||
|
event.community!.isEmpty ||
|
||||||
(device.room?.name
|
(device.room?.name?.toLowerCase().contains(event.community!.toLowerCase()) ?? false);
|
||||||
?.toLowerCase()
|
|
||||||
.contains(event.community!.toLowerCase()) ??
|
|
||||||
false);
|
|
||||||
final matchesUnit = event.unitName == null ||
|
final matchesUnit = event.unitName == null ||
|
||||||
event.unitName!.isEmpty ||
|
event.unitName!.isEmpty ||
|
||||||
(device.unit?.name
|
(device.unit?.name?.toLowerCase().contains(event.unitName!.toLowerCase()) ?? false);
|
||||||
?.toLowerCase()
|
|
||||||
.contains(event.unitName!.toLowerCase()) ??
|
|
||||||
false);
|
|
||||||
final matchesProductName = event.productName == null ||
|
final matchesProductName = event.productName == null ||
|
||||||
event.productName!.isEmpty ||
|
event.productName!.isEmpty ||
|
||||||
(device.name
|
(device.name?.toLowerCase().contains(event.productName!.toLowerCase()) ?? false);
|
||||||
?.toLowerCase()
|
|
||||||
.contains(event.productName!.toLowerCase()) ??
|
|
||||||
false);
|
|
||||||
final matchesDeviceName = event.productName == null ||
|
final matchesDeviceName = event.productName == null ||
|
||||||
event.productName!.isEmpty ||
|
event.productName!.isEmpty ||
|
||||||
(device.categoryName
|
(device.categoryName?.toLowerCase().contains(event.productName!.toLowerCase()) ??
|
||||||
?.toLowerCase()
|
|
||||||
.contains(event.productName!.toLowerCase()) ??
|
|
||||||
false);
|
false);
|
||||||
|
|
||||||
return matchesCommunity &&
|
return matchesCommunity && matchesUnit && (matchesProductName || matchesDeviceName);
|
||||||
matchesUnit &&
|
|
||||||
(matchesProductName || matchesDeviceName);
|
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
emit(DeviceManagementFiltered(
|
emit(DeviceManagementFiltered(
|
||||||
|
|||||||
@ -31,11 +31,13 @@ class SearchDevices extends DeviceManagementEvent {
|
|||||||
final String? community;
|
final String? community;
|
||||||
final String? unitName;
|
final String? unitName;
|
||||||
final String? productName;
|
final String? productName;
|
||||||
|
final bool searchField;
|
||||||
|
|
||||||
const SearchDevices({
|
const SearchDevices({
|
||||||
this.community,
|
this.community,
|
||||||
this.unitName,
|
this.unitName,
|
||||||
this.productName,
|
this.productName,
|
||||||
|
this.searchField = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
|
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/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/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/utils/format_date_time.dart';
|
import 'package:syncrow_web/utils/format_date_time.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
@ -37,8 +37,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
offlineCount = state.offlineCount;
|
offlineCount = state.offlineCount;
|
||||||
lowBatteryCount = state.lowBatteryCount;
|
lowBatteryCount = state.lowBatteryCount;
|
||||||
isControlButtonEnabled = state.isControlButtonEnabled;
|
isControlButtonEnabled = state.isControlButtonEnabled;
|
||||||
selectedDevices = state.selectedDevice ??
|
selectedDevices = state.selectedDevice ?? [];
|
||||||
context.read<DeviceManagementBloc>().selectedDevices;
|
|
||||||
} else if (state is DeviceManagementFiltered) {
|
} else if (state is DeviceManagementFiltered) {
|
||||||
devicesToShow = state.filteredDevices;
|
devicesToShow = state.filteredDevices;
|
||||||
selectedIndex = state.selectedIndex;
|
selectedIndex = state.selectedIndex;
|
||||||
@ -46,14 +45,12 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
offlineCount = state.offlineCount;
|
offlineCount = state.offlineCount;
|
||||||
lowBatteryCount = state.lowBatteryCount;
|
lowBatteryCount = state.lowBatteryCount;
|
||||||
isControlButtonEnabled = state.isControlButtonEnabled;
|
isControlButtonEnabled = state.isControlButtonEnabled;
|
||||||
selectedDevices = state.selectedDevice ??
|
selectedDevices = state.selectedDevice ?? [];
|
||||||
context.read<DeviceManagementBloc>().selectedDevices;
|
|
||||||
} else if (state is DeviceManagementInitial) {
|
} else if (state is DeviceManagementInitial) {
|
||||||
devicesToShow = [];
|
devicesToShow = [];
|
||||||
selectedIndex = 0;
|
selectedIndex = 0;
|
||||||
isControlButtonEnabled = false;
|
isControlButtonEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final tabs = [
|
final tabs = [
|
||||||
'All',
|
'All',
|
||||||
'Online ($onlineCount)',
|
'Online ($onlineCount)',
|
||||||
@ -61,15 +58,12 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
'Low Battery ($lowBatteryCount)',
|
'Low Battery ($lowBatteryCount)',
|
||||||
];
|
];
|
||||||
|
|
||||||
final buttonLabel =
|
final buttonLabel = (selectedDevices.length > 1) ? 'Batch Control' : 'Control';
|
||||||
(selectedDevices.length > 1) ? 'Batch Control' : 'Control';
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: isLargeScreenSize(context)
|
padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15),
|
||||||
? const EdgeInsets.all(30)
|
|
||||||
: const EdgeInsets.all(15),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -78,9 +72,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
tabs: tabs,
|
tabs: tabs,
|
||||||
selectedIndex: selectedIndex,
|
selectedIndex: selectedIndex,
|
||||||
onTabChanged: (index) {
|
onTabChanged: (index) {
|
||||||
context
|
context.read<DeviceManagementBloc>().add(SelectedFilterChanged(index));
|
||||||
.read<DeviceManagementBloc>()
|
|
||||||
.add(SelectedFilterChanged(index));
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
@ -102,14 +94,11 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if (selectedDevices.length > 1) {
|
} else if (selectedDevices.length > 1) {
|
||||||
final productTypes = selectedDevices
|
final productTypes = selectedDevices.map((device) => device.productType).toSet();
|
||||||
.map((device) => device.productType)
|
|
||||||
.toSet();
|
|
||||||
if (productTypes.length == 1) {
|
if (productTypes.length == 1) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) =>
|
builder: (context) => DeviceBatchControlDialog(
|
||||||
DeviceBatchControlDialog(
|
|
||||||
devices: selectedDevices,
|
devices: selectedDevices,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -123,9 +112,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: isControlButtonEnabled
|
color: isControlButtonEnabled ? Colors.white : Colors.grey,
|
||||||
? Colors.white
|
|
||||||
: Colors.grey,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -136,17 +123,13 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: isLargeScreenSize(context)
|
padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15),
|
||||||
? const EdgeInsets.all(30)
|
|
||||||
: const EdgeInsets.all(15),
|
|
||||||
child: DynamicTable(
|
child: DynamicTable(
|
||||||
withSelectAll: true,
|
withSelectAll: true,
|
||||||
cellDecoration: containerDecoration,
|
cellDecoration: containerDecoration,
|
||||||
onRowSelected: (index, isSelected, row) {
|
onRowSelected: (index, isSelected, row) {
|
||||||
final selectedDevice = devicesToShow[index];
|
final selectedDevice = devicesToShow[index];
|
||||||
context
|
context.read<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
|
||||||
.read<DeviceManagementBloc>()
|
|
||||||
.add(SelectDevice(selectedDevice));
|
|
||||||
},
|
},
|
||||||
withCheckBox: true,
|
withCheckBox: true,
|
||||||
size: context.screenSize,
|
size: context.screenSize,
|
||||||
@ -169,26 +152,17 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
device.uuid ?? '',
|
device.uuid ?? '',
|
||||||
device.unit?.name ?? '',
|
device.unit?.name ?? '',
|
||||||
device.room?.name ?? '',
|
device.room?.name ?? '',
|
||||||
device.batteryLevel != null
|
device.batteryLevel != null ? '${device.batteryLevel}%' : '-',
|
||||||
? '${device.batteryLevel}%'
|
formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.createTime ?? 0) * 1000)),
|
||||||
: '-',
|
|
||||||
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
|
|
||||||
(device.createTime ?? 0) * 1000)),
|
|
||||||
device.online == true ? 'Online' : 'Offline',
|
device.online == true ? 'Online' : 'Offline',
|
||||||
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
|
formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.updateTime ?? 0) * 1000)),
|
||||||
(device.updateTime ?? 0) * 1000)),
|
|
||||||
];
|
];
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onSelectionChanged: (selectedRows) {
|
onSelectionChanged: (selectedRows) {
|
||||||
context
|
context.read<DeviceManagementBloc>().add(UpdateSelection(selectedRows));
|
||||||
.read<DeviceManagementBloc>()
|
|
||||||
.add(UpdateSelection(selectedRows));
|
|
||||||
},
|
},
|
||||||
initialSelectedIds: context
|
initialSelectedIds:
|
||||||
.read<DeviceManagementBloc>()
|
context.read<DeviceManagementBloc>().selectedDevices.map((device) => device.uuid!).toList(),
|
||||||
.selectedDevices
|
|
||||||
.map((device) => device.uuid!)
|
|
||||||
.toList(),
|
|
||||||
isEmpty: devicesToShow.isEmpty,
|
isEmpty: devicesToShow.isEmpty,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -12,8 +12,7 @@ class DeviceSearchFilters extends StatefulWidget {
|
|||||||
State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState();
|
State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
final TextEditingController communityController = TextEditingController();
|
final TextEditingController communityController = TextEditingController();
|
||||||
final TextEditingController unitNameController = TextEditingController();
|
final TextEditingController unitNameController = TextEditingController();
|
||||||
final TextEditingController productNameController = TextEditingController();
|
final TextEditingController productNameController = TextEditingController();
|
||||||
@ -35,8 +34,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
|||||||
const SizedBox(width: 20),
|
const SizedBox(width: 20),
|
||||||
_buildSearchField("Unit Name", unitNameController, 200),
|
_buildSearchField("Unit Name", unitNameController, 200),
|
||||||
const SizedBox(width: 20),
|
const SizedBox(width: 20),
|
||||||
_buildSearchField(
|
_buildSearchField("Device Name / Product Name", productNameController, 300),
|
||||||
"Device Name / Product Name", productNameController, 300),
|
|
||||||
const SizedBox(width: 20),
|
const SizedBox(width: 20),
|
||||||
_buildSearchResetButtons(),
|
_buildSearchResetButtons(),
|
||||||
],
|
],
|
||||||
@ -45,22 +43,35 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
|||||||
spacing: 20,
|
spacing: 20,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
children: [
|
children: [
|
||||||
_buildSearchField("Community", communityController, 200),
|
_buildSearchField(
|
||||||
|
"Community",
|
||||||
|
communityController,
|
||||||
|
200,
|
||||||
|
),
|
||||||
_buildSearchField("Unit Name", unitNameController, 200),
|
_buildSearchField("Unit Name", unitNameController, 200),
|
||||||
_buildSearchField(
|
_buildSearchField(
|
||||||
"Device Name / Product Name", productNameController, 300),
|
"Device Name / Product Name",
|
||||||
|
productNameController,
|
||||||
|
300,
|
||||||
|
),
|
||||||
_buildSearchResetButtons(),
|
_buildSearchResetButtons(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSearchField(
|
Widget _buildSearchField(String title, TextEditingController controller, double width) {
|
||||||
String title, TextEditingController controller, double width) {
|
|
||||||
return StatefulTextField(
|
return StatefulTextField(
|
||||||
title: title,
|
title: title,
|
||||||
width: width,
|
width: width,
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
onSubmitted: () {
|
||||||
|
context.read<DeviceManagementBloc>().add(SearchDevices(
|
||||||
|
productName: productNameController.text,
|
||||||
|
unitName: unitNameController.text,
|
||||||
|
community: communityController.text,
|
||||||
|
searchField: true));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +79,10 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
|||||||
return SearchResetButtons(
|
return SearchResetButtons(
|
||||||
onSearch: () {
|
onSearch: () {
|
||||||
context.read<DeviceManagementBloc>().add(SearchDevices(
|
context.read<DeviceManagementBloc>().add(SearchDevices(
|
||||||
community: communityController.text,
|
community: communityController.text,
|
||||||
unitName: unitNameController.text,
|
unitName: unitNameController.text,
|
||||||
productName: productNameController.text,
|
productName: productNameController.text,
|
||||||
));
|
searchField: true));
|
||||||
},
|
},
|
||||||
onReset: () {
|
onReset: () {
|
||||||
communityController.clear();
|
communityController.clear();
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/event.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/state.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/help_description.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/help_description.dart';
|
||||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
@ -27,8 +28,7 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
CeilingInitialEvent event, Emitter<CeilingSensorState> emit) async {
|
CeilingInitialEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
emit(CeilingLoadingInitialState());
|
emit(CeilingLoadingInitialState());
|
||||||
try {
|
try {
|
||||||
var response =
|
var response = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
|
||||||
deviceStatus = CeilingSensorModel.fromJson(response.status);
|
deviceStatus = CeilingSensorModel.fromJson(response.status);
|
||||||
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
||||||
// _listenToChanges();
|
// _listenToChanges();
|
||||||
@ -57,8 +57,7 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
// } catch (_) {}
|
// } catch (_) {}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void _changeValue(
|
void _changeValue(CeilingChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
CeilingChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
|
||||||
emit(CeilingLoadingNewSate(ceilingSensorModel: deviceStatus));
|
emit(CeilingLoadingNewSate(ceilingSensorModel: deviceStatus));
|
||||||
if (event.code == 'sensitivity') {
|
if (event.code == 'sensitivity') {
|
||||||
deviceStatus.sensitivity = event.value;
|
deviceStatus.sensitivity = event.value;
|
||||||
@ -123,8 +122,7 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
try {
|
try {
|
||||||
late bool response;
|
late bool response;
|
||||||
if (isBatch) {
|
if (isBatch) {
|
||||||
response = await DevicesManagementApi()
|
response = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
|
||||||
.deviceBatchControl(deviceId, code, value);
|
|
||||||
} else {
|
} else {
|
||||||
response = await DevicesManagementApi()
|
response = await DevicesManagementApi()
|
||||||
.deviceControl(deviceId, Status(code: code, value: value));
|
.deviceControl(deviceId, Status(code: code, value: value));
|
||||||
@ -145,17 +143,19 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _getDeviceReports(GetCeilingDeviceReportsEvent event,
|
FutureOr<void> _getDeviceReports(
|
||||||
Emitter<CeilingSensorState> emit) async {
|
GetCeilingDeviceReportsEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
if (event.code.isEmpty) {
|
if (event.code.isEmpty) {
|
||||||
emit(ShowCeilingDescriptionState(description: reportString));
|
emit(ShowCeilingDescriptionState(description: reportString));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
emit(CeilingReportsLoadingState());
|
emit(CeilingReportsLoadingState());
|
||||||
|
// final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch;
|
||||||
|
// final to = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await DevicesManagementApi.getDeviceReports(deviceId, event.code)
|
// await DevicesManagementApi.getDeviceReportsByDate(deviceId, event.code, from.toString(), to.toString())
|
||||||
.then((value) {
|
await DevicesManagementApi.getDeviceReports(deviceId, event.code).then((value) {
|
||||||
emit(CeilingReportsState(deviceReport: value));
|
emit(CeilingReportsState(deviceReport: value));
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -165,23 +165,19 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDescription(
|
void _showDescription(ShowCeilingDescriptionEvent event, Emitter<CeilingSensorState> emit) {
|
||||||
ShowCeilingDescriptionEvent event, Emitter<CeilingSensorState> emit) {
|
|
||||||
emit(ShowCeilingDescriptionState(description: event.description));
|
emit(ShowCeilingDescriptionState(description: event.description));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _backToGridView(
|
void _backToGridView(BackToCeilingGridViewEvent event, Emitter<CeilingSensorState> emit) {
|
||||||
BackToCeilingGridViewEvent event, Emitter<CeilingSensorState> emit) {
|
|
||||||
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _fetchCeilingSensorBatchControl(
|
FutureOr<void> _fetchCeilingSensorBatchControl(
|
||||||
CeilingFetchDeviceStatusEvent event,
|
CeilingFetchDeviceStatusEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
Emitter<CeilingSensorState> emit) async {
|
|
||||||
emit(CeilingLoadingInitialState());
|
emit(CeilingLoadingInitialState());
|
||||||
try {
|
try {
|
||||||
var response =
|
var response = await DevicesManagementApi().getBatchStatus(event.devicesIds);
|
||||||
await DevicesManagementApi().getBatchStatus(event.devicesIds);
|
|
||||||
deviceStatus = CeilingSensorModel.fromJson(response.status);
|
deviceStatus = CeilingSensorModel.fromJson(response.status);
|
||||||
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -46,22 +46,19 @@ class CeilingSensorModel {
|
|||||||
_spaceType = getSpaceType(status.value ?? 'none');
|
_spaceType = getSpaceType(status.value ?? 'none');
|
||||||
break;
|
break;
|
||||||
case 'sensitivity':
|
case 'sensitivity':
|
||||||
_sensitivity = status.value is int
|
_sensitivity =
|
||||||
? status.value
|
status.value is int ? status.value : int.tryParse(status.value ?? '1') ?? 1;
|
||||||
: int.tryParse(status.value ?? '1') ?? 1;
|
|
||||||
break;
|
break;
|
||||||
case 'checking_result':
|
case 'checking_result':
|
||||||
_checkingResult = status.value ?? '';
|
_checkingResult = status.value ?? '';
|
||||||
break;
|
break;
|
||||||
case 'presence_range':
|
case 'presence_range':
|
||||||
_presenceRange = status.value is int
|
_presenceRange =
|
||||||
? status.value
|
status.value is int ? status.value : int.tryParse(status.value ?? '0') ?? 0;
|
||||||
: int.tryParse(status.value ?? '0') ?? 0;
|
|
||||||
break;
|
break;
|
||||||
case 'sports_para':
|
case 'sports_para':
|
||||||
_sportsPara = status.value is int
|
_sportsPara =
|
||||||
? status.value
|
status.value is int ? status.value : int.tryParse(status.value ?? '0') ?? 0;
|
||||||
: int.tryParse(status.value ?? '0') ?? 0;
|
|
||||||
break;
|
break;
|
||||||
case 'body_movement':
|
case 'body_movement':
|
||||||
_bodyMovement = status.value ?? '';
|
_bodyMovement = status.value ?? '';
|
||||||
@ -70,9 +67,7 @@ class CeilingSensorModel {
|
|||||||
_noBodyTime = status.value ?? 'none';
|
_noBodyTime = status.value ?? 'none';
|
||||||
break;
|
break;
|
||||||
case 'moving_max_dis':
|
case 'moving_max_dis':
|
||||||
_maxDis = status.value is int
|
_maxDis = status.value is int ? status.value : int.tryParse(status.value ?? '0') ?? 0;
|
||||||
? status.value
|
|
||||||
: int.tryParse(status.value ?? '0') ?? 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/event.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/state.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
|
||||||
@ -12,8 +12,7 @@ import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presen
|
|||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presense_nobody_time.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presense_nobody_time.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
class CeilingSensorBatchControlView extends StatelessWidget
|
class CeilingSensorBatchControlView extends StatelessWidget with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
const CeilingSensorBatchControlView({super.key, required this.devicesIds});
|
const CeilingSensorBatchControlView({super.key, required this.devicesIds});
|
||||||
|
|
||||||
final List<String> devicesIds;
|
final List<String> devicesIds;
|
||||||
@ -28,12 +27,11 @@ class CeilingSensorBatchControlView extends StatelessWidget
|
|||||||
..add(CeilingFetchDeviceStatusEvent(devicesIds)),
|
..add(CeilingFetchDeviceStatusEvent(devicesIds)),
|
||||||
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is CeilingLoadingInitialState ||
|
if (state is CeilingLoadingInitialState || state is CeilingReportsLoadingState) {
|
||||||
state is CeilingReportsLoadingState) {
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (state is CeilingUpdateState) {
|
} else if (state is CeilingUpdateState) {
|
||||||
return _buildGridView(context, state.ceilingSensorModel,
|
return _buildGridView(
|
||||||
isExtraLarge, isLarge, isMedium);
|
context, state.ceilingSensorModel, isExtraLarge, isLarge, isMedium);
|
||||||
}
|
}
|
||||||
return const Center(child: Text('Error fetching status'));
|
return const Center(child: Text('Error fetching status'));
|
||||||
},
|
},
|
||||||
@ -41,8 +39,8 @@ class CeilingSensorBatchControlView extends StatelessWidget
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGridView(BuildContext context, CeilingSensorModel model,
|
Widget _buildGridView(BuildContext context, CeilingSensorModel model, bool isExtraLarge,
|
||||||
bool isExtraLarge, bool isLarge, bool isMedium) {
|
bool isLarge, bool isMedium) {
|
||||||
return GridView(
|
return GridView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
@ -118,8 +116,7 @@ class CeilingSensorBatchControlView extends StatelessWidget
|
|||||||
context.read<CeilingSensorBloc>().add(
|
context.read<CeilingSensorBloc>().add(
|
||||||
CeilingFactoryResetEvent(
|
CeilingFactoryResetEvent(
|
||||||
devicesId: devicesIds.first,
|
devicesId: devicesIds.first,
|
||||||
factoryResetModel:
|
factoryResetModel: FactoryResetModel(devicesUuid: devicesIds),
|
||||||
FactoryResetModel(devicesUuid: devicesIds),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/event.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/state.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_display_data.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_display_data.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_space_type.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_space_type.dart';
|
||||||
@ -16,8 +16,7 @@ import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dar
|
|||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
class CeilingSensorControlsView extends StatelessWidget
|
class CeilingSensorControlsView extends StatelessWidget with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
const CeilingSensorControlsView({super.key, required this.device});
|
const CeilingSensorControlsView({super.key, required this.device});
|
||||||
|
|
||||||
final AllDevicesModel device;
|
final AllDevicesModel device;
|
||||||
@ -32,35 +31,29 @@ class CeilingSensorControlsView extends StatelessWidget
|
|||||||
..add(CeilingInitialEvent(device.uuid ?? '')),
|
..add(CeilingInitialEvent(device.uuid ?? '')),
|
||||||
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is CeilingLoadingInitialState ||
|
if (state is CeilingLoadingInitialState || state is CeilingReportsLoadingState) {
|
||||||
state is CeilingReportsLoadingState) {
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (state is CeilingUpdateState) {
|
} else if (state is CeilingUpdateState) {
|
||||||
return _buildGridView(context, state.ceilingSensorModel,
|
return _buildGridView(
|
||||||
isExtraLarge, isLarge, isMedium);
|
context, state.ceilingSensorModel, isExtraLarge, isLarge, isMedium);
|
||||||
} else if (state is CeilingReportsState) {
|
} else if (state is CeilingReportsState) {
|
||||||
return ReportsTable(
|
return ReportsTable(
|
||||||
report: state.deviceReport,
|
report: state.deviceReport,
|
||||||
onRowTap: (index) {},
|
onRowTap: (index) {},
|
||||||
onClose: () {
|
onClose: () {
|
||||||
context
|
context.read<CeilingSensorBloc>().add(BackToCeilingGridViewEvent());
|
||||||
.read<CeilingSensorBloc>()
|
|
||||||
.add(BackToCeilingGridViewEvent());
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (state is ShowCeilingDescriptionState) {
|
} else if (state is ShowCeilingDescriptionState) {
|
||||||
return DescriptionView(
|
return DescriptionView(
|
||||||
description: state.description,
|
description: state.description,
|
||||||
onClose: () {
|
onClose: () {
|
||||||
context
|
context.read<CeilingSensorBloc>().add(BackToCeilingGridViewEvent());
|
||||||
.read<CeilingSensorBloc>()
|
|
||||||
.add(BackToCeilingGridViewEvent());
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (state is CeilingReportsFailedState) {
|
} else if (state is CeilingReportsFailedState) {
|
||||||
final model = context.read<CeilingSensorBloc>().deviceStatus;
|
final model = context.read<CeilingSensorBloc>().deviceStatus;
|
||||||
return _buildGridView(
|
return _buildGridView(context, model, isExtraLarge, isLarge, isMedium);
|
||||||
context, model, isExtraLarge, isLarge, isMedium);
|
|
||||||
}
|
}
|
||||||
return const Center(child: Text('Error fetching status'));
|
return const Center(child: Text('Error fetching status'));
|
||||||
},
|
},
|
||||||
@ -68,8 +61,8 @@ class CeilingSensorControlsView extends StatelessWidget
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGridView(BuildContext context, CeilingSensorModel model,
|
Widget _buildGridView(BuildContext context, CeilingSensorModel model, bool isExtraLarge,
|
||||||
bool isExtraLarge, bool isLarge, bool isMedium) {
|
bool isLarge, bool isMedium) {
|
||||||
return GridView(
|
return GridView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
@ -150,8 +143,8 @@ class CeilingSensorControlsView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<CeilingSensorBloc>().add(GetCeilingDeviceReportsEvent(
|
context.read<CeilingSensorBloc>().add(
|
||||||
code: 'presence_state', deviceUuid: device.uuid!));
|
GetCeilingDeviceReportsEvent(code: 'presence_state', deviceUuid: device.uuid!));
|
||||||
},
|
},
|
||||||
child: const PresenceStaticWidget(
|
child: const PresenceStaticWidget(
|
||||||
icon: Assets.illuminanceRecordIcon,
|
icon: Assets.illuminanceRecordIcon,
|
||||||
@ -160,8 +153,9 @@ class CeilingSensorControlsView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<CeilingSensorBloc>().add(GetCeilingDeviceReportsEvent(
|
context
|
||||||
code: '', deviceUuid: device.uuid!));
|
.read<CeilingSensorBloc>()
|
||||||
|
.add(GetCeilingDeviceReportsEvent(code: '', deviceUuid: device.uuid!));
|
||||||
},
|
},
|
||||||
child: const PresenceStaticWidget(
|
child: const PresenceStaticWidget(
|
||||||
icon: Assets.helpDescriptionIcon,
|
icon: Assets.helpDescriptionIcon,
|
||||||
|
|||||||
@ -38,14 +38,13 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
on<GarageDoorBatchControlEvent>(_onBatchControl);
|
on<GarageDoorBatchControlEvent>(_onBatchControl);
|
||||||
on<GarageDoorFetchBatchStatusEvent>(_onFetchBatchStatus);
|
on<GarageDoorFetchBatchStatusEvent>(_onFetchBatchStatus);
|
||||||
on<GarageDoorFactoryResetEvent>(_onFactoryReset);
|
on<GarageDoorFactoryResetEvent>(_onFactoryReset);
|
||||||
|
on<EditGarageDoorScheduleEvent>(_onEditSchedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchGarageDoorStatus(
|
void _fetchGarageDoorStatus(GarageDoorInitialEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
GarageDoorInitialEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
emit(GarageDoorLoadingState());
|
emit(GarageDoorLoadingState());
|
||||||
try {
|
try {
|
||||||
var response =
|
var response = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
|
||||||
deviceStatus = GarageDoorStatusModel.fromJson(deviceId, response.status);
|
deviceStatus = GarageDoorStatusModel.fromJson(deviceId, response.status);
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -53,22 +52,18 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchBatchStatus(GarageDoorFetchBatchStatusEvent event,
|
Future<void> _onFetchBatchStatus(GarageDoorFetchBatchStatusEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
Emitter<GarageDoorState> emit) async {
|
|
||||||
emit(GarageDoorLoadingState());
|
emit(GarageDoorLoadingState());
|
||||||
try {
|
try {
|
||||||
final status =
|
final status = await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
||||||
await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
deviceStatus = GarageDoorStatusModel.fromJson(event.deviceIds.first, status.status);
|
||||||
deviceStatus =
|
|
||||||
GarageDoorStatusModel.fromJson(event.deviceIds.first, status.status);
|
|
||||||
emit(GarageDoorBatchStatusLoaded(deviceStatus));
|
emit(GarageDoorBatchStatusLoaded(deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(GarageDoorBatchControlError(e.toString()));
|
emit(GarageDoorBatchControlError(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _addSchedule(
|
Future<void> _addSchedule(AddGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
AddGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
ScheduleEntry newSchedule = ScheduleEntry(
|
ScheduleEntry newSchedule = ScheduleEntry(
|
||||||
category: event.category,
|
category: event.category,
|
||||||
@ -76,11 +71,9 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
function: Status(code: 'switch_1', value: event.functionOn),
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||||
);
|
);
|
||||||
bool success =
|
bool success = await DevicesManagementApi().addScheduleRecord(newSchedule, deviceId);
|
||||||
await DevicesManagementApi().addScheduleRecord(newSchedule, deviceId);
|
|
||||||
if (success) {
|
if (success) {
|
||||||
add(FetchGarageDoorSchedulesEvent(
|
add(FetchGarageDoorSchedulesEvent(deviceId: deviceId, category: 'switch_1'));
|
||||||
deviceId: deviceId, category: 'switch_1'));
|
|
||||||
} else {
|
} else {
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
}
|
}
|
||||||
@ -89,19 +82,16 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateCountdownAlarm(
|
void _onUpdateCountdownAlarm(UpdateCountdownAlarmEvent event, Emitter<GarageDoorState> emit) {
|
||||||
UpdateCountdownAlarmEvent event, Emitter<GarageDoorState> emit) {
|
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is GarageDoorLoadedState) {
|
if (currentState is GarageDoorLoadedState) {
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(
|
||||||
status:
|
status: currentState.status.copyWith(countdownAlarm: event.countdownAlarm),
|
||||||
currentState.status.copyWith(countdownAlarm: event.countdownAlarm),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateTrTimeCon(
|
void _onUpdateTrTimeCon(UpdateTrTimeConEvent event, Emitter<GarageDoorState> emit) {
|
||||||
UpdateTrTimeConEvent event, Emitter<GarageDoorState> emit) {
|
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is GarageDoorLoadedState) {
|
if (currentState is GarageDoorLoadedState) {
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(
|
||||||
@ -110,8 +100,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateSchedule(UpdateGarageDoorScheduleEvent event,
|
Future<void> _updateSchedule(UpdateGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
Emitter<GarageDoorState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
final updatedSchedules = deviceStatus.schedules?.map((schedule) {
|
final updatedSchedules = deviceStatus.schedules?.map((schedule) {
|
||||||
if (schedule.scheduleId == event.scheduleId) {
|
if (schedule.scheduleId == event.scheduleId) {
|
||||||
@ -138,15 +127,12 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _deleteSchedule(DeleteGarageDoorScheduleEvent event,
|
Future<void> _deleteSchedule(DeleteGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
Emitter<GarageDoorState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
bool success = await DevicesManagementApi()
|
bool success = await DevicesManagementApi().deleteScheduleRecord(deviceStatus.uuid, event.scheduleId);
|
||||||
.deleteScheduleRecord(deviceStatus.uuid, event.scheduleId);
|
|
||||||
if (success) {
|
if (success) {
|
||||||
final updatedSchedules = deviceStatus.schedules
|
final updatedSchedules =
|
||||||
?.where((schedule) => schedule.scheduleId != event.scheduleId)
|
deviceStatus.schedules?.where((schedule) => schedule.scheduleId != event.scheduleId).toList();
|
||||||
.toList();
|
|
||||||
deviceStatus = deviceStatus.copyWith(schedules: updatedSchedules);
|
deviceStatus = deviceStatus.copyWith(schedules: updatedSchedules);
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
} else {
|
} else {
|
||||||
@ -157,12 +143,11 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _fetchSchedules(FetchGarageDoorSchedulesEvent event,
|
Future<void> _fetchSchedules(FetchGarageDoorSchedulesEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
Emitter<GarageDoorState> emit) async {
|
|
||||||
emit(ScheduleGarageLoadingState());
|
emit(ScheduleGarageLoadingState());
|
||||||
try {
|
try {
|
||||||
List<ScheduleModel> schedules = await DevicesManagementApi()
|
List<ScheduleModel> schedules =
|
||||||
.getDeviceSchedules(deviceStatus.uuid, event.category);
|
await DevicesManagementApi().getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||||
deviceStatus = deviceStatus.copyWith(schedules: schedules);
|
deviceStatus = deviceStatus.copyWith(schedules: schedules);
|
||||||
emit(
|
emit(
|
||||||
GarageDoorLoadedState(
|
GarageDoorLoadedState(
|
||||||
@ -180,37 +165,30 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateSelectedTime(
|
Future<void> _updateSelectedTime(UpdateSelectedTimeEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
UpdateSelectedTimeEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is GarageDoorLoadedState) {
|
if (currentState is GarageDoorLoadedState) {
|
||||||
emit(currentState.copyWith(selectedTime: event.selectedTime));
|
emit(currentState.copyWith(selectedTime: event.selectedTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateSelectedDay(
|
Future<void> _updateSelectedDay(UpdateSelectedDayEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
UpdateSelectedDayEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is GarageDoorLoadedState) {
|
if (currentState is GarageDoorLoadedState) {
|
||||||
List<bool> updatedDays = List.from(currentState.selectedDays);
|
List<bool> updatedDays = List.from(currentState.selectedDays);
|
||||||
updatedDays[event.dayIndex] = event.isSelected;
|
updatedDays[event.dayIndex] = event.isSelected;
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
||||||
selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateFunctionOn(
|
Future<void> _updateFunctionOn(UpdateFunctionOnEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
UpdateFunctionOnEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is GarageDoorLoadedState) {
|
if (currentState is GarageDoorLoadedState) {
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(functionOn: event.functionOn, selectedTime: currentState.selectedTime));
|
||||||
functionOn: event.functionOn,
|
|
||||||
selectedTime: currentState.selectedTime));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initializeAddSchedule(
|
Future<void> _initializeAddSchedule(InitializeAddScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
InitializeAddScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is GarageDoorLoadedState) {
|
if (currentState is GarageDoorLoadedState) {
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(
|
||||||
@ -222,25 +200,20 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _fetchRecords(
|
Future<void> _fetchRecords(FetchGarageDoorRecordsEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
FetchGarageDoorRecordsEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
emit(GarageDoorReportsLoadingState());
|
emit(GarageDoorReportsLoadingState());
|
||||||
try {
|
try {
|
||||||
final from = DateTime.now()
|
final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch;
|
||||||
.subtract(const Duration(days: 30))
|
|
||||||
.millisecondsSinceEpoch;
|
|
||||||
final to = DateTime.now().millisecondsSinceEpoch;
|
final to = DateTime.now().millisecondsSinceEpoch;
|
||||||
final DeviceReport records =
|
final DeviceReport records =
|
||||||
await DevicesManagementApi.getDeviceReportsByDate(
|
await DevicesManagementApi.getDeviceReportsByDate(event.deviceId, 'switch_1', from.toString(), to.toString());
|
||||||
event.deviceId, 'switch_1', from.toString(), to.toString());
|
|
||||||
emit(GarageDoorReportsState(deviceReport: records));
|
emit(GarageDoorReportsState(deviceReport: records));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(GarageDoorReportsFailedState(error: e.toString()));
|
emit(GarageDoorReportsFailedState(error: e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onBatchControl(
|
Future<void> _onBatchControl(GarageDoorBatchControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
GarageDoorBatchControlEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
final oldValue = event.code == 'switch_1' ? deviceStatus.switch1 : false;
|
final oldValue = event.code == 'switch_1' ? deviceStatus.switch1 : false;
|
||||||
|
|
||||||
_updateLocalValue(event.code, event.value);
|
_updateLocalValue(event.code, event.value);
|
||||||
@ -260,13 +233,11 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _backToGridView(
|
void _backToGridView(BackToGarageDoorGridViewEvent event, Emitter<GarageDoorState> emit) {
|
||||||
BackToGarageDoorGridViewEvent event, Emitter<GarageDoorState> emit) {
|
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleUpdate(
|
void _handleUpdate(GarageDoorUpdatedEvent event, Emitter<GarageDoorState> emit) {
|
||||||
GarageDoorUpdatedEvent event, Emitter<GarageDoorState> emit) {
|
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,11 +253,9 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
late bool status;
|
late bool status;
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
if (isBatch) {
|
if (isBatch) {
|
||||||
status = await DevicesManagementApi()
|
status = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
|
||||||
.deviceBatchControl(deviceId, code, value);
|
|
||||||
} else {
|
} else {
|
||||||
status = await DevicesManagementApi()
|
status = await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
|
||||||
.deviceControl(deviceId, Status(code: code, value: value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
@ -301,12 +270,10 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFactoryReset(
|
Future<void> _onFactoryReset(GarageDoorFactoryResetEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
GarageDoorFactoryResetEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
emit(GarageDoorLoadingState());
|
emit(GarageDoorLoadingState());
|
||||||
try {
|
try {
|
||||||
final response = await DevicesManagementApi()
|
final response = await DevicesManagementApi().factoryReset(event.factoryReset, event.deviceId);
|
||||||
.factoryReset(event.factoryReset, event.deviceId);
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
emit(const GarageDoorErrorState(message: 'Failed to reset device'));
|
emit(const GarageDoorErrorState(message: 'Failed to reset device'));
|
||||||
} else {
|
} else {
|
||||||
@ -317,47 +284,34 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _increaseDelay(
|
void _increaseDelay(IncreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
IncreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
// if (deviceStatus.countdown1 != 0) {
|
// if (deviceStatus.countdown1 != 0) {
|
||||||
try {
|
try {
|
||||||
deviceStatus = deviceStatus.copyWith(
|
deviceStatus = deviceStatus.copyWith(delay: deviceStatus.delay + Duration(minutes: 10));
|
||||||
delay: deviceStatus.delay + Duration(minutes: 10));
|
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
add(GarageDoorControlEvent(
|
add(GarageDoorControlEvent(deviceId: event.deviceId, value: deviceStatus.delay.inSeconds, code: 'countdown_1'));
|
||||||
deviceId: event.deviceId,
|
|
||||||
value: deviceStatus.delay.inSeconds,
|
|
||||||
code: 'countdown_1'));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(GarageDoorErrorState(message: e.toString()));
|
emit(GarageDoorErrorState(message: e.toString()));
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void _decreaseDelay(
|
void _decreaseDelay(DecreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
DecreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
|
||||||
// if (deviceStatus.countdown1 != 0) {
|
// if (deviceStatus.countdown1 != 0) {
|
||||||
try {
|
try {
|
||||||
if (deviceStatus.delay.inMinutes > 10) {
|
if (deviceStatus.delay.inMinutes > 10) {
|
||||||
deviceStatus = deviceStatus.copyWith(
|
deviceStatus = deviceStatus.copyWith(delay: deviceStatus.delay - Duration(minutes: 10));
|
||||||
delay: deviceStatus.delay - Duration(minutes: 10));
|
|
||||||
}
|
}
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
add(GarageDoorControlEvent(
|
add(GarageDoorControlEvent(deviceId: event.deviceId, value: deviceStatus.delay.inSeconds, code: 'countdown_1'));
|
||||||
deviceId: event.deviceId,
|
|
||||||
value: deviceStatus.delay.inSeconds,
|
|
||||||
code: 'countdown_1'));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(GarageDoorErrorState(message: e.toString()));
|
emit(GarageDoorErrorState(message: e.toString()));
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _garageDoorControlEvent(
|
void _garageDoorControlEvent(GarageDoorControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
GarageDoorControlEvent event, Emitter<GarageDoorState> emit) async {
|
final oldValue = event.code == 'countdown_1' ? deviceStatus.countdown1 : deviceStatus.switch1;
|
||||||
final oldValue = event.code == 'countdown_1'
|
|
||||||
? deviceStatus.countdown1
|
|
||||||
: deviceStatus.switch1;
|
|
||||||
_updateLocalValue(event.code, event.value);
|
_updateLocalValue(event.code, event.value);
|
||||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
final success = await _runDeBouncer(
|
final success = await _runDeBouncer(
|
||||||
@ -373,8 +327,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _revertValue(
|
void _revertValue(String code, dynamic oldValue, Emitter<GarageDoorState> emit) {
|
||||||
String code, dynamic oldValue, Emitter<GarageDoorState> emit) {
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'switch_1':
|
case 'switch_1':
|
||||||
if (oldValue is bool) {
|
if (oldValue is bool) {
|
||||||
@ -383,8 +336,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
break;
|
break;
|
||||||
case 'countdown_1':
|
case 'countdown_1':
|
||||||
if (oldValue is int) {
|
if (oldValue is int) {
|
||||||
deviceStatus = deviceStatus.copyWith(
|
deviceStatus = deviceStatus.copyWith(countdown1: oldValue, delay: Duration(seconds: oldValue));
|
||||||
countdown1: oldValue, delay: Duration(seconds: oldValue));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Add other cases if needed
|
// Add other cases if needed
|
||||||
@ -406,8 +358,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
break;
|
break;
|
||||||
case 'countdown_1':
|
case 'countdown_1':
|
||||||
if (value is int) {
|
if (value is int) {
|
||||||
deviceStatus = deviceStatus.copyWith(
|
deviceStatus = deviceStatus.copyWith(countdown1: value, delay: Duration(seconds: value));
|
||||||
countdown1: value, delay: Duration(seconds: value));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'countdown_alarm':
|
case 'countdown_alarm':
|
||||||
@ -420,6 +371,25 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
deviceStatus = deviceStatus.copyWith(trTimeCon: value);
|
deviceStatus = deviceStatus.copyWith(trTimeCon: value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'door_state_1':
|
||||||
|
if (value is String) {
|
||||||
|
deviceStatus = deviceStatus.copyWith(doorState1: value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'door_control_1':
|
||||||
|
if (value is String) {
|
||||||
|
deviceStatus = deviceStatus.copyWith(doorControl1: value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'voice_control_1':
|
||||||
|
if (value is bool) {
|
||||||
|
deviceStatus = deviceStatus.copyWith(voiceControl1: value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'door_contact_state':
|
||||||
|
if (value is bool) {
|
||||||
|
deviceStatus = deviceStatus.copyWith(doorContactState: value);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -430,4 +400,24 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
|||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FutureOr<void> _onEditSchedule(EditGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||||
|
try {
|
||||||
|
ScheduleEntry newSchedule = ScheduleEntry(
|
||||||
|
scheduleId: event.scheduleId,
|
||||||
|
category: event.category,
|
||||||
|
time: formatTimeOfDayToISO(event.time),
|
||||||
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
|
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||||
|
);
|
||||||
|
bool success = await DevicesManagementApi().editScheduleRecord(deviceId, newSchedule);
|
||||||
|
if (success) {
|
||||||
|
add(FetchGarageDoorSchedulesEvent(deviceId: deviceId, category: 'switch_1'));
|
||||||
|
} else {
|
||||||
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,8 +25,7 @@ class GarageDoorControlEvent extends GarageDoorEvent {
|
|||||||
final dynamic value;
|
final dynamic value;
|
||||||
final String code;
|
final String code;
|
||||||
|
|
||||||
const GarageDoorControlEvent(
|
const GarageDoorControlEvent({required this.deviceId, required this.value, required this.code});
|
||||||
{required this.deviceId, required this.value, required this.code});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [deviceId, value];
|
List<Object?> get props => [deviceId, value];
|
||||||
@ -46,6 +45,22 @@ class AddGarageDoorScheduleEvent extends GarageDoorEvent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EditGarageDoorScheduleEvent extends GarageDoorEvent {
|
||||||
|
final String scheduleId;
|
||||||
|
final String category;
|
||||||
|
final TimeOfDay time;
|
||||||
|
final bool functionOn;
|
||||||
|
final List<bool> selectedDays;
|
||||||
|
|
||||||
|
const EditGarageDoorScheduleEvent({
|
||||||
|
required this.scheduleId,
|
||||||
|
required this.category,
|
||||||
|
required this.time,
|
||||||
|
required this.functionOn,
|
||||||
|
required this.selectedDays,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class UpdateGarageDoorScheduleEvent extends GarageDoorEvent {
|
class UpdateGarageDoorScheduleEvent extends GarageDoorEvent {
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
final String scheduleId;
|
final String scheduleId;
|
||||||
@ -106,8 +121,7 @@ class FetchGarageDoorRecordsEvent extends GarageDoorEvent {
|
|||||||
final String deviceId;
|
final String deviceId;
|
||||||
final String code;
|
final String code;
|
||||||
|
|
||||||
const FetchGarageDoorRecordsEvent(
|
const FetchGarageDoorRecordsEvent({required this.deviceId, required this.code});
|
||||||
{required this.deviceId, required this.code});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [deviceId, code];
|
List<Object?> get props => [deviceId, code];
|
||||||
|
|||||||
@ -76,35 +76,30 @@ class GarageDoorDialogHelper {
|
|||||||
padding: 8,
|
padding: 8,
|
||||||
backgroundColor: ColorsManager.boxColor,
|
backgroundColor: ColorsManager.boxColor,
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
onPressed: isEdit == true
|
onPressed: () async {
|
||||||
? null
|
TimeOfDay? time = await showTimePicker(
|
||||||
: () async {
|
context: context,
|
||||||
TimeOfDay? time = await showTimePicker(
|
initialTime: state.selectedTime ?? TimeOfDay.now(),
|
||||||
context: context,
|
builder: (context, child) {
|
||||||
initialTime:
|
return Theme(
|
||||||
state.selectedTime ?? TimeOfDay.now(),
|
data: Theme.of(context).copyWith(
|
||||||
builder: (context, child) {
|
colorScheme: const ColorScheme.light(
|
||||||
return Theme(
|
primary: ColorsManager.primaryColor,
|
||||||
data: Theme.of(context).copyWith(
|
),
|
||||||
colorScheme: const ColorScheme.light(
|
),
|
||||||
primary: ColorsManager.primaryColor,
|
child: child!,
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
child: child!,
|
);
|
||||||
);
|
if (time != null) {
|
||||||
},
|
bloc.add(UpdateSelectedTimeEvent(time));
|
||||||
);
|
}
|
||||||
if (time != null) {
|
},
|
||||||
bloc.add(UpdateSelectedTimeEvent(time));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
state.selectedTime == null
|
state.selectedTime == null ? 'Time' : state.selectedTime!.format(context),
|
||||||
? 'Time'
|
|
||||||
: state.selectedTime!.format(context),
|
|
||||||
style: context.textTheme.bodySmall!.copyWith(
|
style: context.textTheme.bodySmall!.copyWith(
|
||||||
color: ColorsManager.grayColor,
|
color: ColorsManager.grayColor,
|
||||||
),
|
),
|
||||||
@ -119,8 +114,7 @@ class GarageDoorDialogHelper {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildDayCheckboxes(context, state.selectedDays,
|
_buildDayCheckboxes(context, state.selectedDays, isEdit: isEdit),
|
||||||
isEdit: isEdit),
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
||||||
],
|
],
|
||||||
@ -147,7 +141,13 @@ class GarageDoorDialogHelper {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (state.selectedTime != null) {
|
if (state.selectedTime != null) {
|
||||||
if (state.isEditing && index != null) {
|
if (state.isEditing && index != null) {
|
||||||
return;
|
bloc.add(EditGarageDoorScheduleEvent(
|
||||||
|
scheduleId: schedule?.scheduleId ?? '',
|
||||||
|
category: 'switch_1',
|
||||||
|
time: state.selectedTime!,
|
||||||
|
selectedDays: state.selectedDays,
|
||||||
|
functionOn: state.functionOn,
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
bloc.add(AddGarageDoorScheduleEvent(
|
bloc.add(AddGarageDoorScheduleEvent(
|
||||||
category: 'switch_1',
|
category: 'switch_1',
|
||||||
@ -199,9 +199,7 @@ class GarageDoorDialogHelper {
|
|||||||
return daysBoolean;
|
return daysBoolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget _buildDayCheckboxes(
|
static Widget _buildDayCheckboxes(BuildContext context, List<bool> selectedDays, {bool? isEdit}) {
|
||||||
BuildContext context, List<bool> selectedDays,
|
|
||||||
{bool? isEdit}) {
|
|
||||||
final dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
final dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
@ -210,13 +208,9 @@ class GarageDoorDialogHelper {
|
|||||||
children: [
|
children: [
|
||||||
Checkbox(
|
Checkbox(
|
||||||
value: selectedDays[index],
|
value: selectedDays[index],
|
||||||
onChanged: isEdit == true
|
onChanged: (bool? value) {
|
||||||
? null
|
context.read<GarageDoorBloc>().add(UpdateSelectedDayEvent(index, value!));
|
||||||
: (bool? value) {
|
},
|
||||||
context
|
|
||||||
.read<GarageDoorBloc>()
|
|
||||||
.add(UpdateSelectedDayEvent(index, value!));
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
Text(dayLabels[index]),
|
Text(dayLabels[index]),
|
||||||
],
|
],
|
||||||
@ -225,27 +219,19 @@ class GarageDoorDialogHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget _buildFunctionSwitch(
|
static Widget _buildFunctionSwitch(BuildContext context, bool isOn, bool? isEdit) {
|
||||||
BuildContext context, bool isOn, bool? isEdit) {
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Function:',
|
'Function:',
|
||||||
style: context.textTheme.bodySmall!
|
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.grayColor),
|
||||||
.copyWith(color: ColorsManager.grayColor),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Radio<bool>(
|
Radio<bool>(
|
||||||
value: true,
|
value: true,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
if (isEdit == true) {
|
context.read<GarageDoorBloc>().add(const UpdateFunctionOnEvent(functionOn: true));
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
context
|
|
||||||
.read<GarageDoorBloc>()
|
|
||||||
.add(const UpdateFunctionOnEvent(functionOn: true));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Text('On'),
|
const Text('On'),
|
||||||
@ -254,13 +240,7 @@ class GarageDoorDialogHelper {
|
|||||||
value: false,
|
value: false,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
if (isEdit == true) {
|
context.read<GarageDoorBloc>().add(const UpdateFunctionOnEvent(functionOn: false));
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
context
|
|
||||||
.read<GarageDoorBloc>()
|
|
||||||
.add(const UpdateFunctionOnEvent(functionOn: false));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Text('Off'),
|
const Text('Off'),
|
||||||
@ -317,33 +297,36 @@ class GarageDoorDialogHelper {
|
|||||||
alertBody: TimeOutAlarmDialogBody(bloc),
|
alertBody: TimeOutAlarmDialogBody(bloc),
|
||||||
title: 'Time Out Alarm',
|
title: 'Time Out Alarm',
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
final updatedState =
|
final updatedState = context.read<GarageDoorBloc>().state;
|
||||||
context.read<GarageDoorBloc>().state;
|
if (updatedState is GarageDoorLoadedState) {
|
||||||
if (updatedState
|
|
||||||
is GarageDoorLoadedState) {
|
|
||||||
context.read<GarageDoorBloc>().add(
|
context.read<GarageDoorBloc>().add(
|
||||||
GarageDoorControlEvent(
|
GarageDoorControlEvent(
|
||||||
deviceId:
|
deviceId: updatedState.status.uuid,
|
||||||
updatedState.status.uuid,
|
|
||||||
code: 'countdown_alarm',
|
code: 'countdown_alarm',
|
||||||
value: updatedState
|
value: updatedState.status.countdownAlarm,
|
||||||
.status.countdownAlarm,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
// context.read<GarageDoorBloc>().add(
|
|
||||||
// GarageDoorInitialEvent(
|
|
||||||
// bloc.deviceId));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: ToggleWidget(
|
child: ToggleWidget(
|
||||||
icon: "-1",
|
icon: "-1",
|
||||||
value: state.status.countdownAlarm > 0,
|
value: state.status.doorState1 == "close_time_alarm" ? false : true,
|
||||||
code: 'countdown_alarm',
|
code: 'door_state_1',
|
||||||
deviceId: bloc.deviceId,
|
deviceId: bloc.deviceId,
|
||||||
label: 'Alarm when door is open',
|
label: 'Alarm when door is open',
|
||||||
onChange: (value) {}),
|
onChange: (value) {
|
||||||
|
context.read<GarageDoorBloc>().add(
|
||||||
|
GarageDoorControlEvent(
|
||||||
|
deviceId: bloc.deviceId,
|
||||||
|
code: 'door_state_1',
|
||||||
|
value: state.status.doorState1 == "close_time_alarm"
|
||||||
|
? "unclosed_time"
|
||||||
|
: "close_time_alarm",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@ -365,23 +348,16 @@ class GarageDoorDialogHelper {
|
|||||||
),
|
),
|
||||||
title: 'Opening and Closing Time',
|
title: 'Opening and Closing Time',
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
final updatedState =
|
final updatedState = context.read<GarageDoorBloc>().state;
|
||||||
context.read<GarageDoorBloc>().state;
|
if (updatedState is GarageDoorLoadedState) {
|
||||||
if (updatedState
|
|
||||||
is GarageDoorLoadedState) {
|
|
||||||
context.read<GarageDoorBloc>().add(
|
context.read<GarageDoorBloc>().add(
|
||||||
GarageDoorControlEvent(
|
GarageDoorControlEvent(
|
||||||
deviceId:
|
deviceId: updatedState.status.uuid,
|
||||||
updatedState.status.uuid,
|
|
||||||
code: 'tr_timecon',
|
code: 'tr_timecon',
|
||||||
value: updatedState
|
value: updatedState.status.trTimeCon,
|
||||||
.status.trTimeCon,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
// context.read<GarageDoorBloc>().add(
|
|
||||||
// GarageDoorInitialEvent(
|
|
||||||
// bloc.deviceId));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class GarageDoorStatusModel {
|
|||||||
voiceControl1 = status.value ?? false;
|
voiceControl1 = status.value ?? false;
|
||||||
break;
|
break;
|
||||||
case 'door_state_1':
|
case 'door_state_1':
|
||||||
doorState1 = status.value ?? 'closed';
|
doorState1 = status.value ?? 'close_time_alarm';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
Table(
|
Table(
|
||||||
border: TableBorder.all(
|
border: TableBorder.all(
|
||||||
color: ColorsManager.graysColor,
|
color: ColorsManager.graysColor,
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
|
||||||
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
|
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
TableRow(
|
TableRow(
|
||||||
@ -51,21 +50,17 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
BlocBuilder<GarageDoorBloc, GarageDoorState>(
|
BlocBuilder<GarageDoorBloc, GarageDoorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is ScheduleGarageLoadingState) {
|
if (state is ScheduleGarageLoadingState) {
|
||||||
return const SizedBox(
|
return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()));
|
||||||
height: 200,
|
|
||||||
child: Center(child: CircularProgressIndicator()));
|
|
||||||
}
|
}
|
||||||
if (state is GarageDoorLoadedState &&
|
if (state is GarageDoorLoadedState && state.status.schedules?.isEmpty == true) {
|
||||||
state.status.schedules == null) {
|
|
||||||
return _buildEmptyState(context);
|
return _buildEmptyState(context);
|
||||||
} else if (state is GarageDoorLoadedState) {
|
} else if (state is GarageDoorLoadedState) {
|
||||||
return Container(
|
return Container(
|
||||||
height: 200,
|
height: 200,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: ColorsManager.graysColor),
|
border: Border.all(color: ColorsManager.graysColor),
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius:
|
||||||
bottomLeft: Radius.circular(20),
|
const BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||||
bottomRight: Radius.circular(20)),
|
|
||||||
),
|
),
|
||||||
child: _buildTableBody(state, context));
|
child: _buildTableBody(state, context));
|
||||||
}
|
}
|
||||||
@ -83,8 +78,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
height: 200,
|
height: 200,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: ColorsManager.graysColor),
|
border: Border.all(color: ColorsManager.graysColor),
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||||
bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -118,8 +112,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (state.status.schedules != null)
|
if (state.status.schedules != null)
|
||||||
for (int i = 0; i < state.status.schedules!.length; i++)
|
for (int i = 0; i < state.status.schedules!.length; i++)
|
||||||
_buildScheduleRow(
|
_buildScheduleRow(state.status.schedules![i], i, context, state),
|
||||||
state.status.schedules![i], i, context, state),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -141,8 +134,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableRow _buildScheduleRow(ScheduleModel schedule, int index,
|
TableRow _buildScheduleRow(ScheduleModel schedule, int index, BuildContext context, GarageDoorLoadedState state) {
|
||||||
BuildContext context, GarageDoorLoadedState state) {
|
|
||||||
return TableRow(
|
return TableRow(
|
||||||
children: [
|
children: [
|
||||||
Center(
|
Center(
|
||||||
@ -160,8 +152,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
child: schedule.enable
|
child: schedule.enable
|
||||||
? const Icon(Icons.radio_button_checked,
|
? const Icon(Icons.radio_button_checked, color: ColorsManager.blueColor)
|
||||||
color: ColorsManager.blueColor)
|
|
||||||
: const Icon(
|
: const Icon(
|
||||||
Icons.radio_button_unchecked,
|
Icons.radio_button_unchecked,
|
||||||
color: ColorsManager.grayColor,
|
color: ColorsManager.grayColor,
|
||||||
@ -169,9 +160,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Center(
|
Center(child: Text(_getSelectedDays(ScheduleModel.parseSelectedDays(schedule.days)))),
|
||||||
child: Text(_getSelectedDays(
|
|
||||||
ScheduleModel.parseSelectedDays(schedule.days)))),
|
|
||||||
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
||||||
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
||||||
Center(
|
Center(
|
||||||
@ -181,24 +170,18 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
TextButton(
|
TextButton(
|
||||||
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
GarageDoorDialogHelper.showAddGarageDoorScheduleDialog(
|
GarageDoorDialogHelper.showAddGarageDoorScheduleDialog(context,
|
||||||
context,
|
schedule: schedule, index: index, isEdit: true);
|
||||||
schedule: schedule,
|
|
||||||
index: index,
|
|
||||||
isEdit: true);
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Edit',
|
'Edit',
|
||||||
style: context.textTheme.bodySmall!
|
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blueColor),
|
||||||
.copyWith(color: ColorsManager.blueColor),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context
|
context.read<GarageDoorBloc>().add(DeleteGarageDoorScheduleEvent(
|
||||||
.read<GarageDoorBloc>()
|
|
||||||
.add(DeleteGarageDoorScheduleEvent(
|
|
||||||
index: index,
|
index: index,
|
||||||
scheduleId: schedule.scheduleId,
|
scheduleId: schedule.scheduleId,
|
||||||
deviceId: state.status.uuid,
|
deviceId: state.status.uuid,
|
||||||
@ -206,8 +189,7 @@ class ScheduleGarageTableWidget extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Delete',
|
'Delete',
|
||||||
style: context.textTheme.bodySmall!
|
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blueColor),
|
||||||
.copyWith(color: ColorsManager.blueColor),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -16,12 +16,10 @@ class GateWayBloc extends Bloc<GateWayEvent, GateWayState> {
|
|||||||
on<GateWayFactoryReset>(_onFactoryReset);
|
on<GateWayFactoryReset>(_onFactoryReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _getGatWayById(
|
FutureOr<void> _getGatWayById(GatWayById event, Emitter<GateWayState> emit) async {
|
||||||
GatWayById event, Emitter<GateWayState> emit) async {
|
|
||||||
emit(GatewayLoadingState());
|
emit(GatewayLoadingState());
|
||||||
try {
|
try {
|
||||||
List<DeviceModel> devicesList =
|
List<DeviceModel> devicesList = await DevicesManagementApi.getDevicesByGatewayId(event.getWayId);
|
||||||
await DevicesManagementApi.getDevicesByGatewayId(event.getWayId);
|
|
||||||
|
|
||||||
emit(UpdateGatewayState(list: devicesList));
|
emit(UpdateGatewayState(list: devicesList));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -30,8 +28,7 @@ class GateWayBloc extends Bloc<GateWayEvent, GateWayState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onFactoryReset(
|
FutureOr<void> _onFactoryReset(GateWayFactoryReset event, Emitter<GateWayState> emit) async {
|
||||||
GateWayFactoryReset event, Emitter<GateWayState> emit) async {
|
|
||||||
emit(GatewayLoadingState());
|
emit(GatewayLoadingState());
|
||||||
try {
|
try {
|
||||||
final response = await DevicesManagementApi().factoryReset(
|
final response = await DevicesManagementApi().factoryReset(
|
||||||
|
|||||||
@ -74,7 +74,7 @@ class _DeviceItem extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
color: ColorsManager.whiteColors,
|
color: ColorsManager.whiteColors,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
device.icon,
|
device.icon ?? 'assets/icons/gateway.svg',
|
||||||
width: 35,
|
width: 35,
|
||||||
height: 35,
|
height: 35,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
|
|||||||
@ -2,9 +2,18 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class NotificationDialog extends StatelessWidget {
|
class NotificationDialog extends StatefulWidget {
|
||||||
const NotificationDialog({super.key});
|
const NotificationDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<NotificationDialog> createState() => _NotificationDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NotificationDialogState extends State<NotificationDialog> {
|
||||||
|
bool isLowBatteryNotificationEnabled = true;
|
||||||
|
bool isClosingRemindersEnabled = true;
|
||||||
|
bool isDoorAlarmEnabled = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Dialog(
|
return Dialog(
|
||||||
@ -14,7 +23,7 @@ class NotificationDialog extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 798,
|
width: 660,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
@ -61,29 +70,53 @@ class NotificationDialog extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
ToggleWidget(
|
SizedBox(
|
||||||
value: true,
|
width: 170,
|
||||||
code: 'notification',
|
height: 135,
|
||||||
deviceId: '',
|
child: ToggleWidget(
|
||||||
label: 'Low Battery',
|
value: isLowBatteryNotificationEnabled,
|
||||||
onChange: (v) {},
|
code: 'notification',
|
||||||
icon: '-1',
|
deviceId: '',
|
||||||
|
label: 'Low Battery',
|
||||||
|
onChange: (v) {
|
||||||
|
setState(() {
|
||||||
|
isLowBatteryNotificationEnabled = v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: '-1',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ToggleWidget(
|
SizedBox(
|
||||||
value: true,
|
width: 170,
|
||||||
code: 'notification',
|
height: 135,
|
||||||
deviceId: '',
|
child: ToggleWidget(
|
||||||
label: 'Closing\nReminders',
|
value: isClosingRemindersEnabled,
|
||||||
onChange: (v) {},
|
code: 'notification',
|
||||||
icon: '-1',
|
deviceId: '',
|
||||||
|
label: 'Closing\nReminders',
|
||||||
|
onChange: (v) {
|
||||||
|
setState(() {
|
||||||
|
isClosingRemindersEnabled = v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: '-1',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ToggleWidget(
|
SizedBox(
|
||||||
value: true,
|
width: 170,
|
||||||
code: 'notification',
|
height: 135,
|
||||||
deviceId: '',
|
child: ToggleWidget(
|
||||||
label: 'Door Alarm',
|
value: isDoorAlarmEnabled,
|
||||||
onChange: (v) {},
|
code: 'notification',
|
||||||
icon: '-1',
|
deviceId: '',
|
||||||
|
label: 'Door Alarm',
|
||||||
|
onChange: (v) {
|
||||||
|
setState(() {
|
||||||
|
isDoorAlarmEnabled = v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: '-1',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -10,14 +10,12 @@ import 'package:syncrow_web/services/devices_mang_api.dart';
|
|||||||
part 'one_gang_glass_switch_event.dart';
|
part 'one_gang_glass_switch_event.dart';
|
||||||
part 'one_gang_glass_switch_state.dart';
|
part 'one_gang_glass_switch_state.dart';
|
||||||
|
|
||||||
class OneGangGlassSwitchBloc
|
class OneGangGlassSwitchBloc extends Bloc<OneGangGlassSwitchEvent, OneGangGlassSwitchState> {
|
||||||
extends Bloc<OneGangGlassSwitchEvent, OneGangGlassSwitchState> {
|
|
||||||
OneGangGlassStatusModel deviceStatus;
|
OneGangGlassStatusModel deviceStatus;
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
|
|
||||||
OneGangGlassSwitchBloc({required String deviceId})
|
OneGangGlassSwitchBloc({required String deviceId})
|
||||||
: deviceStatus = OneGangGlassStatusModel(
|
: deviceStatus = OneGangGlassStatusModel(uuid: deviceId, switch1: false, countDown: 0),
|
||||||
uuid: deviceId, switch1: false, countDown: 0),
|
|
||||||
super(OneGangGlassSwitchInitial()) {
|
super(OneGangGlassSwitchInitial()) {
|
||||||
on<OneGangGlassSwitchFetchDeviceEvent>(_onFetchDeviceStatus);
|
on<OneGangGlassSwitchFetchDeviceEvent>(_onFetchDeviceStatus);
|
||||||
on<OneGangGlassSwitchControl>(_onControl);
|
on<OneGangGlassSwitchControl>(_onControl);
|
||||||
@ -26,22 +24,19 @@ class OneGangGlassSwitchBloc
|
|||||||
on<OneGangGlassFactoryResetEvent>(_onFactoryReset);
|
on<OneGangGlassFactoryResetEvent>(_onFactoryReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchDeviceStatus(OneGangGlassSwitchFetchDeviceEvent event,
|
Future<void> _onFetchDeviceStatus(
|
||||||
Emitter<OneGangGlassSwitchState> emit) async {
|
OneGangGlassSwitchFetchDeviceEvent event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||||
emit(OneGangGlassSwitchLoading());
|
emit(OneGangGlassSwitchLoading());
|
||||||
try {
|
try {
|
||||||
final status =
|
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
deviceStatus = OneGangGlassStatusModel.fromJson(event.deviceId, status.status);
|
||||||
deviceStatus =
|
|
||||||
OneGangGlassStatusModel.fromJson(event.deviceId, status.status);
|
|
||||||
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(OneGangGlassSwitchError(e.toString()));
|
emit(OneGangGlassSwitchError(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onControl(OneGangGlassSwitchControl event,
|
Future<void> _onControl(OneGangGlassSwitchControl event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||||
Emitter<OneGangGlassSwitchState> emit) async {
|
|
||||||
final oldValue = _getValueByCode(event.code);
|
final oldValue = _getValueByCode(event.code);
|
||||||
|
|
||||||
_updateLocalValue(event.code, event.value);
|
_updateLocalValue(event.code, event.value);
|
||||||
@ -57,12 +52,10 @@ class OneGangGlassSwitchBloc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFactoryReset(OneGangGlassFactoryResetEvent event,
|
Future<void> _onFactoryReset(OneGangGlassFactoryResetEvent event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||||
Emitter<OneGangGlassSwitchState> emit) async {
|
|
||||||
emit(OneGangGlassSwitchLoading());
|
emit(OneGangGlassSwitchLoading());
|
||||||
try {
|
try {
|
||||||
final response = await DevicesManagementApi()
|
final response = await DevicesManagementApi().factoryReset(event.factoryReset, event.deviceId);
|
||||||
.factoryReset(event.factoryReset, event.deviceId);
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
emit(OneGangGlassSwitchError('Failed to reset device'));
|
emit(OneGangGlassSwitchError('Failed to reset device'));
|
||||||
} else {
|
} else {
|
||||||
@ -73,12 +66,11 @@ class OneGangGlassSwitchBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onBatchControl(OneGangGlassSwitchBatchControl event,
|
Future<void> _onBatchControl(OneGangGlassSwitchBatchControl event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||||
Emitter<OneGangGlassSwitchState> emit) async {
|
|
||||||
final oldValue = _getValueByCode(event.code);
|
final oldValue = _getValueByCode(event.code);
|
||||||
|
|
||||||
_updateLocalValue(event.code, event.value);
|
_updateLocalValue(event.code, event.value);
|
||||||
emit(OneGangGlassSwitchBatchStatusLoaded(deviceStatus));
|
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||||
|
|
||||||
await _runDebounce(
|
await _runDebounce(
|
||||||
deviceId: event.deviceIds,
|
deviceId: event.deviceIds,
|
||||||
@ -91,15 +83,12 @@ class OneGangGlassSwitchBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchBatchStatus(
|
Future<void> _onFetchBatchStatus(
|
||||||
OneGangGlassSwitchFetchBatchStatusEvent event,
|
OneGangGlassSwitchFetchBatchStatusEvent event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||||
Emitter<OneGangGlassSwitchState> emit) async {
|
|
||||||
emit(OneGangGlassSwitchLoading());
|
emit(OneGangGlassSwitchLoading());
|
||||||
try {
|
try {
|
||||||
final status =
|
final status = await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
||||||
await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
deviceStatus = OneGangGlassStatusModel.fromJson(event.deviceIds.first, status.status);
|
||||||
deviceStatus = OneGangGlassStatusModel.fromJson(
|
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||||
event.deviceIds.first, status.status);
|
|
||||||
emit(OneGangGlassSwitchBatchStatusLoaded(deviceStatus));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(OneGangGlassSwitchError(e.toString()));
|
emit(OneGangGlassSwitchError(e.toString()));
|
||||||
}
|
}
|
||||||
@ -128,11 +117,9 @@ class OneGangGlassSwitchBloc
|
|||||||
try {
|
try {
|
||||||
late bool response;
|
late bool response;
|
||||||
if (isBatch) {
|
if (isBatch) {
|
||||||
response = await DevicesManagementApi()
|
response = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
|
||||||
.deviceBatchControl(deviceId, code, value);
|
|
||||||
} else {
|
} else {
|
||||||
response = await DevicesManagementApi()
|
response = await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
|
||||||
.deviceControl(deviceId, Status(code: code, value: value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
@ -144,8 +131,7 @@ class OneGangGlassSwitchBloc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _revertValueAndEmit(String deviceId, String code, bool oldValue,
|
void _revertValueAndEmit(String deviceId, String code, bool oldValue, Emitter<OneGangGlassSwitchState> emit) {
|
||||||
Emitter<OneGangGlassSwitchState> emit) {
|
|
||||||
_updateLocalValue(code, oldValue);
|
_updateLocalValue(code, oldValue);
|
||||||
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class OneGangGlassSwitchControlView extends StatelessWidget with HelperResponsiv
|
|||||||
value: status.switch1,
|
value: status.switch1,
|
||||||
code: 'switch_1',
|
code: 'switch_1',
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
label: 'Wall Lightً',
|
label: "Wall Light",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<OneGangGlassSwitchBloc>().add(
|
context.read<OneGangGlassSwitchBloc>().add(
|
||||||
OneGangGlassSwitchControl(
|
OneGangGlassSwitchControl(
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
|||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
class FirmwareUpdateWidget extends StatefulWidget {
|
class FirmwareUpdateWidget extends StatefulWidget {
|
||||||
const FirmwareUpdateWidget(
|
const FirmwareUpdateWidget({super.key, required this.deviceId, required this.version});
|
||||||
{super.key, required this.deviceId, required this.version});
|
|
||||||
|
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
final int version;
|
final int version;
|
||||||
@ -34,20 +33,23 @@ class _FirmwareUpdateWidgetState extends State<FirmwareUpdateWidget> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Column(
|
||||||
'Firmware Update',
|
children: [
|
||||||
style: context.textTheme.titleMedium!.copyWith(
|
Text(
|
||||||
fontWeight: FontWeight.bold,
|
'Firmware Update',
|
||||||
color: ColorsManager.blackColor,
|
style: context.textTheme.titleMedium!.copyWith(
|
||||||
),
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Are you sure?',
|
||||||
|
style: context.textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Text(
|
|
||||||
'Are you sure?',
|
|
||||||
style: context.textTheme.bodySmall!.copyWith(
|
|
||||||
color: ColorsManager.grayColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/helper/route_cont
|
|||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class DeviceBatchControlDialog extends StatelessWidget
|
class DeviceBatchControlDialog extends StatelessWidget with RouteControlsBasedCode {
|
||||||
with RouteControlsBasedCode {
|
|
||||||
final List<AllDevicesModel> devices;
|
final List<AllDevicesModel> devices;
|
||||||
|
|
||||||
const DeviceBatchControlDialog({super.key, required this.devices});
|
const DeviceBatchControlDialog({super.key, required this.devices});
|
||||||
@ -110,11 +109,11 @@ String getBatchDialogName(AllDevicesModel device) {
|
|||||||
case '1G':
|
case '1G':
|
||||||
return "Smart Light Switch";
|
return "Smart Light Switch";
|
||||||
case '2G':
|
case '2G':
|
||||||
return "2Gang Light";
|
return "Smart Light Switch";
|
||||||
case '3G':
|
case '3G':
|
||||||
return "Living Room";
|
return "Smart Light Switch";
|
||||||
case 'GW':
|
case 'GW':
|
||||||
return "GateWay";
|
return "Gateway";
|
||||||
case 'DL':
|
case 'DL':
|
||||||
return "Door Lock";
|
return "Door Lock";
|
||||||
case 'WPS':
|
case 'WPS':
|
||||||
@ -124,9 +123,21 @@ String getBatchDialogName(AllDevicesModel device) {
|
|||||||
case 'CUR':
|
case 'CUR':
|
||||||
return "Smart Curtains";
|
return "Smart Curtains";
|
||||||
case 'WH':
|
case 'WH':
|
||||||
return "Smart Water Hater";
|
return "Smart Water Heater";
|
||||||
case 'AC':
|
case 'AC':
|
||||||
return "Smart AC";
|
return "Smart AC";
|
||||||
|
case 'DS':
|
||||||
|
return "Door / Window Sensor";
|
||||||
|
case '1GT':
|
||||||
|
return "Touch Switch";
|
||||||
|
case '2GT':
|
||||||
|
return "Touch Switch";
|
||||||
|
case '3GT':
|
||||||
|
return "Touch Switch";
|
||||||
|
case 'GD':
|
||||||
|
return "Garage Door Opener";
|
||||||
|
case 'WL':
|
||||||
|
return "Water Leak Sensor";
|
||||||
default:
|
default:
|
||||||
return device.categoryName ?? 'Device Control';
|
return device.categoryName ?? 'Device Control';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class DeviceControlDialog extends StatelessWidget with RouteControlsBasedCode {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(),
|
const SizedBox(),
|
||||||
Text(
|
Text(
|
||||||
device.categoryName ?? 'Device Control',
|
device.productName ?? 'Device Control',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
|
|||||||
@ -2,8 +2,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class DeviceControlsContainer extends StatelessWidget {
|
class DeviceControlsContainer extends StatelessWidget {
|
||||||
const DeviceControlsContainer({required this.child, super.key});
|
const DeviceControlsContainer({required this.child, this.padding, super.key});
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
final double? padding;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -11,9 +12,16 @@ class DeviceControlsContainer extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
|
// boxShadow: <BoxShadow>[
|
||||||
|
// BoxShadow(
|
||||||
|
// color: ColorsManager.blackColor.withOpacity(0.05),
|
||||||
|
// blurRadius: 6.0,
|
||||||
|
// offset: const Offset(0, 5),
|
||||||
|
// spreadRadius: 0)
|
||||||
|
// ],
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.all(12),
|
padding: EdgeInsets.all(padding ?? 12),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/table/table_cell_widget.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/table/table_cell_widget.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/table/table_header.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/table/table_header.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class ReportsTable extends StatelessWidget {
|
class ReportsTable extends StatelessWidget {
|
||||||
@ -31,81 +33,90 @@ class ReportsTable extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Stack(
|
return report.data == null || report.data!.isEmpty
|
||||||
children: [
|
? Container(
|
||||||
Padding(
|
padding: const EdgeInsets.all(20.0),
|
||||||
padding: const EdgeInsets.all(20.0),
|
width: MediaQuery.sizeOf(context).width,
|
||||||
child: Table(
|
alignment: AlignmentDirectional.center,
|
||||||
border: TableBorder.all(color: Colors.grey.shade300, width: 1),
|
height: 100,
|
||||||
columnWidths: const {
|
child: Text(
|
||||||
0: FlexColumnWidth(),
|
'No reports found',
|
||||||
1: FlexColumnWidth(),
|
style: context.textTheme.bodyLarge!.copyWith(color: ColorsManager.grayColor),
|
||||||
2: FlexColumnWidth(),
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
TableRow(
|
|
||||||
decoration: BoxDecoration(color: Colors.grey.shade200),
|
|
||||||
children: [
|
|
||||||
const TableHeader(title: 'Date'),
|
|
||||||
const TableHeader(title: 'Time'),
|
|
||||||
TableHeader(title: thirdColumnTitle ?? 'Status'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (report.data != null)
|
|
||||||
...report.data!.asMap().entries.map((entry) {
|
|
||||||
int index = entry.key;
|
|
||||||
DeviceEvent data = entry.value;
|
|
||||||
|
|
||||||
// Parse eventTime into Date and Time
|
|
||||||
DateTime eventDateTime =
|
|
||||||
DateTime.fromMillisecondsSinceEpoch(data.eventTime!);
|
|
||||||
String date = DateFormat('dd/MM/yyyy').format(eventDateTime);
|
|
||||||
String time = DateFormat('HH:mm').format(eventDateTime);
|
|
||||||
|
|
||||||
String value;
|
|
||||||
if (hideValueShowDescription == true) {
|
|
||||||
if (mainDoorSensor != null && mainDoorSensor == true) {
|
|
||||||
value = data.value == 'true' ? 'Open' : 'Close';
|
|
||||||
} else if (garageDoorSensor != null &&
|
|
||||||
garageDoorSensor == true) {
|
|
||||||
value = data.value == 'true' ? 'Opened' : 'Closed';
|
|
||||||
} else if (waterLeak != null && waterLeak == true) {
|
|
||||||
value =
|
|
||||||
data.value == 'normal' ? 'Normal' : 'Leak Detected';
|
|
||||||
} else {
|
|
||||||
value = '${data.value!} ${thirdColumnDescription ?? ''}';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = '${data.value!} ${thirdColumnDescription ?? ''}';
|
|
||||||
}
|
|
||||||
|
|
||||||
return TableRow(
|
|
||||||
children: [
|
|
||||||
TableCellWidget(value: date),
|
|
||||||
TableCellWidget(value: time),
|
|
||||||
TableCellWidget(
|
|
||||||
value: value,
|
|
||||||
onTap: () => onRowTap(index),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
top: 0,
|
|
||||||
right: 0,
|
|
||||||
child: IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.close,
|
|
||||||
color: Colors.red,
|
|
||||||
size: 18,
|
|
||||||
),
|
),
|
||||||
onPressed: onClose,
|
)
|
||||||
),
|
: Stack(
|
||||||
),
|
children: [
|
||||||
],
|
Padding(
|
||||||
);
|
padding: const EdgeInsets.all(20.0),
|
||||||
|
child: Table(
|
||||||
|
border: TableBorder.all(color: Colors.grey.shade300, width: 1),
|
||||||
|
columnWidths: const {
|
||||||
|
0: FlexColumnWidth(),
|
||||||
|
1: FlexColumnWidth(),
|
||||||
|
2: FlexColumnWidth(),
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
TableRow(
|
||||||
|
decoration: BoxDecoration(color: Colors.grey.shade200),
|
||||||
|
children: [
|
||||||
|
const TableHeader(title: 'Date'),
|
||||||
|
const TableHeader(title: 'Time'),
|
||||||
|
TableHeader(title: thirdColumnTitle ?? 'Status'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (report.data != null)
|
||||||
|
...report.data!.asMap().entries.map((entry) {
|
||||||
|
int index = entry.key;
|
||||||
|
DeviceEvent data = entry.value;
|
||||||
|
|
||||||
|
// Parse eventTime into Date and Time
|
||||||
|
DateTime eventDateTime =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(data.eventTime!);
|
||||||
|
String date = DateFormat('dd/MM/yyyy').format(eventDateTime);
|
||||||
|
String time = DateFormat('HH:mm').format(eventDateTime);
|
||||||
|
|
||||||
|
String value;
|
||||||
|
if (hideValueShowDescription == true) {
|
||||||
|
if (mainDoorSensor != null && mainDoorSensor == true) {
|
||||||
|
value = data.value == 'true' ? 'Open' : 'Close';
|
||||||
|
} else if (garageDoorSensor != null && garageDoorSensor == true) {
|
||||||
|
value = data.value == 'true' ? 'Opened' : 'Closed';
|
||||||
|
} else if (waterLeak != null && waterLeak == true) {
|
||||||
|
value = data.value == 'normal' ? 'Normal' : 'Leak Detected';
|
||||||
|
} else {
|
||||||
|
value = '${data.value!} ${thirdColumnDescription ?? ''}';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = '${data.value!} ${thirdColumnDescription ?? ''}';
|
||||||
|
}
|
||||||
|
|
||||||
|
return TableRow(
|
||||||
|
children: [
|
||||||
|
TableCellWidget(value: date),
|
||||||
|
TableCellWidget(value: time),
|
||||||
|
TableCellWidget(
|
||||||
|
value: value,
|
||||||
|
onTap: () => onRowTap(index),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.close,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
onPressed: onClose,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
@ -30,13 +31,7 @@ class ToggleWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return DeviceControlsContainer(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
|
||||||
border: Border.all(color: ColorsManager.boxDivider),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@ -57,7 +57,7 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
|
|||||||
value: status.switch1,
|
value: status.switch1,
|
||||||
code: 'switch_1',
|
code: 'switch_1',
|
||||||
deviceId: deviceIds.first,
|
deviceId: deviceIds.first,
|
||||||
label: 'Glass Switch 1',
|
label: "Wall Light",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||||
ThreeGangGlassSwitchBatchControl(
|
ThreeGangGlassSwitchBatchControl(
|
||||||
@ -72,7 +72,7 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
|
|||||||
value: status.switch2,
|
value: status.switch2,
|
||||||
code: 'switch_2',
|
code: 'switch_2',
|
||||||
deviceId: deviceIds.first,
|
deviceId: deviceIds.first,
|
||||||
label: 'Glass Switch 2',
|
label: "Ceiling Light",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||||
ThreeGangGlassSwitchBatchControl(
|
ThreeGangGlassSwitchBatchControl(
|
||||||
@ -87,7 +87,7 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
|
|||||||
value: status.switch3,
|
value: status.switch3,
|
||||||
code: 'switch_3',
|
code: 'switch_3',
|
||||||
deviceId: deviceIds.first,
|
deviceId: deviceIds.first,
|
||||||
label: 'Glass Switch 3',
|
label: "SpotLight",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||||
ThreeGangGlassSwitchBatchControl(
|
ThreeGangGlassSwitchBatchControl(
|
||||||
|
|||||||
@ -56,7 +56,7 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperRespons
|
|||||||
value: status.switch1,
|
value: status.switch1,
|
||||||
code: 'switch_1',
|
code: 'switch_1',
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
label: 'Wall Light',
|
label: "Wall Light",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||||
ThreeGangGlassSwitchControl(
|
ThreeGangGlassSwitchControl(
|
||||||
@ -71,7 +71,7 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperRespons
|
|||||||
value: status.switch2,
|
value: status.switch2,
|
||||||
code: 'switch_2',
|
code: 'switch_2',
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
label: 'Ceiling Light',
|
label: "Ceiling Light",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||||
ThreeGangGlassSwitchControl(
|
ThreeGangGlassSwitchControl(
|
||||||
@ -86,7 +86,7 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperRespons
|
|||||||
value: status.switch3,
|
value: status.switch3,
|
||||||
code: 'switch_3',
|
code: 'switch_3',
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
label: 'SpotLight',
|
label: "SpotLight",
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||||
ThreeGangGlassSwitchControl(
|
ThreeGangGlassSwitchControl(
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/event.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/state.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_state.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/model/wall_sensor_model.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/model/wall_sensor_model.dart';
|
||||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
|
|
||||||
@ -38,12 +38,10 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
|
|
||||||
// Fetch batch status
|
// Fetch batch status
|
||||||
FutureOr<void> _fetchWallSensorBatchControl(
|
FutureOr<void> _fetchWallSensorBatchControl(
|
||||||
WallSensorFetchBatchStatusEvent event,
|
WallSensorFetchBatchStatusEvent event, Emitter<WallSensorState> emit) async {
|
||||||
Emitter<WallSensorState> emit) async {
|
|
||||||
emit(WallSensorLoadingInitialState());
|
emit(WallSensorLoadingInitialState());
|
||||||
try {
|
try {
|
||||||
var response =
|
var response = await DevicesManagementApi().getBatchStatus(event.devicesIds);
|
||||||
await DevicesManagementApi().getBatchStatus(event.devicesIds);
|
|
||||||
deviceStatus = WallSensorModel.fromJson(response.status);
|
deviceStatus = WallSensorModel.fromJson(response.status);
|
||||||
emit(WallSensorUpdateState(wallSensorModel: deviceStatus));
|
emit(WallSensorUpdateState(wallSensorModel: deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -70,8 +68,7 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
// } catch (_) {}
|
// } catch (_) {}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void _changeValue(
|
void _changeValue(WallSensorChangeValueEvent event, Emitter<WallSensorState> emit) async {
|
||||||
WallSensorChangeValueEvent event, Emitter<WallSensorState> emit) async {
|
|
||||||
emit(WallSensorLoadingNewSate(wallSensorModel: deviceStatus));
|
emit(WallSensorLoadingNewSate(wallSensorModel: deviceStatus));
|
||||||
if (event.code == 'far_detection') {
|
if (event.code == 'far_detection') {
|
||||||
deviceStatus.farDetection = event.value;
|
deviceStatus.farDetection = event.value;
|
||||||
@ -128,8 +125,7 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
try {
|
try {
|
||||||
late bool response;
|
late bool response;
|
||||||
if (isBatch) {
|
if (isBatch) {
|
||||||
response = await DevicesManagementApi()
|
response = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
|
||||||
.deviceBatchControl(deviceId, code, value);
|
|
||||||
} else {
|
} else {
|
||||||
response = await DevicesManagementApi()
|
response = await DevicesManagementApi()
|
||||||
.deviceControl(deviceId, Status(code: code, value: value));
|
.deviceControl(deviceId, Status(code: code, value: value));
|
||||||
@ -148,10 +144,13 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
FutureOr<void> _getDeviceReports(
|
FutureOr<void> _getDeviceReports(
|
||||||
GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async {
|
GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async {
|
||||||
emit(DeviceReportsLoadingState());
|
emit(DeviceReportsLoadingState());
|
||||||
|
// final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch;
|
||||||
|
// final to = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await DevicesManagementApi.getDeviceReports(deviceId, event.code)
|
// await DevicesManagementApi.getDeviceReportsByDate(
|
||||||
.then((value) {
|
// deviceId, event.code, from.toString(), to.toString())
|
||||||
|
await DevicesManagementApi.getDeviceReports(deviceId, event.code).then((value) {
|
||||||
emit(DeviceReportsState(deviceReport: value, code: event.code));
|
emit(DeviceReportsState(deviceReport: value, code: event.code));
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -160,13 +159,11 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDescription(
|
void _showDescription(ShowDescriptionEvent event, Emitter<WallSensorState> emit) {
|
||||||
ShowDescriptionEvent event, Emitter<WallSensorState> emit) {
|
|
||||||
emit(WallSensorShowDescriptionState(description: event.description));
|
emit(WallSensorShowDescriptionState(description: event.description));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _backToGridView(
|
void _backToGridView(BackToGridViewEvent event, Emitter<WallSensorState> emit) {
|
||||||
BackToGridViewEvent event, Emitter<WallSensorState> emit) {
|
|
||||||
emit(WallSensorUpdateState(wallSensorModel: deviceStatus));
|
emit(WallSensorUpdateState(wallSensorModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4,14 +4,13 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_re
|
|||||||
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/event.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/state.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_state.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/model/wall_sensor_model.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/model/wall_sensor_model.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
class WallSensorBatchControlView extends StatelessWidget
|
class WallSensorBatchControlView extends StatelessWidget with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
const WallSensorBatchControlView({super.key, required this.devicesIds});
|
const WallSensorBatchControlView({super.key, required this.devicesIds});
|
||||||
|
|
||||||
final List<String> devicesIds;
|
final List<String> devicesIds;
|
||||||
@ -26,16 +25,13 @@ class WallSensorBatchControlView extends StatelessWidget
|
|||||||
..add(WallSensorFetchBatchStatusEvent(devicesIds)),
|
..add(WallSensorFetchBatchStatusEvent(devicesIds)),
|
||||||
child: BlocBuilder<WallSensorBloc, WallSensorState>(
|
child: BlocBuilder<WallSensorBloc, WallSensorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is WallSensorLoadingInitialState ||
|
if (state is WallSensorLoadingInitialState || state is DeviceReportsLoadingState) {
|
||||||
state is DeviceReportsLoadingState) {
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (state is WallSensorUpdateState) {
|
} else if (state is WallSensorUpdateState) {
|
||||||
return _buildGridView(context, state.wallSensorModel, isExtraLarge,
|
return _buildGridView(context, state.wallSensorModel, isExtraLarge, isLarge, isMedium);
|
||||||
isLarge, isMedium);
|
|
||||||
} else if (state is DeviceReportsFailedState) {
|
} else if (state is DeviceReportsFailedState) {
|
||||||
final model = context.read<WallSensorBloc>().deviceStatus;
|
final model = context.read<WallSensorBloc>().deviceStatus;
|
||||||
return _buildGridView(
|
return _buildGridView(context, model, isExtraLarge, isLarge, isMedium);
|
||||||
context, model, isExtraLarge, isLarge, isMedium);
|
|
||||||
}
|
}
|
||||||
return const Center(child: Text('Error fetching status'));
|
return const Center(child: Text('Error fetching status'));
|
||||||
},
|
},
|
||||||
@ -43,8 +39,8 @@ class WallSensorBatchControlView extends StatelessWidget
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGridView(BuildContext context, WallSensorModel model,
|
Widget _buildGridView(
|
||||||
bool isExtraLarge, bool isLarge, bool isMedium) {
|
BuildContext context, WallSensorModel model, bool isExtraLarge, bool isLarge, bool isMedium) {
|
||||||
return GridView(
|
return GridView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
@ -97,12 +93,11 @@ class WallSensorBatchControlView extends StatelessWidget
|
|||||||
maxValue: 10000,
|
maxValue: 10000,
|
||||||
steps: 1,
|
steps: 1,
|
||||||
description: 'sec',
|
description: 'sec',
|
||||||
action: (int value) =>
|
action: (int value) => context.read<WallSensorBloc>().add(WallSensorBatchControlEvent(
|
||||||
context.read<WallSensorBloc>().add(WallSensorBatchControlEvent(
|
deviceIds: devicesIds,
|
||||||
deviceIds: devicesIds,
|
code: 'no_one_time',
|
||||||
code: 'no_one_time',
|
value: value,
|
||||||
value: value,
|
))),
|
||||||
))),
|
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: model.farDetection.toDouble(),
|
value: model.farDetection.toDouble(),
|
||||||
title: 'Far Detection:',
|
title: 'Far Detection:',
|
||||||
|
|||||||
@ -3,9 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/table/description_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/table/description_view.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/event.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_event.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/state.dart';
|
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_state.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_display_data.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_display_data.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_static_widget.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_static_widget.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_status.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_status.dart';
|
||||||
@ -14,8 +14,7 @@ import 'package:syncrow_web/pages/device_managment/wall_sensor/model/wall_sensor
|
|||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
class WallSensorControlsView extends StatelessWidget
|
class WallSensorControlsView extends StatelessWidget with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
const WallSensorControlsView({super.key, required this.device});
|
const WallSensorControlsView({super.key, required this.device});
|
||||||
|
|
||||||
final AllDevicesModel device;
|
final AllDevicesModel device;
|
||||||
@ -26,23 +25,19 @@ class WallSensorControlsView extends StatelessWidget
|
|||||||
final isLarge = isLargeScreenSize(context);
|
final isLarge = isLargeScreenSize(context);
|
||||||
final isMedium = isMediumScreenSize(context);
|
final isMedium = isMediumScreenSize(context);
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => WallSensorBloc(deviceId: device.uuid!)
|
create: (context) =>
|
||||||
..add(WallSensorFetchStatusEvent()),
|
WallSensorBloc(deviceId: device.uuid!)..add(WallSensorFetchStatusEvent()),
|
||||||
child: BlocBuilder<WallSensorBloc, WallSensorState>(
|
child: BlocBuilder<WallSensorBloc, WallSensorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is WallSensorLoadingInitialState ||
|
if (state is WallSensorLoadingInitialState || state is DeviceReportsLoadingState) {
|
||||||
state is DeviceReportsLoadingState) {
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (state is WallSensorUpdateState) {
|
} else if (state is WallSensorUpdateState) {
|
||||||
return _buildGridView(context, state.wallSensorModel, isExtraLarge,
|
return _buildGridView(context, state.wallSensorModel, isExtraLarge, isLarge, isMedium);
|
||||||
isLarge, isMedium);
|
|
||||||
} else if (state is DeviceReportsState) {
|
} else if (state is DeviceReportsState) {
|
||||||
return ReportsTable(
|
return ReportsTable(
|
||||||
report: state.deviceReport,
|
report: state.deviceReport,
|
||||||
thirdColumnTitle:
|
thirdColumnTitle: state.code == 'illuminance_value' ? "Value" : 'Status',
|
||||||
state.code == 'illuminance_value' ? "Value" : 'Status',
|
thirdColumnDescription: state.code == 'illuminance_value' ? "Lux" : null,
|
||||||
thirdColumnDescription:
|
|
||||||
state.code == 'illuminance_value' ? "Lux" : null,
|
|
||||||
onRowTap: (index) {},
|
onRowTap: (index) {},
|
||||||
onClose: () {
|
onClose: () {
|
||||||
context.read<WallSensorBloc>().add(BackToGridViewEvent());
|
context.read<WallSensorBloc>().add(BackToGridViewEvent());
|
||||||
@ -57,8 +52,7 @@ class WallSensorControlsView extends StatelessWidget
|
|||||||
);
|
);
|
||||||
} else if (state is DeviceReportsFailedState) {
|
} else if (state is DeviceReportsFailedState) {
|
||||||
final model = context.read<WallSensorBloc>().deviceStatus;
|
final model = context.read<WallSensorBloc>().deviceStatus;
|
||||||
return _buildGridView(
|
return _buildGridView(context, model, isExtraLarge, isLarge, isMedium);
|
||||||
context, model, isExtraLarge, isLarge, isMedium);
|
|
||||||
}
|
}
|
||||||
return const Center(child: Text('Error fetching status'));
|
return const Center(child: Text('Error fetching status'));
|
||||||
},
|
},
|
||||||
@ -66,8 +60,8 @@ class WallSensorControlsView extends StatelessWidget
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGridView(BuildContext context, WallSensorModel model,
|
Widget _buildGridView(
|
||||||
bool isExtraLarge, bool isLarge, bool isMedium) {
|
BuildContext context, WallSensorModel model, bool isExtraLarge, bool isLarge, bool isMedium) {
|
||||||
return GridView(
|
return GridView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
@ -136,11 +130,10 @@ class WallSensorControlsView extends StatelessWidget
|
|||||||
maxValue: 10000,
|
maxValue: 10000,
|
||||||
steps: 1,
|
steps: 1,
|
||||||
description: 'sec',
|
description: 'sec',
|
||||||
action: (int value) =>
|
action: (int value) => context.read<WallSensorBloc>().add(WallSensorChangeValueEvent(
|
||||||
context.read<WallSensorBloc>().add(WallSensorChangeValueEvent(
|
code: 'no_one_time',
|
||||||
code: 'no_one_time',
|
value: value,
|
||||||
value: value,
|
))),
|
||||||
))),
|
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: model.farDetection.toDouble(),
|
value: model.farDetection.toDouble(),
|
||||||
title: 'Far Detection:',
|
title: 'Far Detection:',
|
||||||
@ -157,8 +150,9 @@ class WallSensorControlsView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<WallSensorBloc>().add(GetDeviceReportsEvent(
|
context
|
||||||
code: 'illuminance_value', deviceUuid: device.uuid!));
|
.read<WallSensorBloc>()
|
||||||
|
.add(GetDeviceReportsEvent(code: 'illuminance_value', deviceUuid: device.uuid!));
|
||||||
},
|
},
|
||||||
child: const PresenceStaticWidget(
|
child: const PresenceStaticWidget(
|
||||||
icon: Assets.illuminanceRecordIcon,
|
icon: Assets.illuminanceRecordIcon,
|
||||||
@ -167,8 +161,9 @@ class WallSensorControlsView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<WallSensorBloc>().add(GetDeviceReportsEvent(
|
context
|
||||||
code: 'presence_state', deviceUuid: device.uuid!));
|
.read<WallSensorBloc>()
|
||||||
|
.add(GetDeviceReportsEvent(code: 'presence_state', deviceUuid: device.uuid!));
|
||||||
},
|
},
|
||||||
child: const PresenceStaticWidget(
|
child: const PresenceStaticWidget(
|
||||||
icon: Assets.presenceRecordIcon,
|
icon: Assets.presenceRecordIcon,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// water_heater_bloc.dart
|
// water_heater_bloc.dart
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -30,6 +31,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
|
|
||||||
on<GetSchedulesEvent>(_getSchedule);
|
on<GetSchedulesEvent>(_getSchedule);
|
||||||
on<AddScheduleEvent>(_onAddSchedule);
|
on<AddScheduleEvent>(_onAddSchedule);
|
||||||
|
on<EditWaterHeaterScheduleEvent>(_onEditSchedule);
|
||||||
on<DeleteScheduleEvent>(_onDeleteSchedule);
|
on<DeleteScheduleEvent>(_onDeleteSchedule);
|
||||||
on<UpdateScheduleEntryEvent>(_onUpdateSchedule);
|
on<UpdateScheduleEntryEvent>(_onUpdateSchedule);
|
||||||
}
|
}
|
||||||
@ -76,8 +78,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
final updatedDays = List<bool>.from(currentState.selectedDays);
|
final updatedDays = List<bool>.from(currentState.selectedDays);
|
||||||
updatedDays[event.index] = event.value;
|
updatedDays[event.index] = event.value;
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
||||||
selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _updateFunctionOn(
|
FutureOr<void> _updateFunctionOn(
|
||||||
@ -85,8 +86,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
Emitter<WaterHeaterState> emit,
|
Emitter<WaterHeaterState> emit,
|
||||||
) {
|
) {
|
||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(functionOn: event.isOn, selectedTime: currentState.selectedTime));
|
||||||
functionOn: event.isOn, selectedTime: currentState.selectedTime));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _updateScheduleEvent(
|
FutureOr<void> _updateScheduleEvent(
|
||||||
@ -101,8 +101,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (event.scheduleMode == ScheduleModes.countdown) {
|
if (event.scheduleMode == ScheduleModes.countdown) {
|
||||||
final countdownRemaining =
|
final countdownRemaining = Duration(hours: event.hours, minutes: event.minutes);
|
||||||
Duration(hours: event.hours, minutes: event.minutes);
|
|
||||||
|
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(
|
||||||
scheduleMode: ScheduleModes.countdown,
|
scheduleMode: ScheduleModes.countdown,
|
||||||
@ -112,13 +111,11 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
countdownRemaining: countdownRemaining,
|
countdownRemaining: countdownRemaining,
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!currentState.isCountdownActive! &&
|
if (!currentState.isCountdownActive! && countdownRemaining > Duration.zero) {
|
||||||
countdownRemaining > Duration.zero) {
|
|
||||||
_startCountdownTimer(emit, countdownRemaining);
|
_startCountdownTimer(emit, countdownRemaining);
|
||||||
}
|
}
|
||||||
} else if (event.scheduleMode == ScheduleModes.inching) {
|
} else if (event.scheduleMode == ScheduleModes.inching) {
|
||||||
final inchingDuration =
|
final inchingDuration = Duration(hours: event.hours, minutes: event.minutes);
|
||||||
Duration(hours: event.hours, minutes: event.minutes);
|
|
||||||
|
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(
|
||||||
scheduleMode: ScheduleModes.inching,
|
scheduleMode: ScheduleModes.inching,
|
||||||
@ -220,8 +217,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
try {
|
try {
|
||||||
final status = await DevicesManagementApi().deviceControl(
|
final status = await DevicesManagementApi().deviceControl(
|
||||||
event.deviceId,
|
event.deviceId,
|
||||||
Status(
|
Status(code: isCountDown ? 'countdown_1' : 'switch_inching', value: 0),
|
||||||
code: isCountDown ? 'countdown_1' : 'switch_inching', value: 0),
|
|
||||||
);
|
);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
emit(const WaterHeaterFailedState(error: 'Failed to stop schedule.'));
|
emit(const WaterHeaterFailedState(error: 'Failed to stop schedule.'));
|
||||||
@ -239,10 +235,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
emit(WaterHeaterLoadingState());
|
emit(WaterHeaterLoadingState());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final status =
|
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
deviceStatus = WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||||
deviceStatus =
|
|
||||||
WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
|
||||||
|
|
||||||
if (deviceStatus.scheduleMode == ScheduleModes.countdown) {
|
if (deviceStatus.scheduleMode == ScheduleModes.countdown) {
|
||||||
final countdownRemaining = Duration(
|
final countdownRemaining = Duration(
|
||||||
@ -340,10 +334,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
|
|
||||||
if (currentState.countdownRemaining != null &&
|
if (currentState.countdownRemaining != null && currentState.countdownRemaining! > Duration.zero) {
|
||||||
currentState.countdownRemaining! > Duration.zero) {
|
final newRemaining = currentState.countdownRemaining! - const Duration(minutes: 1);
|
||||||
final newRemaining =
|
|
||||||
currentState.countdownRemaining! - const Duration(minutes: 1);
|
|
||||||
|
|
||||||
if (newRemaining <= Duration.zero) {
|
if (newRemaining <= Duration.zero) {
|
||||||
_countdownTimer?.cancel();
|
_countdownTimer?.cancel();
|
||||||
@ -438,8 +430,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _revertValue(String code, dynamic oldValue,
|
void _revertValue(String code, dynamic oldValue, void Function(WaterHeaterState state) emit) {
|
||||||
void Function(WaterHeaterState state) emit) {
|
|
||||||
_updateLocalValue(code, oldValue);
|
_updateLocalValue(code, oldValue);
|
||||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
@ -486,13 +477,12 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _getSchedule(
|
FutureOr<void> _getSchedule(GetSchedulesEvent event, Emitter<WaterHeaterState> emit) async {
|
||||||
GetSchedulesEvent event, Emitter<WaterHeaterState> emit) async {
|
|
||||||
emit(ScheduleLoadingState());
|
emit(ScheduleLoadingState());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<ScheduleModel> schedules = await DevicesManagementApi()
|
List<ScheduleModel> schedules =
|
||||||
.getDeviceSchedules(deviceStatus.uuid, event.category);
|
await DevicesManagementApi().getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||||
|
|
||||||
emit(WaterHeaterDeviceStatusLoaded(
|
emit(WaterHeaterDeviceStatusLoaded(
|
||||||
deviceStatus,
|
deviceStatus,
|
||||||
@ -524,8 +514,35 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
|
|
||||||
// emit(ScheduleLoadingState());
|
// emit(ScheduleLoadingState());
|
||||||
|
|
||||||
bool success = await DevicesManagementApi()
|
bool success = await DevicesManagementApi().addScheduleRecord(newSchedule, currentState.status.uuid);
|
||||||
.addScheduleRecord(newSchedule, currentState.status.uuid);
|
|
||||||
|
if (success) {
|
||||||
|
add(GetSchedulesEvent(category: 'switch_1', uuid: deviceStatus.uuid));
|
||||||
|
} else {
|
||||||
|
emit(currentState);
|
||||||
|
//emit(const WaterHeaterFailedState(error: 'Failed to add schedule.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> _onEditSchedule(EditWaterHeaterScheduleEvent event, Emitter<WaterHeaterState> emit) async {
|
||||||
|
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||||
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
|
|
||||||
|
ScheduleEntry newSchedule = ScheduleEntry(
|
||||||
|
scheduleId: event.scheduleId,
|
||||||
|
category: event.category,
|
||||||
|
time: formatTimeOfDayToISO(event.time),
|
||||||
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
|
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||||
|
);
|
||||||
|
|
||||||
|
// emit(ScheduleLoadingState());
|
||||||
|
|
||||||
|
bool success = await DevicesManagementApi().editScheduleRecord(
|
||||||
|
currentState.status.uuid,
|
||||||
|
newSchedule,
|
||||||
|
);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
add(GetSchedulesEvent(category: 'switch_1', uuid: deviceStatus.uuid));
|
add(GetSchedulesEvent(category: 'switch_1', uuid: deviceStatus.uuid));
|
||||||
@ -577,13 +594,11 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
|
|
||||||
// emit(ScheduleLoadingState());
|
// emit(ScheduleLoadingState());
|
||||||
|
|
||||||
bool success = await DevicesManagementApi()
|
bool success = await DevicesManagementApi().deleteScheduleRecord(currentState.status.uuid, event.scheduleId);
|
||||||
.deleteScheduleRecord(currentState.status.uuid, event.scheduleId);
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
final updatedSchedules = currentState.schedules
|
final updatedSchedules =
|
||||||
.where((schedule) => schedule.scheduleId != event.scheduleId)
|
currentState.schedules.where((schedule) => schedule.scheduleId != event.scheduleId).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
emit(currentState.copyWith(schedules: updatedSchedules));
|
emit(currentState.copyWith(schedules: updatedSchedules));
|
||||||
} else {
|
} else {
|
||||||
@ -593,15 +608,12 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _batchFetchWaterHeater(FetchWaterHeaterBatchStatusEvent event,
|
FutureOr<void> _batchFetchWaterHeater(FetchWaterHeaterBatchStatusEvent event, Emitter<WaterHeaterState> emit) async {
|
||||||
Emitter<WaterHeaterState> emit) async {
|
|
||||||
emit(WaterHeaterLoadingState());
|
emit(WaterHeaterLoadingState());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final status =
|
final status = await DevicesManagementApi().getBatchStatus(event.devicesUuid);
|
||||||
await DevicesManagementApi().getBatchStatus(event.devicesUuid);
|
deviceStatus = WaterHeaterStatusModel.fromJson(event.devicesUuid.first, status.status);
|
||||||
deviceStatus = WaterHeaterStatusModel.fromJson(
|
|
||||||
event.devicesUuid.first, status.status);
|
|
||||||
|
|
||||||
emit(WaterHeaterDeviceStatusLoaded(deviceStatus));
|
emit(WaterHeaterDeviceStatusLoaded(deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -609,8 +621,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _batchControlWaterHeater(ControlWaterHeaterBatchEvent event,
|
FutureOr<void> _batchControlWaterHeater(ControlWaterHeaterBatchEvent event, Emitter<WaterHeaterState> emit) async {
|
||||||
Emitter<WaterHeaterState> emit) async {
|
|
||||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
|
|
||||||
|
|||||||
@ -71,6 +71,22 @@ final class AddScheduleEvent extends WaterHeaterEvent {
|
|||||||
List<Object?> get props => [selectedDays, time, functionOn, category];
|
List<Object?> get props => [selectedDays, time, functionOn, category];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EditWaterHeaterScheduleEvent extends WaterHeaterEvent {
|
||||||
|
final String scheduleId;
|
||||||
|
final String category;
|
||||||
|
final TimeOfDay time;
|
||||||
|
final bool functionOn;
|
||||||
|
final List<bool> selectedDays;
|
||||||
|
|
||||||
|
const EditWaterHeaterScheduleEvent({
|
||||||
|
required this.scheduleId,
|
||||||
|
required this.category,
|
||||||
|
required this.time,
|
||||||
|
required this.functionOn,
|
||||||
|
required this.selectedDays,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final class DeleteScheduleEvent extends WaterHeaterEvent {
|
final class DeleteScheduleEvent extends WaterHeaterEvent {
|
||||||
final int index;
|
final int index;
|
||||||
final String scheduleId;
|
final String scheduleId;
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
|
||||||
|
|
||||||
class ScheduleDialogHelper {
|
class ScheduleDialogHelper {
|
||||||
static void showAddScheduleDialog(BuildContext context,
|
static void showAddScheduleDialog(BuildContext context, {ScheduleModel? schedule, int? index, bool? isEdit}) {
|
||||||
{ScheduleModel? schedule, int? index, bool? isEdit}) {
|
|
||||||
final bloc = context.read<WaterHeaterBloc>();
|
final bloc = context.read<WaterHeaterBloc>();
|
||||||
|
|
||||||
if (schedule == null) {
|
if (schedule == null) {
|
||||||
@ -70,35 +69,30 @@ class ScheduleDialogHelper {
|
|||||||
padding: 8,
|
padding: 8,
|
||||||
backgroundColor: ColorsManager.boxColor,
|
backgroundColor: ColorsManager.boxColor,
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
onPressed: isEdit == true
|
onPressed: () async {
|
||||||
? null
|
TimeOfDay? time = await showTimePicker(
|
||||||
: () async {
|
context: context,
|
||||||
TimeOfDay? time = await showTimePicker(
|
initialTime: state.selectedTime ?? TimeOfDay.now(),
|
||||||
context: context,
|
builder: (context, child) {
|
||||||
initialTime:
|
return Theme(
|
||||||
state.selectedTime ?? TimeOfDay.now(),
|
data: Theme.of(context).copyWith(
|
||||||
builder: (context, child) {
|
colorScheme: const ColorScheme.light(
|
||||||
return Theme(
|
primary: ColorsManager.primaryColor,
|
||||||
data: Theme.of(context).copyWith(
|
),
|
||||||
colorScheme: const ColorScheme.light(
|
),
|
||||||
primary: ColorsManager.primaryColor,
|
child: child!,
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
child: child!,
|
);
|
||||||
);
|
if (time != null) {
|
||||||
},
|
bloc.add(UpdateSelectedTimeEvent(time));
|
||||||
);
|
}
|
||||||
if (time != null) {
|
},
|
||||||
bloc.add(UpdateSelectedTimeEvent(time));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
state.selectedTime == null
|
state.selectedTime == null ? 'Time' : state.selectedTime!.format(context),
|
||||||
? 'Time'
|
|
||||||
: state.selectedTime!.format(context),
|
|
||||||
style: context.textTheme.bodySmall!.copyWith(
|
style: context.textTheme.bodySmall!.copyWith(
|
||||||
color: ColorsManager.grayColor,
|
color: ColorsManager.grayColor,
|
||||||
),
|
),
|
||||||
@ -113,8 +107,7 @@ class ScheduleDialogHelper {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildDayCheckboxes(context, state.selectedDays,
|
_buildDayCheckboxes(context, state.selectedDays, isEdit: isEdit),
|
||||||
isEdit: isEdit),
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
||||||
],
|
],
|
||||||
@ -141,7 +134,13 @@ class ScheduleDialogHelper {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (state.selectedTime != null) {
|
if (state.selectedTime != null) {
|
||||||
if (state.isEditing && index != null) {
|
if (state.isEditing && index != null) {
|
||||||
return;
|
bloc.add(EditWaterHeaterScheduleEvent(
|
||||||
|
scheduleId: schedule?.scheduleId ?? '',
|
||||||
|
category: 'switch_1',
|
||||||
|
time: state.selectedTime!,
|
||||||
|
selectedDays: state.selectedDays,
|
||||||
|
functionOn: state.functionOn,
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
bloc.add(AddScheduleEvent(
|
bloc.add(AddScheduleEvent(
|
||||||
category: 'switch_1',
|
category: 'switch_1',
|
||||||
@ -193,9 +192,7 @@ class ScheduleDialogHelper {
|
|||||||
return daysBoolean;
|
return daysBoolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget _buildDayCheckboxes(
|
static Widget _buildDayCheckboxes(BuildContext context, List<bool> selectedDays, {bool? isEdit}) {
|
||||||
BuildContext context, List<bool> selectedDays,
|
|
||||||
{bool? isEdit}) {
|
|
||||||
final dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
final dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
@ -204,13 +201,9 @@ class ScheduleDialogHelper {
|
|||||||
children: [
|
children: [
|
||||||
Checkbox(
|
Checkbox(
|
||||||
value: selectedDays[index],
|
value: selectedDays[index],
|
||||||
onChanged: isEdit == true
|
onChanged: (bool? value) {
|
||||||
? null
|
context.read<WaterHeaterBloc>().add(UpdateSelectedDayEvent(index, value!));
|
||||||
: (bool? value) {
|
},
|
||||||
context
|
|
||||||
.read<WaterHeaterBloc>()
|
|
||||||
.add(UpdateSelectedDayEvent(index, value!));
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
Text(dayLabels[index]),
|
Text(dayLabels[index]),
|
||||||
],
|
],
|
||||||
@ -219,27 +212,19 @@ class ScheduleDialogHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget _buildFunctionSwitch(
|
static Widget _buildFunctionSwitch(BuildContext context, bool isOn, bool? isEdit) {
|
||||||
BuildContext context, bool isOn, bool? isEdit) {
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Function:',
|
'Function:',
|
||||||
style: context.textTheme.bodySmall!
|
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.grayColor),
|
||||||
.copyWith(color: ColorsManager.grayColor),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Radio<bool>(
|
Radio<bool>(
|
||||||
value: true,
|
value: true,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
if (isEdit == true) {
|
context.read<WaterHeaterBloc>().add(const UpdateFunctionOnEvent(true));
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
context
|
|
||||||
.read<WaterHeaterBloc>()
|
|
||||||
.add(const UpdateFunctionOnEvent(true));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Text('On'),
|
const Text('On'),
|
||||||
@ -248,13 +233,7 @@ class ScheduleDialogHelper {
|
|||||||
value: false,
|
value: false,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
if (isEdit == true) {
|
context.read<WaterHeaterBloc>().add(const UpdateFunctionOnEvent(false));
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
context
|
|
||||||
.read<WaterHeaterBloc>()
|
|
||||||
.add(const UpdateFunctionOnEvent(false));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Text('Off'),
|
const Text('Off'),
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||||
|
|
||||||
class ScheduleEntry {
|
class ScheduleEntry {
|
||||||
@ -9,12 +8,14 @@ class ScheduleEntry {
|
|||||||
final String time;
|
final String time;
|
||||||
final Status function;
|
final Status function;
|
||||||
final List<String> days;
|
final List<String> days;
|
||||||
|
final String? scheduleId;
|
||||||
|
|
||||||
ScheduleEntry({
|
ScheduleEntry({
|
||||||
required this.category,
|
required this.category,
|
||||||
required this.time,
|
required this.time,
|
||||||
required this.function,
|
required this.function,
|
||||||
required this.days,
|
required this.days,
|
||||||
|
this.scheduleId,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -38,6 +39,7 @@ class ScheduleEntry {
|
|||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return {
|
return {
|
||||||
|
'scheduleId': scheduleId,
|
||||||
'category': category,
|
'category': category,
|
||||||
'time': time,
|
'time': time,
|
||||||
'function': function.toMap(),
|
'function': function.toMap(),
|
||||||
@ -56,8 +58,7 @@ class ScheduleEntry {
|
|||||||
|
|
||||||
String toJson() => json.encode(toMap());
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
factory ScheduleEntry.fromJson(String source) =>
|
factory ScheduleEntry.fromJson(String source) => ScheduleEntry.fromMap(json.decode(source));
|
||||||
ScheduleEntry.fromMap(json.decode(source));
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
@ -72,9 +73,6 @@ class ScheduleEntry {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
return category.hashCode ^
|
return category.hashCode ^ time.hashCode ^ function.hashCode ^ days.hashCode;
|
||||||
time.hashCode ^
|
|
||||||
function.hashCode ^
|
|
||||||
days.hashCode;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,18 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class WaterLeakNotificationDialog extends StatelessWidget {
|
class WaterLeakNotificationDialog extends StatefulWidget {
|
||||||
const WaterLeakNotificationDialog({super.key});
|
const WaterLeakNotificationDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WaterLeakNotificationDialog> createState() => _NotificationDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NotificationDialogState extends State<WaterLeakNotificationDialog> {
|
||||||
|
bool isLowBatteryNotificationEnabled = true;
|
||||||
|
bool isClosingRemindersEnabled = true;
|
||||||
|
bool isWaterLeakage = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Dialog(
|
return Dialog(
|
||||||
@ -14,7 +23,7 @@ class WaterLeakNotificationDialog extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 400,
|
width: 560,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
@ -61,21 +70,37 @@ class WaterLeakNotificationDialog extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
ToggleWidget(
|
SizedBox(
|
||||||
value: true,
|
width: 170,
|
||||||
code: 'notification',
|
height: 135,
|
||||||
deviceId: '',
|
child: ToggleWidget(
|
||||||
label: 'Low Battery',
|
value: isLowBatteryNotificationEnabled,
|
||||||
onChange: (v) {},
|
code: 'notification',
|
||||||
icon: '-1',
|
deviceId: '',
|
||||||
|
label: 'Low Battery',
|
||||||
|
onChange: (v) {
|
||||||
|
setState(() {
|
||||||
|
isLowBatteryNotificationEnabled = v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: '-1',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ToggleWidget(
|
SizedBox(
|
||||||
value: true,
|
width: 170,
|
||||||
code: 'notification',
|
height: 135,
|
||||||
deviceId: '',
|
child: ToggleWidget(
|
||||||
label: 'Water Leakage',
|
value: isWaterLeakage,
|
||||||
onChange: (v) {},
|
code: 'notification',
|
||||||
icon: '-1',
|
deviceId: '',
|
||||||
|
label: 'Water Leakage',
|
||||||
|
onChange: (v) {
|
||||||
|
setState(() {
|
||||||
|
isWaterLeakage = v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: '-1',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -76,7 +76,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
|
|
||||||
Future<void> selectTimeVisitorPassword(
|
Future<void> selectTimeVisitorPassword(
|
||||||
SelectTimeVisitorPassword event,
|
SelectTimeVisitorPassword event,
|
||||||
Emitter<VisitorPasswordState> emit,) async {
|
Emitter<VisitorPasswordState> emit,
|
||||||
|
) async {
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
@ -359,7 +360,6 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
context: event.context,
|
context: event.context,
|
||||||
initialTime: TimeOfDay.now(),
|
initialTime: TimeOfDay.now(),
|
||||||
);
|
);
|
||||||
print('timePicked=$timePicked');
|
|
||||||
|
|
||||||
if (timePicked != null) {
|
if (timePicked != null) {
|
||||||
final selectedDateTime = DateTime(
|
final selectedDateTime = DateTime(
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/enum/device_types.dart';
|
import 'package:syncrow_web/utils/enum/device_types.dart';
|
||||||
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
|
||||||
|
|
||||||
class DeviceModel {
|
class DeviceModel {
|
||||||
dynamic productUuid;
|
dynamic productUuid;
|
||||||
@ -51,7 +51,6 @@ class DeviceModel {
|
|||||||
factory DeviceModel.fromJson(Map<String, dynamic> json) {
|
factory DeviceModel.fromJson(Map<String, dynamic> json) {
|
||||||
String tempIcon = '';
|
String tempIcon = '';
|
||||||
DeviceType type = devicesTypesMap[json['productType']] ?? DeviceType.Other;
|
DeviceType type = devicesTypesMap[json['productType']] ?? DeviceType.Other;
|
||||||
|
|
||||||
if (type == DeviceType.LightBulb) {
|
if (type == DeviceType.LightBulb) {
|
||||||
tempIcon = Assets.lightBulb;
|
tempIcon = Assets.lightBulb;
|
||||||
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
||||||
@ -66,9 +65,22 @@ class DeviceModel {
|
|||||||
tempIcon = Assets.gangSwitch;
|
tempIcon = Assets.gangSwitch;
|
||||||
} else if (type == DeviceType.Gateway) {
|
} else if (type == DeviceType.Gateway) {
|
||||||
tempIcon = Assets.gateway;
|
tempIcon = Assets.gateway;
|
||||||
|
} else if (type == DeviceType.OneGang) {
|
||||||
|
tempIcon = Assets.oneGang;
|
||||||
|
} else if (type == DeviceType.TwoGang) {
|
||||||
|
tempIcon = Assets.twoGang;
|
||||||
|
} else if (type == DeviceType.WH) {
|
||||||
|
tempIcon = Assets.waterHeater;
|
||||||
|
} else if (type == DeviceType.DoorSensor) {
|
||||||
|
tempIcon = Assets.openCloseDoor;
|
||||||
|
} else if (type == DeviceType.GarageDoor) {
|
||||||
|
tempIcon = Assets.openedDoor;
|
||||||
|
} else if (type == DeviceType.WaterLeak) {
|
||||||
|
tempIcon = Assets.waterLeakNormal;
|
||||||
} else {
|
} else {
|
||||||
tempIcon = Assets.logo;
|
tempIcon = Assets.blackLogo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeviceModel(
|
return DeviceModel(
|
||||||
productUuid: json['productUuid'],
|
productUuid: json['productUuid'],
|
||||||
productType: json['productType'],
|
productType: json['productType'],
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/access_device_table.dart';
|
||||||
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||||
@ -49,7 +49,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
width: size.width,
|
width: size.width,
|
||||||
padding: EdgeInsets.all(15),
|
padding: const EdgeInsets.all(15),
|
||||||
decoration: containerDecoration.copyWith(
|
decoration: containerDecoration.copyWith(
|
||||||
color: ColorsManager.worningColor,
|
color: ColorsManager.worningColor,
|
||||||
border: Border.all(color: Color(0xffFFD22F)),
|
border: Border.all(color: Color(0xffFFD22F)),
|
||||||
@ -163,7 +163,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
child: state is TableLoaded
|
child: state is TableLoaded
|
||||||
? DynamicTable(
|
? AccessDeviceTable(
|
||||||
uuidIndex: 1,
|
uuidIndex: 1,
|
||||||
withSelectAll: true,
|
withSelectAll: true,
|
||||||
initialSelectedIds: selectedDeviceIds,
|
initialSelectedIds: selectedDeviceIds,
|
||||||
|
|||||||
@ -12,7 +12,6 @@ class AccessMangApi {
|
|||||||
path: ApiEndpoints.visitorPassword,
|
path: ApiEndpoints.visitorPassword,
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
print(json);
|
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
||||||
return PasswordModel.fromJson(jsonItem);
|
return PasswordModel.fromJson(jsonItem);
|
||||||
|
|||||||
@ -68,8 +68,7 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> deviceBatchControl(
|
Future<bool> deviceBatchControl(List<String> uuids, String code, dynamic value) async {
|
||||||
List<String> uuids, String code, dynamic value) async {
|
|
||||||
try {
|
try {
|
||||||
final body = {
|
final body = {
|
||||||
'devicesUuid': uuids,
|
'devicesUuid': uuids,
|
||||||
@ -93,8 +92,7 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<DeviceModel>> getDevicesByGatewayId(
|
static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
|
||||||
String gatewayId) async {
|
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
|
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
@ -128,9 +126,7 @@ class DevicesManagementApi {
|
|||||||
String code,
|
String code,
|
||||||
) async {
|
) async {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getDeviceLogs
|
path: ApiEndpoints.getDeviceLogs.replaceAll('{uuid}', uuid).replaceAll('{code}', code),
|
||||||
.replaceAll('{uuid}', uuid)
|
|
||||||
.replaceAll('{code}', code),
|
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return DeviceReport.fromJson(json);
|
return DeviceReport.fromJson(json);
|
||||||
@ -139,8 +135,7 @@ class DevicesManagementApi {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<DeviceReport> getDeviceReportsByDate(String uuid, String code,
|
static Future<DeviceReport> getDeviceReportsByDate(String uuid, String code, [String? from, String? to]) async {
|
||||||
[String? from, String? to]) async {
|
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getDeviceLogsByDate
|
path: ApiEndpoints.getDeviceLogsByDate
|
||||||
.replaceAll('{uuid}', uuid)
|
.replaceAll('{uuid}', uuid)
|
||||||
@ -179,8 +174,7 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> addScheduleRecord(
|
Future<bool> addScheduleRecord(ScheduleEntry sendSchedule, String uuid) async {
|
||||||
ScheduleEntry sendSchedule, String uuid) async {
|
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
|
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
|
||||||
@ -197,13 +191,10 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ScheduleModel>> getDeviceSchedules(
|
Future<List<ScheduleModel>> getDeviceSchedules(String uuid, String category) async {
|
||||||
String uuid, String category) async {
|
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getScheduleByDeviceId
|
path: ApiEndpoints.getScheduleByDeviceId.replaceAll('{deviceUuid}', uuid).replaceAll('{category}', category),
|
||||||
.replaceAll('{deviceUuid}', uuid)
|
|
||||||
.replaceAll('{category}', category),
|
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<ScheduleModel> schedules = [];
|
List<ScheduleModel> schedules = [];
|
||||||
@ -220,10 +211,7 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> updateScheduleRecord(
|
Future<bool> updateScheduleRecord({required bool enable, required String uuid, required String scheduleId}) async {
|
||||||
{required bool enable,
|
|
||||||
required String uuid,
|
|
||||||
required String scheduleId}) async {
|
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().put(
|
final response = await HTTPService().put(
|
||||||
path: ApiEndpoints.updateScheduleByDeviceId
|
path: ApiEndpoints.updateScheduleByDeviceId
|
||||||
@ -244,6 +232,22 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> editScheduleRecord(String uuid, ScheduleEntry newSchedule) async {
|
||||||
|
try {
|
||||||
|
final response = await HTTPService().put(
|
||||||
|
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
|
||||||
|
body: newSchedule.toMap(),
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json['success'] ?? false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error fetching $e');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> deleteScheduleRecord(String uuid, String scheduleId) async {
|
Future<bool> deleteScheduleRecord(String uuid, String scheduleId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().delete(
|
final response = await HTTPService().delete(
|
||||||
|
|||||||
@ -5,8 +5,7 @@ abstract class ColorsManager {
|
|||||||
static const Color switchOffColor = Color(0x7F8D99AE);
|
static const Color switchOffColor = Color(0x7F8D99AE);
|
||||||
static const Color primaryColor = Color(0xFF0030CB); //023DFE
|
static const Color primaryColor = Color(0xFF0030CB); //023DFE
|
||||||
static const Color secondaryTextColor = Color(0xFF848484);
|
static const Color secondaryTextColor = Color(0xFF848484);
|
||||||
static Color primaryColorWithOpacity =
|
static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
|
||||||
const Color(0xFF023DFE).withOpacity(0.6);
|
|
||||||
static const Color whiteColors = Colors.white;
|
static const Color whiteColors = Colors.white;
|
||||||
static const Color secondaryColor = Color(0xFF023DFE);
|
static const Color secondaryColor = Color(0xFF023DFE);
|
||||||
static const Color onSecondaryColor = Color(0xFF023DFE);
|
static const Color onSecondaryColor = Color(0xFF023DFE);
|
||||||
|
|||||||
@ -13,12 +13,10 @@ class Assets {
|
|||||||
static const String rightLine = "assets/images/right_line.png";
|
static const String rightLine = "assets/images/right_line.png";
|
||||||
static const String google = "assets/images/google.svg";
|
static const String google = "assets/images/google.svg";
|
||||||
static const String facebook = "assets/images/facebook.svg";
|
static const String facebook = "assets/images/facebook.svg";
|
||||||
static const String invisiblePassword =
|
static const String invisiblePassword = "assets/images/Password_invisible.svg";
|
||||||
"assets/images/Password_invisible.svg";
|
|
||||||
static const String visiblePassword = "assets/images/password_visible.svg";
|
static const String visiblePassword = "assets/images/password_visible.svg";
|
||||||
static const String accessIcon = "assets/images/access_icon.svg";
|
static const String accessIcon = "assets/images/access_icon.svg";
|
||||||
static const String spaseManagementIcon =
|
static const String spaseManagementIcon = "assets/images/spase_management_icon.svg";
|
||||||
"assets/images/spase_management_icon.svg";
|
|
||||||
static const String devicesIcon = "assets/images/devices_icon.svg";
|
static const String devicesIcon = "assets/images/devices_icon.svg";
|
||||||
static const String moveinIcon = "assets/images/movein_icon.svg";
|
static const String moveinIcon = "assets/images/movein_icon.svg";
|
||||||
static const String constructionIcon = "assets/images/construction_icon.svg";
|
static const String constructionIcon = "assets/images/construction_icon.svg";
|
||||||
@ -31,15 +29,13 @@ class Assets {
|
|||||||
static const String emptyTable = "assets/images/empty_table.svg";
|
static const String emptyTable = "assets/images/empty_table.svg";
|
||||||
|
|
||||||
// General assets
|
// General assets
|
||||||
static const String motionlessDetection =
|
static const String motionlessDetection = "assets/icons/motionless_detection.svg";
|
||||||
"assets/icons/motionless_detection.svg";
|
|
||||||
static const String acHeating = "assets/icons/ac_heating.svg";
|
static const String acHeating = "assets/icons/ac_heating.svg";
|
||||||
static const String acPowerOff = "assets/icons/ac_power_off.svg";
|
static const String acPowerOff = "assets/icons/ac_power_off.svg";
|
||||||
static const String acFanMiddle = "assets/icons/ac_fan_middle.svg";
|
static const String acFanMiddle = "assets/icons/ac_fan_middle.svg";
|
||||||
static const String switchAlarmSound = "assets/icons/switch_alarm_sound.svg";
|
static const String switchAlarmSound = "assets/icons/switch_alarm_sound.svg";
|
||||||
static const String resetOff = "assets/icons/reset_off.svg";
|
static const String resetOff = "assets/icons/reset_off.svg";
|
||||||
static const String sensitivityOperationIcon =
|
static const String sensitivityOperationIcon = "assets/icons/sesitivity_operation_icon.svg";
|
||||||
"assets/icons/sesitivity_operation_icon.svg";
|
|
||||||
static const String motionDetection = "assets/icons/motion_detection.svg";
|
static const String motionDetection = "assets/icons/motion_detection.svg";
|
||||||
static const String freezing = "assets/icons/freezing.svg";
|
static const String freezing = "assets/icons/freezing.svg";
|
||||||
static const String indicator = "assets/icons/indicator.svg";
|
static const String indicator = "assets/icons/indicator.svg";
|
||||||
@ -60,56 +56,35 @@ class Assets {
|
|||||||
static const String celsiusDegrees = "assets/icons/celsius_degrees.svg";
|
static const String celsiusDegrees = "assets/icons/celsius_degrees.svg";
|
||||||
static const String masterState = "assets/icons/master_state.svg";
|
static const String masterState = "assets/icons/master_state.svg";
|
||||||
static const String acPower = "assets/icons/ac_power.svg";
|
static const String acPower = "assets/icons/ac_power.svg";
|
||||||
static const String farDetectionFunction =
|
static const String farDetectionFunction = "assets/icons/far_detection_function.svg";
|
||||||
"assets/icons/far_detection_function.svg";
|
|
||||||
static const String nobodyTime = "assets/icons/nobody_time.svg";
|
static const String nobodyTime = "assets/icons/nobody_time.svg";
|
||||||
|
|
||||||
// Automation functions
|
// Automation functions
|
||||||
static const String tempPasswordUnlock =
|
static const String tempPasswordUnlock = "assets/icons/automation_functions/temp_password_unlock.svg";
|
||||||
"assets/icons/automation_functions/temp_password_unlock.svg";
|
static const String doorlockNormalOpen = "assets/icons/automation_functions/doorlock_normal_open.svg";
|
||||||
static const String doorlockNormalOpen =
|
static const String doorbell = "assets/icons/automation_functions/doorbell.svg";
|
||||||
"assets/icons/automation_functions/doorlock_normal_open.svg";
|
static const String remoteUnlockViaApp = "assets/icons/automation_functions/remote_unlock_via_app.svg";
|
||||||
static const String doorbell =
|
static const String doubleLock = "assets/icons/automation_functions/double_lock.svg";
|
||||||
"assets/icons/automation_functions/doorbell.svg";
|
static const String selfTestResult = "assets/icons/automation_functions/self_test_result.svg";
|
||||||
static const String remoteUnlockViaApp =
|
static const String lockAlarm = "assets/icons/automation_functions/lock_alarm.svg";
|
||||||
"assets/icons/automation_functions/remote_unlock_via_app.svg";
|
static const String presenceState = "assets/icons/automation_functions/presence_state.svg";
|
||||||
static const String doubleLock =
|
static const String currentTemp = "assets/icons/automation_functions/current_temp.svg";
|
||||||
"assets/icons/automation_functions/double_lock.svg";
|
static const String presence = "assets/icons/automation_functions/presence.svg";
|
||||||
static const String selfTestResult =
|
static const String residualElectricity = "assets/icons/automation_functions/residual_electricity.svg";
|
||||||
"assets/icons/automation_functions/self_test_result.svg";
|
static const String hijackAlarm = "assets/icons/automation_functions/hijack_alarm.svg";
|
||||||
static const String lockAlarm =
|
static const String passwordUnlock = "assets/icons/automation_functions/password_unlock.svg";
|
||||||
"assets/icons/automation_functions/lock_alarm.svg";
|
static const String remoteUnlockRequest = "assets/icons/automation_functions/remote_unlock_req.svg";
|
||||||
static const String presenceState =
|
static const String cardUnlock = "assets/icons/automation_functions/card_unlock.svg";
|
||||||
"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 residualElectricity =
|
|
||||||
"assets/icons/automation_functions/residual_electricity.svg";
|
|
||||||
static const String hijackAlarm =
|
|
||||||
"assets/icons/automation_functions/hijack_alarm.svg";
|
|
||||||
static const String passwordUnlock =
|
|
||||||
"assets/icons/automation_functions/password_unlock.svg";
|
|
||||||
static const String remoteUnlockRequest =
|
|
||||||
"assets/icons/automation_functions/remote_unlock_req.svg";
|
|
||||||
static const String cardUnlock =
|
|
||||||
"assets/icons/automation_functions/card_unlock.svg";
|
|
||||||
static const String motion = "assets/icons/automation_functions/motion.svg";
|
static const String motion = "assets/icons/automation_functions/motion.svg";
|
||||||
static const String fingerprintUnlock =
|
static const String fingerprintUnlock = "assets/icons/automation_functions/fingerprint_unlock.svg";
|
||||||
"assets/icons/automation_functions/fingerprint_unlock.svg";
|
|
||||||
|
|
||||||
// Presence Sensor Assets
|
// Presence Sensor Assets
|
||||||
static const String sensorMotionIcon = "assets/icons/sensor_motion_ic.svg";
|
static const String sensorMotionIcon = "assets/icons/sensor_motion_ic.svg";
|
||||||
static const String sensorPresenceIcon =
|
static const String sensorPresenceIcon = "assets/icons/sensor_presence_ic.svg";
|
||||||
"assets/icons/sensor_presence_ic.svg";
|
|
||||||
static const String sensorVacantIcon = "assets/icons/sensor_vacant_ic.svg";
|
static const String sensorVacantIcon = "assets/icons/sensor_vacant_ic.svg";
|
||||||
static const String illuminanceRecordIcon =
|
static const String illuminanceRecordIcon = "assets/icons/illuminance_record_ic.svg";
|
||||||
"assets/icons/illuminance_record_ic.svg";
|
static const String presenceRecordIcon = "assets/icons/presence_record_ic.svg";
|
||||||
static const String presenceRecordIcon =
|
static const String helpDescriptionIcon = "assets/icons/help_description_ic.svg";
|
||||||
"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 lightPulp = "assets/icons/light_pulb.svg";
|
||||||
static const String acDevice = "assets/icons/ac_device.svg";
|
static const String acDevice = "assets/icons/ac_device.svg";
|
||||||
@ -183,9 +158,14 @@ class Assets {
|
|||||||
//assets/icons/water_leak_normal.svg
|
//assets/icons/water_leak_normal.svg
|
||||||
static const String waterLeakNormal = 'assets/icons/water_leak_normal.svg';
|
static const String waterLeakNormal = 'assets/icons/water_leak_normal.svg';
|
||||||
//assets/icons/water_leak_detected.svg
|
//assets/icons/water_leak_detected.svg
|
||||||
static const String waterLeakDetected =
|
static const String waterLeakDetected = 'assets/icons/water_leak_detected.svg';
|
||||||
'assets/icons/water_leak_detected.svg';
|
|
||||||
|
|
||||||
//assets/icons/automation_records.svg
|
//assets/icons/automation_records.svg
|
||||||
static const String automationRecords = 'assets/icons/automation_records.svg';
|
static const String automationRecords = 'assets/icons/automation_records.svg';
|
||||||
|
|
||||||
|
//assets/icons/1gang.svg
|
||||||
|
static const String oneGang = 'assets/icons/1gang.svg';
|
||||||
|
|
||||||
|
//assets/icons/2gang.svg
|
||||||
|
static const String twoGang = 'assets/icons/2gang.svg';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,37 @@ enum DeviceType {
|
|||||||
DoorLock,
|
DoorLock,
|
||||||
Curtain,
|
Curtain,
|
||||||
Blind,
|
Blind,
|
||||||
|
OneGang,
|
||||||
|
TwoGang,
|
||||||
ThreeGang,
|
ThreeGang,
|
||||||
Gateway,
|
Gateway,
|
||||||
CeilingSensor,
|
CeilingSensor,
|
||||||
WallSensor,
|
WallSensor,
|
||||||
|
WH,
|
||||||
|
DoorSensor,
|
||||||
|
GarageDoor,
|
||||||
|
WaterLeak,
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
3G:
|
||||||
|
1G:
|
||||||
|
2G:
|
||||||
|
GW:
|
||||||
|
DL:
|
||||||
|
WPS:
|
||||||
|
CPS:
|
||||||
|
AC:
|
||||||
|
CUR:
|
||||||
|
WH:
|
||||||
|
DS:
|
||||||
|
1GT:
|
||||||
|
2GT:
|
||||||
|
3GT:
|
||||||
|
GD:
|
||||||
|
WL:
|
||||||
|
*/
|
||||||
|
|
||||||
Map<String, DeviceType> devicesTypesMap = {
|
Map<String, DeviceType> devicesTypesMap = {
|
||||||
"AC": DeviceType.AC,
|
"AC": DeviceType.AC,
|
||||||
@ -18,4 +43,14 @@ Map<String, DeviceType> devicesTypesMap = {
|
|||||||
"DL": DeviceType.DoorLock,
|
"DL": DeviceType.DoorLock,
|
||||||
"WPS": DeviceType.WallSensor,
|
"WPS": DeviceType.WallSensor,
|
||||||
"3G": DeviceType.ThreeGang,
|
"3G": DeviceType.ThreeGang,
|
||||||
|
"2G": DeviceType.TwoGang,
|
||||||
|
"1G": DeviceType.OneGang,
|
||||||
|
"CUR": DeviceType.Curtain,
|
||||||
|
"WH": DeviceType.WH,
|
||||||
|
'DS': DeviceType.DoorSensor,
|
||||||
|
"1GT": DeviceType.OneGang,
|
||||||
|
"2GT": DeviceType.TwoGang,
|
||||||
|
"3GT": DeviceType.ThreeGang,
|
||||||
|
'GD': DeviceType.GarageDoor,
|
||||||
|
'WL': DeviceType.WaterLeak
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user