curtain and forget password and select all check box and fix bugs

This commit is contained in:
mohammad
2024-09-08 17:09:32 +03:00
parent 67ea7af595
commit 85a04e504f
16 changed files with 708 additions and 352 deletions
+81 -28
View File
@@ -31,7 +31,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
////////////////////////////// forget password //////////////////////////////////
final TextEditingController forgetEmailController = TextEditingController();
final TextEditingController forgetPasswordController = TextEditingController();
final TextEditingController forgetPasswordController =
TextEditingController();
final TextEditingController forgetOtp = TextEditingController();
final forgetFormKey = GlobalKey<FormState>();
late bool checkValidate = false;
@@ -40,22 +41,55 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
int _remainingTime = 0;
List<RegionModel>? regionList = [RegionModel(name: 'name', id: 'id')];
Future<void> _onStartTimer(StartTimerEvent event, Emitter<AuthState> emit) async {
Future _onStartTimer(
StartTimerEvent event, Emitter<AuthState> emit) async {
if (_validateInputs(emit)) return;
if (_timer != null && _timer!.isActive) {
return;
}
_remainingTime = 1;
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
_remainingTime = (await AuthenticationAPI.sendOtp(
email: forgetEmailController.text, regionUuid: regionUuid))!;
add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false));
try {
forgetEmailValidate = '';
_remainingTime = (await AuthenticationAPI.sendOtp(
email: forgetEmailController.text, regionUuid: regionUuid))!;
} on DioException catch (e) {
if (e.response!.statusCode == 400) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('sendOtp=$errorMessage');
if (errorMessage == 'User not found') {
validate='Invalid Credential';
emit(AuthInitialState());
return 1;
} else {
validate='';
_remainingTime = errorData['data']['cooldown'] ?? 1;
emit(AuthInitialState());
}
} else {
emit(AuthInitialState());
return 1;
}
emit(AuthInitialState());
} catch (e) {
emit(AuthInitialState());
return 1;
}
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
_remainingTime--;
if (_remainingTime <= 0) {
_timer?.cancel();
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
} else {
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false));
}
});
}
@@ -65,14 +99,16 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
}
Future<void> changePassword(ChangePasswordEvent event, Emitter<AuthState> emit) async {
Future<void> changePassword(
ChangePasswordEvent event, Emitter<AuthState> emit) async {
try {
emit(LoadingForgetState());
var response = await AuthenticationAPI.verifyOtp(
email: forgetEmailController.text, otpCode: forgetOtp.text);
if (response == true) {
await AuthenticationAPI.forgetPassword(
password: forgetPasswordController.text, email: forgetEmailController.text);
password: forgetPasswordController.text,
email: forgetEmailController.text);
_timer?.cancel();
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
emit(SuccessForgetState());
@@ -89,7 +125,12 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
} else if (errorMessage == "OTP expired") {
forgetValidate = 'One time password has been expired.';
emit(AuthInitialState());
}else{
validate='';
emit(AuthInitialState());
}
}
}
@@ -101,7 +142,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
emit(TimerState(isButtonEnabled: event.isButtonEnabled, remainingTime: event.remainingTime));
emit(TimerState(
isButtonEnabled: event.isButtonEnabled,
remainingTime: event.remainingTime));
}
///////////////////////////////////// login /////////////////////////////////////
@@ -115,6 +158,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
String otpCode = '';
String validate = '';
String forgetValidate = '';
String forgetEmailValidate = '';
String regionUuid = '';
static Token token = Token.emptyConstructor();
static UserModel? user;
@@ -132,7 +176,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
token = await AuthenticationAPI.loginWithEmail(
model: LoginWithEmailModel(
email: event.username, password: event.password, regionUuid: event.regionUuid),
email: event.username,
password: event.password,
regionUuid: event.regionUuid),
);
} catch (failure) {
validate = 'Invalid Credentials!';
@@ -142,7 +188,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
if (token.accessTokenIsNotEmpty) {
FlutterSecureStorage storage = const FlutterSecureStorage();
await storage.write(key: Token.loginAccessTokenKey, value: token.accessToken);
await storage.write(
key: Token.loginAccessTokenKey, value: token.accessToken);
const FlutterSecureStorage().write(
key: UserModel.userUuidKey,
value: Token.decodeToken(token.accessToken)['uuid'].toString());
@@ -160,9 +207,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
checkBoxToggle(
CheckBoxEvent event,
Emitter<AuthState> emit,
) {
CheckBoxEvent event,
Emitter<AuthState> emit,
) {
emit(AuthLoading());
isChecked = event.newValue!;
add(CheckEnableEvent());
@@ -218,7 +265,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
emit(LoadingForgetState());
final nameError = validateEmail(forgetEmailController.text);
if (nameError != null) {
emit(FailureForgetState(error: nameError));
forgetEmailValidate = nameError;
emit(AuthInitialState());
// emit(FailureForgetState(error: nameError));
return true;
}
return false;
@@ -297,12 +346,14 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
static Future<String> getTokenAndValidate() async {
try {
const storage = FlutterSecureStorage();
final firstLaunch =
await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
final firstLaunch = await SharedPreferencesHelper.readBoolFromSP(
StringsManager.firstLaunch) ??
true;
if (firstLaunch) {
storage.deleteAll();
}
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
await SharedPreferencesHelper.saveBoolToSP(
StringsManager.firstLaunch, false);
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
if (value.isEmpty) {
return 'Token not found';
@@ -354,7 +405,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
final String formattedTime = [
if (days > 0) '${days}d', // Append 'd' for days
if (days > 0 || hours > 0)
hours.toString().padLeft(2, '0'), // Show hours if there are days or hours
hours
.toString()
.padLeft(2, '0'), // Show hours if there are days or hours
minutes.toString().padLeft(2, '0'),
seconds.toString().padLeft(2, '0'),
].join(':');
@@ -363,9 +416,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
bool checkEnable(
CheckEnableEvent event,
Emitter<AuthState> emit,
) {
CheckEnableEvent event,
Emitter<AuthState> emit,
) {
emit(AuthLoading());
checkValidate = isChecked == true &&
loginPasswordController.text.isNotEmpty &&
@@ -376,18 +429,18 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
changeValidate(
ChangeValidateEvent event,
Emitter<AuthState> emit,
) {
ChangeValidateEvent event,
Emitter<AuthState> emit,
) {
emit(AuthLoading());
validate = '';
emit(LoginInitial());
}
changeForgetValidate(
ChangeValidateEvent event,
Emitter<AuthState> emit,
) {
ChangeValidateEvent event,
Emitter<AuthState> emit,
) {
emit(AuthLoading());
forgetValidate = '';
emit(LoginInitial());
+258 -254
View File
@@ -64,307 +64,310 @@ class ForgetPasswordWebPage extends StatelessWidget {
Size size = MediaQuery.of(context).size;
return FirstLayer(
second: Center(
child: Stack(
children: [
if (state is AuthLoading)
const Center(child: CircularProgressIndicator()),
ListView(
shrinkWrap: true,
controller: _scrollController,
child: Stack(
children: [
Container(
padding: EdgeInsets.all(size.width * 0.02),
margin: EdgeInsets.all(size.width * 0.09),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(),
Expanded(
flex: 3,
child: SvgPicture.asset(
Assets.loginLogo,
),
),
const Spacer(),
Expanded(
flex: 3,
child: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius:
const BorderRadius.all(Radius.circular(30)),
border: Border.all(
color:
ColorsManager.graysColor.withOpacity(0.2)),
if (state is AuthLoading)
const Center(child: CircularProgressIndicator()),
ListView(
shrinkWrap: true,
controller: _scrollController,
children: [
Container(
padding: EdgeInsets.all(size.width * 0.02),
margin: EdgeInsets.all(size.width * 0.09),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(),
Expanded(
flex: 3,
child: SvgPicture.asset(
Assets.loginLogo,
),
),
child: Form(
key: forgetBloc.forgetFormKey,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.02,
vertical: size.width * 0.003),
child: Column(
mainAxisAlignment:
const Spacer(),
Expanded(
flex: 3,
child: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius:
const BorderRadius.all(Radius.circular(30)),
border: Border.all(
color:
ColorsManager.graysColor.withOpacity(0.2)),
),
child: Form(
key: forgetBloc.forgetFormKey,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.02,
vertical: size.width * 0.003),
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 10),
const Text(
'Forget Password',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
Text(
'Please fill in your account information to\nretrieve your password',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 10),
const Text(
'Forget Password',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
Text(
'Please fill in your account information to\nretrieve your password',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
),
const SizedBox(height: 10),
SizedBox(
child: _buildDropdownField(context, forgetBloc, size)
)
],
),
const SizedBox(height: 20),
Column(
crossAxisAlignment:
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Account",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 10),
SizedBox(
child: _buildDropdownField(context, forgetBloc, size)
)
],
),
const SizedBox(height: 20),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Account",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
controller:forgetBloc.forgetEmailController ,
validator: forgetBloc.validateEmail,
decoration: textBoxDecoration()!.copyWith(
hintText: 'Enter your email',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
),
style: const TextStyle(
color: Colors.black),
),
),
if(forgetBloc.forgetEmailValidate!='')
SizedBox(
child: Text(
forgetBloc.forgetEmailValidate,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: ColorsManager.red),
),
),
const SizedBox(height: 10.0),
],
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
controller:forgetBloc.forgetEmailController ,
validator: forgetBloc.validateEmail,
decoration: textBoxDecoration()!
.copyWith(
hintText: 'Enter your email',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400)),
style: const TextStyle(
color: Colors.black),
),
),
],
),
const SizedBox(height: 20.0),
Column(
crossAxisAlignment:
const SizedBox(height: 20.0),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"One Time Password",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"One Time Password",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
validator: forgetBloc.validateCode,
keyboardType:
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
validator: forgetBloc.validateCode,
keyboardType:
TextInputType.visiblePassword,
controller: forgetBloc.forgetOtp,
decoration:
controller: forgetBloc.forgetOtp,
decoration:
textBoxDecoration()!.copyWith(
hintText: 'Enter Code',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
suffixIcon: SizedBox(
width: 100,
child: Center(
child: InkWell(
onTap: state is TimerState &&
hintText: 'Enter Code',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
suffixIcon: SizedBox(
width: 100,
child: Center(
child: InkWell(
onTap: state is TimerState &&
!state.isButtonEnabled &&
state.remainingTime !=
1
? null
: () {
forgetBloc.add(
StartTimerEvent());
},
child: Text(
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
style: TextStyle(
color: state is TimerState &&
state.remainingTime != 1
? null : () {
forgetBloc.add(StartTimerEvent());
},
child: Text(
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
style: TextStyle(
color: state is TimerState &&
!state.isButtonEnabled
? Colors.grey
: ColorsManager
.btnColor,
? Colors.grey
: ColorsManager.btnColor,
),
),
),
),
),
),
style: const TextStyle(
color: Colors.black),
),
),
style: const TextStyle(
color: Colors.black),
),
),
if (forgetBloc.forgetValidate != '') // Check if there is a validation message
Padding(
padding:
if (forgetBloc.forgetValidate != '') // Check if there is a validation message
Padding(
padding:
const EdgeInsets.only(top: 8.0),
child: Text(
forgetBloc.forgetValidate,
style: const TextStyle(
color: ColorsManager.red,
fontSize: 10,
fontWeight: FontWeight.w700),
),
),
],
),
const SizedBox(height: 20.0),
Column(
crossAxisAlignment:
child: Text(
forgetBloc.forgetValidate,
style: const TextStyle(
color: ColorsManager.red,
fontSize: 10,
fontWeight: FontWeight.w700),
),
),
],
),
const SizedBox(height: 20.0),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Password",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Password",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
validator: forgetBloc.passwordValidator,
keyboardType: TextInputType.visiblePassword,
controller: forgetBloc.forgetPasswordController,
decoration: textBoxDecoration()!.copyWith(
hintText: 'At least 8 characters',
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
validator: forgetBloc.passwordValidator,
keyboardType: TextInputType.visiblePassword,
controller: forgetBloc.forgetPasswordController,
decoration: textBoxDecoration()!.copyWith(
hintText: 'At least 8 characters',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
),
style: const TextStyle(color: Colors.black),
),
),
style: const TextStyle(color: Colors.black),
),
],
),
],
),
const SizedBox(
height: 10,
),
const SizedBox(height: 20.0),
Row(
crossAxisAlignment:
const SizedBox(
height: 10,
),
const SizedBox(height: 20.0),
Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: size.width * 0.2,
child: DefaultButton(
backgroundColor:
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: size.width * 0.2,
child: DefaultButton(
backgroundColor:
ColorsManager.btnColor,
child: const Text('Submit'),
onPressed: () {
if (forgetBloc
.forgetFormKey.currentState!
.validate()) {
forgetBloc.add(ChangePasswordEvent());
}
},
child: const Text('Submit'),
onPressed: () {
if (forgetBloc.forgetFormKey.currentState!.validate()) {
forgetBloc.add(ChangePasswordEvent());
}
},
),
),
],
),
const SizedBox(height: 10.0),
Center(
child: SizedBox(
child: Text(
forgetBloc.validate,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: ColorsManager.red),
),
),
),
const SizedBox(
height: 10,
),
SizedBox(
child: Center(
child: Wrap(
children: [
const Text(
"Do you have an account? ",
style: TextStyle(color: Colors.white),
),
InkWell(
onTap: () {
forgetBloc.add(StopTimerEvent());
Navigator.pop(context);
},
child: const Text(
"Sign in",
),
),
],
),
),
),
const SizedBox(height: 15.0),
],
),
const SizedBox(height: 10.0),
Center(
child: SizedBox(
child: Text(
forgetBloc.validate,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: ColorsManager.red),
),
),
),
SizedBox(
height: 10,
),
SizedBox(
width: size.width * 0.2,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
const Flexible(
child: Text(
"Do you have an account? ",
style: TextStyle(color: Colors.white),
)),
InkWell(
onTap: () {
forgetBloc.add(StopTimerEvent());
Navigator.pop(context);
},
child: const Flexible(
child: Text(
"Sign in",
)),
),
],
),
),
const SizedBox(height: 15.0),
],
),
),
),
),
),
const Spacer(),
],
),
const Spacer(),
],
),
),
),
],
),
],
),
],
),
));
));
}
Widget _buildDropdownField(
BuildContext context, AuthBloc loginBloc, Size size) {
final TextEditingController textEditingController = TextEditingController();
@@ -467,6 +470,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
),
),
),
],
);
}
+83
View File
@@ -0,0 +1,83 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class CurtainToggle extends StatelessWidget {
final bool value;
final String code;
final String deviceId;
final String label;
const CurtainToggle({
super.key,
required this.value,
required this.code,
required this.deviceId,
required this.label,
});
@override
Widget build(BuildContext context) {
return Container(
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(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipOval(
child: Container(
color: ColorsManager.whiteColors,
child: SvgPicture.asset(
Assets.curtainIcon,
width: 60,
height: 60,
fit: BoxFit.cover,
),
)),
SizedBox(
height: 20,
width: 35,
child: CupertinoSwitch(
value: value,
activeColor: ColorsManager.dialogBlueTitle,
onChanged: (newValue) {
context.read<LivingRoomBloc>().add(
LivingRoomControl(
deviceId: deviceId,
code: code,
value: newValue,
),
);
},
),
),
],
),
const Spacer(),
Text(
label,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
],
),
);
}
}
+2 -2
View File
@@ -48,11 +48,11 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
value: _isPm,
items: const [
DropdownMenuItem(
value: false,
value: true,
child: Text('AM'),
),
DropdownMenuItem(
value: true,
value:false ,
child: Text('PM'),
),
],
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/ac_device_control.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart';
import 'package:syncrow_web/pages/device_managment/curtain/view/curtain_control.dart';
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_status_view.dart';
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_view.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_device_control.dart';
@@ -27,6 +28,10 @@ mixin RouteControlsBasedCode {
return CeilingSensorControls(
device: device,
);
case 'CUR':
return CurtainControl(
deviceId: device.uuid!,
);
case 'AC':
return AcDeviceControl(device: device);
default:
@@ -116,7 +116,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
? const EdgeInsets.all(30)
: const EdgeInsets.all(15),
child: DynamicTable(
withSelectAll: false,
withSelectAll: true,
cellDecoration: containerDecoration,
onRowSelected: (index, isSelected, row) {
final selectedDevice = devicesToShow[index];
@@ -0,0 +1,40 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_event.dart';
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_state.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';
class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
late bool deviceStatus;
final String deviceId;
CurtainBloc({required this.deviceId}) : super(CurtainInitial()) {
on<CurtainFetchDeviceStatus>(_onFetchDeviceStatus);
}
FutureOr<void> _onFetchDeviceStatus(
CurtainFetchDeviceStatus event, Emitter<CurtainState> emit) async {
emit(CurtainStatusLoading());
try {
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
deviceStatus =checkStatus(status.status[0].value) ; // Assuming this is a Map<String, dynamic>
emit(CurtainStatusLoaded(deviceStatus));
} catch (e) {
emit(CurtainError(e.toString()));
}
}
bool checkStatus(String command) {
if (command.toLowerCase() == 'open') {
return true;
} else {
return false;
}
}
}
@@ -0,0 +1,32 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
sealed class CurtainEvent extends Equatable {
const CurtainEvent();
@override
List<Object> get props => [];
}
class CurtainFetchDeviceStatus extends CurtainEvent {
final String deviceId;
const CurtainFetchDeviceStatus(this.deviceId);
@override
List<Object> get props => [deviceId];
}
class CurtainControl extends CurtainEvent {
final String deviceId;
final String code;
final bool value;
const CurtainControl(
{required this.deviceId, required this.code, required this.value});
@override
List<Object> get props => [deviceId, code, value];
}
@@ -0,0 +1,41 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/device_managment/curtain/model/curtain_model.dart';
sealed class CurtainState extends Equatable {
const CurtainState();
@override
List<Object> get props => [];
}
final class CurtainInitial extends CurtainState {}
class CurtainStatusLoading extends CurtainState {}
class CurtainStatusLoaded extends CurtainState {
final bool status;
const CurtainStatusLoaded(this.status);
@override
List<Object> get props => [status];
}
class CurtainError extends CurtainState {
final String message;
const CurtainError(this.message);
@override
List<Object> get props => [message];
}
class CurtainControlError extends CurtainState {
final String message;
const CurtainControlError(this.message);
@override
List<Object> get props => [message];
}
@@ -0,0 +1,32 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
class CurtainModel {
final String productUuid;
final String productType;
final List<Status> status;
CurtainModel({
required this.productUuid,
required this.productType,
required this.status,
});
factory CurtainModel.fromJson(dynamic json) {
var statusList = json['status'] as List;
List<Status> status = statusList.map((i) => Status.fromJson(i)).toList();
return CurtainModel(
productUuid: json['productUuid'],
productType: json['productType'],
status: status,
);
}
Map<String, dynamic> toJson() {
return {
'productUuid': productUuid,
'productType': productType,
'status': status.map((s) => s!.toJson()).toList(),
};
}
}
@@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/curtain_toggle.dart';
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_event.dart';
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_state.dart';
import 'package:syncrow_web/pages/device_managment/curtain/model/curtain_model.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class CurtainControl extends StatelessWidget with HelperResponsiveLayout {
final String deviceId;
const CurtainControl({super.key, required this.deviceId});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
CurtainBloc(deviceId: deviceId)..add(CurtainFetchDeviceStatus(deviceId)),
child: BlocBuilder<CurtainBloc, CurtainState>(
builder: (context, state) {
if (state is CurtainStatusLoading) {
return const Center(child: CircularProgressIndicator());
} else if (state is CurtainStatusLoaded) {
return _buildStatusControls(context, state.status);
} else if (state is CurtainError || state is CurtainControlError) {
return const Center(child: Text('Error fetching status'));
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
Widget _buildStatusControls(BuildContext context, bool status) {
final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context);
return Container(
child: GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
CurtainToggle(
value: status,
code: 'Curtains',
deviceId: deviceId,
label: 'Curtains',
),
],
),
);
}
}
@@ -35,40 +35,42 @@ class LivingRoomDeviceControl extends StatelessWidget with HelperResponsiveLayou
final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context);
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
return Container(
child: GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
ToggleWidget(
value: status.switch1,
code: 'switch_1',
deviceId: deviceId,
label: 'Wall Light',
),
ToggleWidget(
value: status.switch2,
code: 'switch_2',
deviceId: deviceId,
label: 'Ceiling Light',
),
ToggleWidget(
value: status.switch3,
code: 'switch_3',
deviceId: deviceId,
label: 'Spotlight',
),
],
),
children: [
ToggleWidget(
value: status.switch1,
code: 'switch_1',
deviceId: deviceId,
label: 'Wall Light',
),
ToggleWidget(
value: status.switch2,
code: 'switch_2',
deviceId: deviceId,
label: 'Ceiling Light',
),
ToggleWidget(
value: status.switch3,
code: 'switch_3',
deviceId: deviceId,
label: 'Spotlight',
),
],
);
}
}
+7 -34
View File
@@ -29,40 +29,13 @@ class AuthenticationAPI {
}
static Future<int?> sendOtp({required String email, required String regionUuid}) async {
try {
final response = await HTTPService().post(
path: ApiEndpoints.sendOtp,
body: {"email": email, "type": "PASSWORD", "regionUuid": regionUuid},
showServerMessage: true,
expectedResponseModel: (json) {
return json['data']['cooldown'];
});
return response;
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('sendOtp=$errorMessage');
if (e.response != null) {
if (e.response!.statusCode == 400) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('sendOtp=$errorMessage');
if (errorMessage == 'User not found') {
return 1;
} else {
int cooldown = errorData['data']['cooldown'] ?? 1;
return cooldown;
}
} else {
return 1;
}
} else {
return 1;
}
} catch (e) {
return 1;
}
final response = await HTTPService().post(
path: ApiEndpoints.sendOtp,
body: {"email": email, "type": "PASSWORD", "regionUuid": regionUuid},
showServerMessage: true,
expectedResponseModel: (json) {
return json['data']['cooldown'];
});
}
static Future verifyOtp({required String email, required String otpCode}) async {
+1
View File
@@ -33,6 +33,7 @@ class DevicesManagementApi {
path: ApiEndpoints.getDeviceStatus.replaceAll('{uuid}', uuid),
showServerMessage: true,
expectedResponseModel: (json) {
print('getDeviceStatus$json');
return DeviceStatus.fromJson(json);
},
);
+1
View File
@@ -124,4 +124,5 @@ class Assets {
static const String office = 'assets/icons/office.svg';
static const String parlour = 'assets/icons/parlour.svg';
static const String grid = "assets/images/grid.svg";
static const String curtainIcon = "assets/images/curtain.svg";
}