four_scene

This commit is contained in:
mohammad
2024-11-19 11:31:17 +03:00
parent f1bb454429
commit 1be6d71e89
7 changed files with 151 additions and 10 deletions

View File

@ -18,6 +18,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart'; import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart'; import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart'; import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> { class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
final String fourSceneId; final String fourSceneId;
@ -27,6 +28,7 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
on<FourSceneInitial>(_fetchStatus); on<FourSceneInitial>(_fetchStatus);
on<FourSceneInitialInfo>(fetchDeviceData); on<FourSceneInitialInfo>(fetchDeviceData);
on<ReportLogsInitial>(fetchLogsForLastMonth); on<ReportLogsInitial>(fetchLogsForLastMonth);
on<SaveNameEvent>(saveName);
on<ToggleNotificationEvent>(_toggleNotification); on<ToggleNotificationEvent>(_toggleNotification);
on<ChangeNameEvent>(_changeName); on<ChangeNameEvent>(_changeName);
on<SearchFaqEvent>(_onSearchFaq); on<SearchFaqEvent>(_onSearchFaq);
@ -40,6 +42,7 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
on<AddDeviceToGroup>(_addDeviceToGroup); on<AddDeviceToGroup>(_addDeviceToGroup);
on<RemoveDeviceFromGroup>(_removeDeviceFromGroup); on<RemoveDeviceFromGroup>(_removeDeviceFromGroup);
on<FourSceneInitialQuestion>(_onFourSceneInitial); on<FourSceneInitialQuestion>(_onFourSceneInitial);
on<FetchDeviceScene>(_fetchDeviceScene);
} }
final TextEditingController nameController = final TextEditingController nameController =
@ -93,6 +96,47 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
), ),
); );
// void changeDeviceName(
// SaveNameEvent event, Emitter<FourSceneState> emit) async {
// emit(FourSceneLoadingState());
// try {
// var response = await DevicesAPI.putDeviceName(
// deviceId: fourSceneId, deviceName: event.deviceName!);
// List<StatusModel> statusModelList = [];
// for (var status in response['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// }
// deviceStatus = FourSceneModel.fromJson(
// statusModelList,
// );
// emit(UpdateState(sensor: deviceStatus));
// Future.delayed(const Duration(milliseconds: 500));
// // _listenToChanges();
// } catch (e) {
// emit(FourSceneFailedState(errorMessage: e.toString()));
// return;
// }
// }
Future<void> saveName(
SaveNameEvent event, Emitter<FourSceneState> emit) async {
if (_validateInputs()) return;
try {
add(const ChangeNameEvent(value: false));
isSaving = true;
emit(FourSceneLoadingState());
var response = await DevicesAPI.putDeviceName(
deviceId: fourSceneId, deviceName: nameController.text);
add(FourSceneInitialInfo());
CustomSnackBar.displaySnackBar('Save Successfully');
emit(SaveState());
} catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString()));
} finally {
isSaving = false;
}
}
void _fetchStatus( void _fetchStatus(
FourSceneInitial event, Emitter<FourSceneState> emit) async { FourSceneInitial event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState()); emit(FourSceneLoadingState());
@ -114,6 +158,27 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
} }
} }
void _fetchDeviceScene(
FetchDeviceScene event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(fourSceneId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = FourSceneModel.fromJson(
statusModelList,
);
emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString()));
return;
}
}
Future fetchDeviceData( Future fetchDeviceData(
FourSceneInitialInfo event, Emitter<FourSceneState> emit) async { FourSceneInitialInfo event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState()); emit(FourSceneLoadingState());
@ -369,6 +434,8 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
allDevices.forEach((element) { allDevices.forEach((element) {
allDevicesIds.add(element.uuid!); allDevicesIds.add(element.uuid!);
}); });
CustomSnackBar.displaySnackBar('Save Successfully');
emit(SaveSelectionSuccessState()); emit(SaveSelectionSuccessState());
} }
} catch (e) { } catch (e) {
@ -376,5 +443,27 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
return; return;
} }
} }
bool _validateInputs() {
final nameError = fullNameValidator(nameController.text);
if (nameError != null) {
CustomSnackBar.displaySnackBar(nameError);
return true;
}
return false;
}
String? fullNameValidator(String? value) {
if (value == null) return 'name is required';
final withoutExtraSpaces = value.replaceAll(RegExp(r"\s+"), ' ').trim();
if (withoutExtraSpaces.length < 2 || withoutExtraSpaces.length > 30) {
return 'Full name must be between 2 and 30 characters long';
}
// Test if it contains anything but alphanumeric spaces and single quote
if (RegExp(r"/[^ a-zA-Z0-9-\']/").hasMatch(withoutExtraSpaces)) {
return 'Only alphanumeric characters, space, dash and single quote are allowed';
}
return null;
}
} }

View File

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart'; import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
@ -23,12 +24,19 @@ class FourSceneSwitch extends FourSceneEvent {
} }
class FourSceneUpdated extends FourSceneEvent {} class FourSceneUpdated extends FourSceneEvent {}
class FourSceneInitialInfo extends FourSceneEvent {} class FourSceneInitialInfo extends FourSceneEvent {}
class FourSceneInitial extends FourSceneEvent { class FourSceneInitial extends FourSceneEvent {
const FourSceneInitial(); const FourSceneInitial();
} }
class SaveNameEvent extends FourSceneEvent {
final String? deviceName;
const SaveNameEvent({this.deviceName});
}
class ReportLogsInitial extends FourSceneEvent { class ReportLogsInitial extends FourSceneEvent {
const ReportLogsInitial(); const ReportLogsInitial();
} }
@ -173,19 +181,25 @@ class RemoveDeviceFromGroup extends FourSceneEvent {
RemoveDeviceFromGroup(this.device, this.icon); RemoveDeviceFromGroup(this.device, this.icon);
} }
class AssignRoomEvent extends FourSceneEvent { class AssignRoomEvent extends FourSceneEvent {
final String roomId; final String roomId;
final SpaceModel unit; final SpaceModel unit;
final BuildContext context;
const AssignRoomEvent({ const AssignRoomEvent({
required this.roomId, required this.roomId,
required this.unit, required this.unit,
required this.context,
}); });
@override @override
List<Object> get props => [ List<Object> get props => [
roomId, roomId,
unit, unit,
context,
]; ];
} }
class FetchDeviceScene extends FourSceneEvent {
const FetchDeviceScene();
}

