Compare commits

..

4 Commits

Author SHA1 Message Date
5d32fc1213 Resend 2024-10-30 12:18:16 +03:00
bfd9c557ce remove_real_time 2024-10-30 11:56:12 +03:00
ef232e9cd5 password_changes&_routine_changes 2024-10-29 17:21:31 +03:00
a1b8c79ce4 Merge pull request #61 from SyncrowIOT/power_clamp_issue
power_clamp_issue&search_issue
2024-10-29 11:10:44 +03:00
28 changed files with 428 additions and 174 deletions

View File

@ -237,26 +237,34 @@ class AuthCubit extends Cubit<AuthState> {
}
}
sendOtp() async {
sendOtp({bool? isforget}) async {
try {
emit(AuthLoading());
await AuthenticationAPI.sendOtp(
body: {'email': email, 'type': 'VERIFICATION'});
await AuthenticationAPI.sendOtp(body: {
'email': email,
'type': isforget == true ? 'PASSWORD' : 'VERIFICATION'
});
emit(AuthSignUpSuccess());
} catch (_) {
emit(AuthLoginError(message: 'Something went wrong'));
emit(AuthErrorStatusWithoutMsg());
// emit(AuthLoginError(message: 'Something went wrong'));
}
}
Future<bool> reSendOtp() async {
Future<bool> reSendOtp({bool? forget}) async {
try {
emit(AuthLoading());
await AuthenticationAPI.sendOtp(
body: {'email': email, 'type': 'VERIFICATION'});
await AuthenticationAPI.sendOtp(body: {
'email': email,
'type': forget == true ? 'PASSWORD' : 'VERIFICATION'
});
emit(ResendOtpSuccess());
return true;
} catch (_) {
emit(AuthLoginError(message: 'Something went wrong'));
emit(AuthErrorStatusWithoutMsg());
// emit(AuthLoginError(message: 'Something went wrong'));
return false;
}
}
@ -264,8 +272,11 @@ class AuthCubit extends Cubit<AuthState> {
verifyOtp(bool isForgotPass) async {
emit(AuthLoginLoading());
try {
final response = await AuthenticationAPI.verifyPassCode(
body: {'email': email, 'type': 'VERIFICATION', 'otpCode': otpCode});
final response = await AuthenticationAPI.verifyPassCode(body: {
'email': email,
'type': isForgotPass == true ? 'PASSWORD' : 'VERIFICATION',
'otpCode': otpCode
});
if (response['statusCode'] == 200) {
if (!isForgotPass) {
emailController.text = email;
@ -292,7 +303,9 @@ class AuthCubit extends Cubit<AuthState> {
(Route route) => false,
);
} catch (failure) {
emit(AuthLogoutError(message: 'Something went wrong'));
emit(AuthErrorStatusWithoutMsg());
// emit(AuthLogoutError(message: 'Something went wrong'));
return;
}
}
@ -333,17 +346,22 @@ class AuthCubit extends Cubit<AuthState> {
emit(AuthTokenError(message: "Something went wrong"));
}
} catch (_) {
emit(AuthTokenError(message: "Something went wrong"));
emit(AuthErrorStatusWithoutMsg());
// emit(AuthTokenError(message: "Something went wrong"));
}
}
sendToForgetPassword({required String password}) async {
try {
emit(AuthForgetPassLoading());
await AuthenticationAPI.forgetPassword(email: email, password: password);
await AuthenticationAPI.forgetPassword(
email: email, password: password, otpCode: otpCode);
emit(AuthForgetPassSuccess());
} catch (_) {
emit(AuthForgetPassError(message: 'Something went wrong'));
emit(AuthErrorStatusWithoutMsg());
// emit(AuthForgetPassError(message: 'Something went wrong'));
}
}
}

View File

@ -52,9 +52,6 @@ class AuthTokenError extends AuthError {
AuthTokenError({required super.message, super.code});
}
//ForgetPassword log states
class AuthForgetPassLoading extends AuthLoading {}
@ -64,3 +61,6 @@ class AuthForgetPassError extends AuthError {
AuthForgetPassError({required super.message, super.code});
}
class AuthErrorStatusWithoutMsg extends AuthState {
AuthErrorStatusWithoutMsg();
}

View File

@ -15,13 +15,15 @@ import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:syncrow_app/utils/resource_manager/styles_manager.dart';
class checkEmailPage extends StatelessWidget {
const checkEmailPage({super.key});
bool? forget;
checkEmailPage({super.key, this.forget});
@override
Widget build(BuildContext context) {
final formKey = AuthCubit.get(context).checkEmailFormKey;
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarBrightness: Brightness.light, statusBarIconBrightness: Brightness.light));
statusBarBrightness: Brightness.light,
statusBarIconBrightness: Brightness.light));
return BlocConsumer<AuthCubit, AuthState>(
listener: (context, state) {
if (state is AuthError) {
@ -34,8 +36,8 @@ class checkEmailPage extends StatelessWidget {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const OtpView(
isForgetPage: true,
builder: (context) => OtpView(
isForgetPage: forget!,
),
));
}
@ -91,7 +93,9 @@ class checkEmailPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: MediaQuery.sizeOf(context).height / 5.5,
height:
MediaQuery.sizeOf(context).height /
5.5,
),
TitleMedium(
text: 'Forgot password?',
@ -113,32 +117,39 @@ class checkEmailPage extends StatelessWidget {
scrollPadding: EdgeInsets.zero,
autocorrect: false,
enableSuggestions: false,
autofillHints: const [AutofillHints.email],
validator: AuthCubit.get(context).emailAddressValidator,
autofillHints: const [
AutofillHints.email
],
validator: AuthCubit.get(context)
.emailAddressValidator,
onTapOutside: (event) {
FocusScope.of(context).unfocus();
},
onChanged: (value) {
AuthCubit.get(context).email = value;
},
decoration: defaultInputDecoration(context,
decoration: defaultInputDecoration(
context,
hint: "Example@email.com"),
),
const SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Expanded(
child: DefaultButton(
isDone: state is AuthLoginSuccess,
isLoading: state is AuthLoading,
customButtonStyle: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
backgroundColor:
MaterialStateProperty.all(
Colors.black.withOpacity(.25),
),
foregroundColor: MaterialStateProperty.all(
foregroundColor:
MaterialStateProperty.all(
Colors.white,
),
),
@ -146,11 +157,16 @@ class checkEmailPage extends StatelessWidget {
'Send Code',
),
onPressed: () {
AuthCubit.get(context).showValidationMessage = true;
if (formKey.currentState!.validate()) {
AuthCubit.get(context)
.showValidationMessage = true;
if (formKey.currentState!
.validate()) {
if ((state is! AuthLoading)) {
AuthCubit.get(context).sendOtp();
FocusScope.of(context).unfocus();
AuthCubit.get(context)
.sendOtp(
isforget: forget);
FocusScope.of(context)
.unfocus();
}
}
},
@ -160,14 +176,17 @@ class checkEmailPage extends StatelessWidget {
),
Padding(
padding: EdgeInsets.only(
top: MediaQuery.sizeOf(context).height / 5.5),
top: MediaQuery.sizeOf(context)
.height /
5.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
BodyLarge(
text: "Do you have an account? ",
style:
context.displaySmall.copyWith(color: Colors.white),
style: context.displaySmall
.copyWith(color: Colors.white),
),
TextButton(
onPressed: () {
@ -175,7 +194,8 @@ class checkEmailPage extends StatelessWidget {
},
child: BodyLarge(
text: "Sign in",
style: context.displaySmall.copyWith(
style:
context.displaySmall.copyWith(
color: Colors.black,
fontWeight: FontsManager.bold,
),

View File

@ -12,6 +12,7 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:syncrow_app/utils/resource_manager/styles_manager.dart';
class CreateNewPasswordPage extends StatelessWidget {
const CreateNewPasswordPage({super.key,});

View File

@ -374,20 +374,25 @@ class _OtpViewState extends State<OtpView> {
return;
}
if ((state is! AuthLoading)) {
bool success = await AuthCubit.get(context)
.reSendOtp();
bool success =
await AuthCubit.get(context)
.reSendOtp(
forget:
widget.isForgetPage);
FocusScope.of(context).unfocus();
if(success){
showDialog(
context: context,
builder: (_) => SuccessDialog(
key: ValueKey('SuccessDialog'),
message: 'New OTP sent!',));
if (success) {
showDialog(
context: context,
builder: (_) =>const SuccessDialog(
key: ValueKey(
'SuccessDialog'),
message: 'New OTP sent!',
));
}
Future.delayed(Duration(seconds: 2),
() {
Navigator.of(context).pop();
});
// Future.delayed(Duration(seconds: 2),
// () {
// Navigator.of(context).pop();
// });
}
},
),

View File

@ -10,12 +10,17 @@ class ForgetPassword extends StatelessWidget {
@override
Widget build(BuildContext context) {
bool isforget = true;
return Row(
children: [
const Spacer(),
TextButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => const checkEmailPage(),));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => checkEmailPage(forget: isforget),
));
},
child: BodyMedium(
text: "Forgot Password?",

View File

@ -64,7 +64,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
emit(GetAcStatusState(acStatusModel: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
_listenToChanges();
// _listenToChanges();
}
} catch (e) {
emit(AcsFailedState(errorMessage: e.toString()));

View File

@ -29,7 +29,7 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
}
deviceStatus = CeilingSensorModel.fromJson(statusModelList);
emit(UpdateState(ceilingSensorModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;

View File

@ -40,7 +40,7 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
);
emit(UpdateState(doorSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(DoorSensorFailedState(errorMessage: e.toString()));
return;

View File

@ -80,7 +80,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
toggleDoor = deviceStatus.switch1;
emit(UpdateState(garageSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(GarageDoorFailedState(errorMessage: e.toString()));
return;

View File

@ -59,7 +59,7 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
deviceStatus = OneGangModel.fromJson(statusModelList);
emit(UpdateState(oneGangModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;

View File

@ -63,7 +63,7 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
deviceStatus = OneTouchModel.fromJson(statusModelList);
emit(UpdateState(oneTouchModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;

View File

@ -102,7 +102,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
deviceStatus = SmartDoorModel.fromJson(statusModelList);
emit(UpdateState(smartDoorModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;

View File

@ -101,7 +101,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));

View File

@ -107,7 +107,7 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
emit(UpdateState(threeTouchModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));

View File

@ -89,7 +89,7 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
deviceStatus = TwoGangModel.fromJson(statusModelList);
emit(UpdateState(twoGangModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;

View File

@ -95,7 +95,7 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
deviceStatus = TwoTouchModel.fromJson(statusModelList);
emit(UpdateState(twoTouchModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;

View File

@ -30,7 +30,7 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
}
deviceStatus = WallSensorModel.fromJson(statusModelList);
emit(UpdateState(wallSensorModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;

View File

@ -72,7 +72,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
statusModelList,
);
emit(UpdateState(whModel: deviceStatus));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(WHFailedState(errorMessage: e.toString()));
return;

View File

@ -25,9 +25,11 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
bool lowBattery = false;
bool closingReminder = false;
bool waterAlarm = false;
WaterLeakModel deviceStatus = WaterLeakModel(waterContactState: 'normal', batteryPercentage: 0);
WaterLeakModel deviceStatus =
WaterLeakModel(waterContactState: 'normal', batteryPercentage: 0);
void _fetchStatus(WaterLeakInitial event, Emitter<WaterLeakState> emit) async {
void _fetchStatus(
WaterLeakInitial event, Emitter<WaterLeakState> emit) async {
emit(WaterLeakLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(WLId);
@ -41,14 +43,15 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
emit(UpdateState(waterSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
_listenToChanges();
// _listenToChanges();
} catch (e) {
emit(WaterLeakFailedState(errorMessage: e.toString()));
return;
}
}
void _toggleLowBattery(ToggleLowBatteryEvent event, Emitter<WaterLeakState> emit) async {
void _toggleLowBattery(
ToggleLowBatteryEvent event, Emitter<WaterLeakState> emit) async {
emit(LoadingNewSate(waterSensor: deviceStatus));
try {
lowBattery = event.isLowBatteryEnabled;
@ -87,7 +90,8 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
}
}
void _toggleWaterLeakAlarm(ToggleWaterLeakAlarmEvent event, Emitter<WaterLeakState> emit) async {
void _toggleWaterLeakAlarm(
ToggleWaterLeakAlarmEvent event, Emitter<WaterLeakState> emit) async {
emit(LoadingNewSate(waterSensor: deviceStatus));
try {
waterAlarm = event.isWaterLeakAlarmEnabled;
@ -105,9 +109,11 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
}
}
DeviceReport recordGroups = DeviceReport(startTime: '0', endTime: '0', data: []);
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(ReportLogsInitial event, Emitter<WaterLeakState> emit) async {
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<WaterLeakState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
int startTime = lastMonth.millisecondsSinceEpoch;
@ -131,14 +137,16 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$WLId');
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$WLId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {

View File

@ -83,22 +83,24 @@ class _RoomPageState extends State<RoomPage> {
},
),
)
: const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Text(
'No Results Found',
style: TextStyle(
color: ColorsManager.grayColor,
fontSize: 14,
fontWeight: FontWeight.w400),
)),
],
),
),
: widget.room.devices!.isNotEmpty
? const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Text(
'No Results Found',
style: TextStyle(
color: ColorsManager.grayColor,
fontSize: 14,
fontWeight: FontWeight.w400),
)),
],
),
)
: const SizedBox(),
],
);
}

View File

@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/icons_dialog.dart';
import 'package:syncrow_app/features/scene/widgets/delete_routine_b.dart';
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart';
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
@ -18,10 +18,12 @@ class SceneAutoSettings extends StatelessWidget {
@override
Widget build(BuildContext context) {
final sceneSettings = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>? ?? {};
final sceneSettings =
ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>? ??
{};
final sceneId = sceneSettings['sceneId'] as String? ?? '';
final isAutomation =
context.read<CreateSceneBloc>().sceneType == CreateSceneEnum.deviceStatusChanges;
final isAutomation = context.read<CreateSceneBloc>().sceneType ==
CreateSceneEnum.deviceStatusChanges;
final sceneName = sceneSettings['sceneName'] as String? ?? '';
bool showInDevice = context.read<CreateSceneBloc>().showInDeviceScreen;
String selectedIcon = '';
@ -35,7 +37,8 @@ class SceneAutoSettings extends StatelessWidget {
icon: const Icon(
Icons.arrow_back_ios,
)),
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(builder: (context, state) {
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) {
if (state is AddSceneTask) {
showInDevice = state.showInDevice ?? false;
}
@ -47,7 +50,8 @@ class SceneAutoSettings extends StatelessWidget {
if (!isAutomation)
DefaultContainer(
child: Padding(
padding: const EdgeInsets.only(top: 10, left: 10, right: 10, bottom: 10),
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 10),
child: Column(
children: [
InkWell(
@ -55,20 +59,24 @@ class SceneAutoSettings extends StatelessWidget {
showDialog(
context: context,
builder: (context) {
BlocProvider.of<CreateSceneBloc>(context).add(SceneIconEvent());
BlocProvider.of<CreateSceneBloc>(context)
.add(SceneIconEvent());
return IconsDialog(
widgetList: Container(
height: MediaQuery.sizeOf(context).height * 0.4,
height:
MediaQuery.sizeOf(context).height * 0.4,
width: MediaQuery.sizeOf(context).width,
padding: const EdgeInsets.all(24),
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
child: BlocBuilder<CreateSceneBloc,
CreateSceneState>(
builder: (context, state) {
if (state is CreateSceneLoading) {
return const Center(
child: SizedBox(
height: 50,
width: 50,
child: CircularProgressIndicator()),
child:
CircularProgressIndicator()),
);
} else if (state is AddSceneTask) {
return GridView.builder(
@ -78,25 +86,35 @@ class SceneAutoSettings extends StatelessWidget {
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemCount: state.iconModels?.length ?? 0,
itemCount:
state.iconModels?.length ?? 0,
itemBuilder: (context, index) {
final iconModel = state.iconModels![index];
final iconModel =
state.iconModels![index];
return InkWell(
onTap: () {
BlocProvider.of<CreateSceneBloc>(context).add(
IconSelected(
iconId: iconModel.uuid,
confirmSelection: false));
BlocProvider.of<
CreateSceneBloc>(
context)
.add(IconSelected(
iconId:
iconModel.uuid,
confirmSelection:
false));
selectedIcon = iconModel.uuid;
},
child: ClipOval(
child: Container(
padding: const EdgeInsets.all(1),
padding:
const EdgeInsets.all(1),
decoration: BoxDecoration(
border: Border.all(
color: state.selectedIcon == iconModel.uuid
? ColorsManager.primaryColorWithOpacity
: Colors.transparent,
color: state.selectedIcon ==
iconModel.uuid
? ColorsManager
.primaryColorWithOpacity
: Colors
.transparent,
width: 2,
),
shape: BoxShape.circle,
@ -123,8 +141,10 @@ class SceneAutoSettings extends StatelessWidget {
Navigator.of(context).pop();
},
confirmTab: () {
BlocProvider.of<CreateSceneBloc>(context).add(
IconSelected(iconId: selectedIcon, confirmSelection: true));
BlocProvider.of<CreateSceneBloc>(context)
.add(IconSelected(
iconId: selectedIcon,
confirmSelection: true));
Navigator.of(context).pop();
},
title: 'Icons',
@ -171,7 +191,8 @@ class SceneAutoSettings extends StatelessWidget {
value: showInDevice,
onChanged: (value) {
BlocProvider.of<CreateSceneBloc>(context)
.add(ShowOnDeviceClicked(value: value));
.add(ShowOnDeviceClicked(
value: value));
},
applyTheme: true,
),
@ -219,7 +240,8 @@ class SceneAutoSettings extends StatelessWidget {
visible: isAutomation,
child: SceneListTile(
titleString: "Effective Period",
trailingWidget: const Icon(Icons.arrow_forward_ios_rounded),
trailingWidget:
const Icon(Icons.arrow_forward_ios_rounded),
onPressed: () {
context.customBottomSheet(
child: const EffectPeriodBottomSheetContent(),
@ -236,19 +258,29 @@ class SceneAutoSettings extends StatelessWidget {
),
),
),
Visibility(
],
),
),
const SizedBox(
height: 15,
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
child: Center(
child: Visibility(
visible: sceneName.isNotEmpty,
child: DeleteBottomSheetContent(
child: DeleteRoutineButton(
isAutomation: isAutomation,
sceneId: sceneId,
),
),
const SizedBox(
height: 16,
),
],
),
),
),
],
),
],
),
);

View File

@ -7,10 +7,10 @@ import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/delete_routine_dialog.dart';
import 'package:syncrow_app/features/scene/widgets/create_scene_save_button.dart';
import 'package:syncrow_app/features/scene/widgets/if_then_containers/if_container.dart';
import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_container.dart';
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigate_to_route.dart';
@ -117,49 +117,3 @@ class SceneTasksView extends StatelessWidget {
);
}
}
class DeleteBottomSheetContent extends StatelessWidget {
const DeleteBottomSheetContent(
{super.key, required this.sceneId, required this.isAutomation});
final String sceneId;
final bool isAutomation;
@override
Widget build(BuildContext context) {
return BlocConsumer<CreateSceneBloc, CreateSceneState>(
listener: (context, state) {
if (state is DeleteSceneSuccess) {
if (state.success) {
navigateToRoute(context, Routes.homeRoute);
BlocProvider.of<SceneBloc>(context)
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
BlocProvider.of<SceneBloc>(context).add(
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
}
}
},
builder: (context, state) {
return SceneListTile(
onPressed: () {
context.read<CreateSceneBloc>().add(DeleteSceneEvent(
sceneId: sceneId,
unitUuid: HomeCubit.getInstance().selectedSpace!.id!,
));
},
padding: const EdgeInsets.symmetric(horizontal: 8),
titleString: isAutomation
? StringsManager.deleteAutomation
: StringsManager.deleteScene,
leadingWidget: (state is DeleteSceneLoading)
? const SizedBox(
height: 24, width: 24, child: CircularProgressIndicator())
: SvgPicture.asset(
Assets.assetsDeleteIcon,
color: ColorsManager.red,
),
);
},
);
}
}

View File

@ -0,0 +1,114 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DeleteRoutineDialog extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const DeleteRoutineDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Delete Routine',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.red,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 20),
child: Column(
children: [
Center(child: const Text('Are you sure you want to ')),
Center(child: const Text('delete the routine?'))
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Confirm',
style: TextStyle(
color: ColorsManager.red,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,81 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/delete_routine_dialog.dart';
import 'package:syncrow_app/navigation/navigate_to_route.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DeleteRoutineButton extends StatelessWidget {
const DeleteRoutineButton(
{super.key, required this.sceneId, required this.isAutomation});
final String sceneId;
final bool isAutomation;
@override
Widget build(BuildContext context) {
return BlocConsumer<CreateSceneBloc, CreateSceneState>(
listener: (context, state) {
if (state is DeleteSceneSuccess) {
if (state.success) {
navigateToRoute(context, Routes.homeRoute);
BlocProvider.of<SceneBloc>(context)
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
BlocProvider.of<SceneBloc>(context).add(
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
}
}
},
builder: (context, state) {
return InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DeleteRoutineDialog(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
context.read<CreateSceneBloc>().add(DeleteSceneEvent(
sceneId: sceneId,
unitUuid:
HomeCubit.getInstance().selectedSpace!.id!,
));
Navigator.of(context).pop();
},
);
},
);
},
child: const Center(
child: Text(
'Remove Routine',
style: TextStyle(color: ColorsManager.red),
))
// : SceneListTile(
// onPressed: () {
// },
// padding: const EdgeInsets.symmetric(horizontal: 8),
// titleString: isAutomation
// ? StringsManager.deleteAutomation
// : StringsManager.deleteScene,
// leadingWidget: (state is DeleteSceneLoading)
// ? const SizedBox(
// height: 24,
// width: 24,
// child: CircularProgressIndicator())
// : SvgPicture.asset(
// Assets.assetsDeleteIcon,
// color: ColorsManager.red,
// ),
);
},
);
}
}

View File

@ -5,7 +5,8 @@ import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart';
class AuthenticationAPI {
static Future<Map<String, dynamic>> verifyPassCode({required Map<String, dynamic> body}) async {
static Future<Map<String, dynamic>> verifyPassCode(
{required Map<String, dynamic> body}) async {
final response = await HTTPService().post(
path: ApiEndpoints.verifyOtp,
body: body,
@ -14,7 +15,8 @@ class AuthenticationAPI {
return response;
}
static Future<Token> loginWithEmail({required LoginWithEmailModel model}) async {
static Future<Token> loginWithEmail(
{required LoginWithEmailModel model}) async {
final response = await HTTPService().post(
path: ApiEndpoints.login,
body: model.toJson(),
@ -32,17 +34,29 @@ class AuthenticationAPI {
return response;
}
static Future<Map<String, dynamic>> sendOtp({required Map<String, dynamic> body}) async {
static Future<Map<String, dynamic>> sendOtp(
{required Map<String, dynamic> body}) async {
final response = await HTTPService().post(
path: ApiEndpoints.sendOtp,
body: body,
showServerMessage: false,
expectedResponseModel: (json) => json['data']);
expectedResponseModel: (json) {
print(json['data']);
return json['data'];
});
return response;
}
static Future<Map<String, dynamic>> forgetPassword({required String email,required String password ,}) async {
Map<String, dynamic> params = {"email": email, "password": password,};
static Future<Map<String, dynamic>> forgetPassword({
required String otpCode,
required String email,
required String password,
}) async {
Map<String, dynamic> params = {
"email": email,
"password": password,
"otpCode": otpCode
};
final response = await HTTPService().post(
path: ApiEndpoints.forgetPassword,
body: params,

View File

@ -39,6 +39,6 @@ class StringsManager {
'Example: when an unusual activity is detected.';
static const String functions = "Functions";
static const String firstLaunch = "firstLaunch";
static const String deleteScene = 'Delete Scene';
static const String deleteScene = 'Remove Routine';
static const String deleteAutomation = 'Delete Automation';
}

View File

@ -5,7 +5,7 @@ description: This is the mobile application project, developed with Flutter for
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.5+34
version: 1.0.5+35
environment:
sdk: ">=3.0.6 <4.0.0"