View File

@ -97,6 +97,7 @@ class SceneLoaded extends FourSceneState {
class SelectedSceneState extends FourSceneState {} class SelectedSceneState extends FourSceneState {}
class SearchResultsState extends FourSceneState {} class SearchResultsState extends FourSceneState {}
class SaveState extends FourSceneState {}
class SaveSelectionSuccessState extends FourSceneState {} class SaveSelectionSuccessState extends FourSceneState {}

View File

@ -25,6 +25,11 @@ class FourSceneProfilePage extends StatelessWidget {
return DefaultScaffold( return DefaultScaffold(
title: 'Device Settings', title: 'Device Settings',
leading: IconButton(
onPressed: () {
Navigator.of(context).pop(true);
},
icon: const Icon(Icons.arrow_back_ios)),
child: BlocProvider( child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '') create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitial()) ..add(const FourSceneInitial())
@ -93,7 +98,7 @@ class FourSceneProfilePage extends StatelessWidget {
controller: _bloc.nameController, controller: _bloc.nameController,
enabled: _bloc.editName, enabled: _bloc.editName,
onEditingComplete: () { onEditingComplete: () {
// sensor.add(SaveNameEvent(context: context)); _bloc.add(const SaveNameEvent());
}, },
decoration: const InputDecoration( decoration: const InputDecoration(
hintText: "Your Name", hintText: "Your Name",
@ -131,19 +136,22 @@ class FourSceneProfilePage extends StatelessWidget {
DefaultContainer( DefaultContainer(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
child: InkWell( child: InkWell(
onTap: () { onTap: () async {
Navigator.of(context).push( bool val = await Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => LocationFourScenePage( builder: (context) => LocationFourScenePage(
space: spaces!.first, space: spaces!.first,
deviceId: device?.uuid ?? '', deviceId: device?.uuid ?? '',
)), )),
); );
if (val == true) {
_bloc.add(FourSceneInitialInfo());
}
}, },
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox( const SizedBox(
child: Text('Location'), child: Text('Location'),
), ),
Row( Row(
@ -155,7 +163,7 @@ class FourSceneProfilePage extends StatelessWidget {
fontColor: ColorsManager.textGray, fontColor: ColorsManager.textGray,
), ),
), ),
Icon( const Icon(
Icons.arrow_forward_ios, Icons.arrow_forward_ios,
size: 15, size: 15,
color: ColorsManager.textGray, color: ColorsManager.textGray,

View File

@ -69,14 +69,17 @@ class FourSceneSettings extends StatelessWidget {
vertical: 10, vertical: 10,
), ),
child: InkWell( child: InkWell(
onTap: () { onTap: () async {
Navigator.of(context).push( bool val = await Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => FourSceneProfilePage( builder: (context) => FourSceneProfilePage(
device: device, device: device,
), ),
), ),
); );
if (val == true) {
_bloc.add(FourSceneInitialInfo());
}
}, },
child: Stack( child: Stack(
children: [ children: [
@ -161,7 +164,9 @@ class FourSceneSettings extends StatelessWidget {
onTap: () { onTap: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => FourSceneInfoPage( device: device!,)), builder: (context) => FourSceneInfoPage(
device: device!,
)),
); );
}, },
text: 'Device Information', text: 'Device Information',

View File

@ -41,6 +41,12 @@ class LocationFourScenePage extends StatelessWidget {
scene_4: '', scene_4: '',
scene_id_group_id: '', scene_id_group_id: '',
switch_backlight: ''); switch_backlight: '');
if (state is SaveSelectionSuccessState) {
new Future.delayed(const Duration(microseconds: 500), () {
_bloc.add(FourSceneInitialInfo());
Navigator.of(context).pop(true);
});
}
return state is FourSceneLoadingState return state is FourSceneLoadingState
? const Center( ? const Center(
child: DefaultContainer( child: DefaultContainer(
@ -60,6 +66,7 @@ class LocationFourScenePage extends StatelessWidget {
? () { ? () {
context.read<FourSceneBloc>().add( context.read<FourSceneBloc>().add(
AssignRoomEvent( AssignRoomEvent(
context: context,
roomId: roomIdSelected, roomId: roomIdSelected,
unit: space!)); unit: space!));
} }
@ -77,6 +84,7 @@ class LocationFourScenePage extends StatelessWidget {
), ),
const SizedBox(width: 20), const SizedBox(width: 20),
], ],
child: RefreshIndicator( child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
// sensor.add(const SosInitial()); // sensor.add(const SosInitial());

View File

@ -31,6 +31,22 @@ class DevicesAPI {
} }
} }
static Future<Map<String, dynamic>> putDeviceName(
{required String deviceId, required String deviceName}) async {
try {
final response = await _httpService.put(
path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
body: {"deviceName": deviceName},
expectedResponseModel: (json) {
return json;
},
);
return response;
} catch (e) {
rethrow;
}
}
static Future<Map<String, dynamic>> controlDevice( static Future<Map<String, dynamic>> controlDevice(
DeviceControlModel controlModel, String deviceId) async { DeviceControlModel controlModel, String deviceId) async {
try { try {