mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-08-26 07:59:39 +00:00
Compare commits
5 Commits
4ac6077011
...
SP-519-del
Author | SHA1 | Date | |
---|---|---|---|
42c8b776ec | |||
04352c980d | |||
228aee97e6 | |||
24c7bcef55 | |||
2ff34a07a7 |
3
assets/icons/delete_account_icon.svg
Normal file
3
assets/icons/delete_account_icon.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 14 KiB |
@ -479,7 +479,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
// onPressed: () {},
|
||||
// ),
|
||||
],
|
||||
'Automation': [
|
||||
'Routine': [
|
||||
// IconButton(
|
||||
// icon: Image.asset(
|
||||
// Assets.assetsIconsFilter,
|
||||
@ -553,7 +553,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
static Map<String, Widget?> appBarLeading = {
|
||||
// 'Dashboard': const AppBarHomeDropdown(),
|
||||
'Devices': const AppBarHomeDropdown(),
|
||||
'Automation': const AppBarHomeDropdown(),
|
||||
'Routine': const AppBarHomeDropdown(),
|
||||
'Menu': Padding(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: Image.asset(
|
||||
@ -569,8 +569,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
// defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
||||
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
|
||||
defaultBottomNavBarItem(
|
||||
icon: Assets.assetsIconsRoutines, label: 'Automation'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsMenu, label: 'Menu'),
|
||||
];
|
||||
|
||||
@ -617,6 +616,7 @@ BottomNavigationBarItem defaultBottomNavBarItem(
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// class PermissionUtils {
|
||||
// // Check if the "VIEW" permission exists in "MANAGE_SUBSPACE"
|
||||
// static bool hasViewPermission(List<dynamic> permissions) {
|
||||
|
@ -354,7 +354,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
||||
|
||||
Future<void> selectTimeOnlinePassword(
|
||||
SelectTimeOnlinePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
||||
effectiveTimeTimeStamp ??= DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
emit(ChangeTimeState());
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: event.context,
|
||||
@ -399,13 +398,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
||||
selectedDateTime.minute,
|
||||
).millisecondsSinceEpoch ~/
|
||||
1000; // Divide by 1000 to remove milliseconds
|
||||
final currentTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
if (event.isEffective) {
|
||||
if (selectedTimestamp < currentTimestamp) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
'Effective Time cannot be later than Expiration Time.');
|
||||
return;
|
||||
}
|
||||
if (expirationTimeTimeStamp != null &&
|
||||
selectedTimestamp > expirationTimeTimeStamp!) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
|
@ -11,9 +11,6 @@ class NameTimeWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime cleaned =
|
||||
DateTime(now.year, now.month, now.day, now.hour, now.minute);
|
||||
return DefaultContainer(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
@ -62,22 +59,19 @@ class NameTimeWidget extends StatelessWidget {
|
||||
width: MediaQuery.of(context).size.width / 3.5,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
BlocProvider.of<SmartDoorBloc>(context).add(
|
||||
SelectTimeOnlinePasswordEvent(
|
||||
context: context, isEffective: true));
|
||||
|
||||
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeOnlinePasswordEvent(context: context, isEffective: true));
|
||||
},
|
||||
child: Text(
|
||||
BlocProvider.of<SmartDoorBloc>(context)
|
||||
.effectiveTime ==
|
||||
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
||||
style: TextStyle(fontSize: 14,
|
||||
color: BlocProvider.of<SmartDoorBloc>(context).effectiveTime ==
|
||||
'Select Time'
|
||||
? cleaned.toString()
|
||||
: BlocProvider.of<SmartDoorBloc>(context)
|
||||
.effectiveTime,
|
||||
style: TextStyle(fontSize: 14),
|
||||
? ColorsManager.textGray
|
||||
: null),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
],),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
@ -102,13 +96,10 @@ class NameTimeWidget extends StatelessWidget {
|
||||
context: context, isEffective: false));
|
||||
},
|
||||
child: Text(
|
||||
BlocProvider.of<SmartDoorBloc>(context)
|
||||
.expirationTime,
|
||||
BlocProvider.of<SmartDoorBloc>(context).expirationTime,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: BlocProvider.of<SmartDoorBloc>(context)
|
||||
.expirationTime ==
|
||||
'Select Time'
|
||||
color: BlocProvider.of<SmartDoorBloc>(context).expirationTime == 'Select Time'
|
||||
? ColorsManager.textGray
|
||||
: null),
|
||||
),
|
||||
|
@ -18,8 +18,7 @@ import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
final String? deviceId;
|
||||
final String? type;
|
||||
const CreateOfflineTimeLimitPasswordPage(
|
||||
{super.key, this.deviceId, this.type});
|
||||
const CreateOfflineTimeLimitPasswordPage({super.key, this.deviceId, this.type});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isRepeat = false;
|
||||
@ -29,7 +28,9 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||
listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(state.errorMessage);
|
||||
CustomSnackBar.displaySnackBar(
|
||||
state.errorMessage
|
||||
);
|
||||
}
|
||||
if (state is IsRepeatState) {
|
||||
isRepeat = state.repeat;
|
||||
@ -38,10 +39,6 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
generated = state.generated;
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime cleaned =
|
||||
DateTime(now.year, now.month, now.day, now.hour, now.minute);
|
||||
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
@ -88,9 +85,8 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
Flexible(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: smartDoorBloc
|
||||
.passwordController.text.isEmpty
|
||||
? List.generate(10, (index) {
|
||||
children: smartDoorBloc.passwordController.text.isEmpty ?
|
||||
List.generate(10, (index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 4.0,
|
||||
@ -101,39 +97,30 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
})
|
||||
: [
|
||||
}) : [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: BodyLarge(
|
||||
style: const TextStyle(
|
||||
color: ColorsManager
|
||||
.primaryColor,
|
||||
fontWeight:
|
||||
FontWeight.bold,
|
||||
color: ColorsManager.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 8.0,
|
||||
fontSize: 25,
|
||||
wordSpacing: 2),
|
||||
textAlign:
|
||||
TextAlign.center,
|
||||
text: smartDoorBloc
|
||||
.passwordController
|
||||
.text,
|
||||
textAlign: TextAlign.center,
|
||||
text: smartDoorBloc.passwordController.text,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: smartDoorBloc
|
||||
.passwordController
|
||||
.text));
|
||||
ClipboardData(text: smartDoorBloc.passwordController.text)
|
||||
);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.copy)),
|
||||
icon: const Icon(Icons.copy)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -149,13 +136,11 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.all(10.0),
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: const BodyMedium(
|
||||
text: 'Password Name',
|
||||
fontWeight: FontWeight.normal,
|
||||
@ -163,78 +148,47 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context)
|
||||
.size
|
||||
.width /
|
||||
2.6,
|
||||
width: MediaQuery.of(context).size.width / 2.6,
|
||||
child: TextFormField(
|
||||
controller: BlocProvider.of<
|
||||
SmartDoorBloc>(context)
|
||||
.passwordNameController,
|
||||
controller: BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
|
||||
decoration:
|
||||
const InputDecoration(
|
||||
hintText:
|
||||
'Enter The Name',
|
||||
hintText: 'Enter The Name',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
color: ColorsManager
|
||||
.textGray)),
|
||||
color: ColorsManager.textGray)
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
const Divider(color: ColorsManager.graysColor,),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Expanded(
|
||||
child: BodyMedium(
|
||||
text: 'Effective Time',
|
||||
fontWeight:
|
||||
FontWeight.normal,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width:
|
||||
MediaQuery.of(context)
|
||||
.size
|
||||
.width /
|
||||
3.5,
|
||||
width: MediaQuery.of(context).size.width / 3.5,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
BlocProvider.of<
|
||||
SmartDoorBloc>(
|
||||
context)
|
||||
.add(
|
||||
SelectTimeEvent(
|
||||
context:
|
||||
context,
|
||||
isEffective:
|
||||
true));
|
||||
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeEvent(context: context, isEffective: true));
|
||||
},
|
||||
child: Text(
|
||||
BlocProvider.of<SmartDoorBloc>(
|
||||
context)
|
||||
.effectiveTime ==
|
||||
'Select Time'
|
||||
? cleaned.toString()
|
||||
: BlocProvider.of<
|
||||
SmartDoorBloc>(
|
||||
context)
|
||||
.effectiveTime,
|
||||
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: BlocProvider.of<SmartDoorBloc>(context).effectiveTime ==
|
||||
'Select Time' ? ColorsManager.textGray : null),
|
||||
),
|
||||
),
|
||||
)),
|
||||
],
|
||||
)),],
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
@ -242,48 +196,30 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
child: Row(mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Expanded(
|
||||
child: BodyMedium(
|
||||
text: 'Expiration Time',
|
||||
fontWeight:
|
||||
FontWeight.normal,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context)
|
||||
.size
|
||||
.width /
|
||||
3.5,
|
||||
width: MediaQuery.of(context).size.width / 3.5,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
BlocProvider.of<
|
||||
SmartDoorBloc>(
|
||||
context)
|
||||
.add(SelectTimeEvent(
|
||||
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeEvent(
|
||||
context: context,
|
||||
isEffective:
|
||||
false));
|
||||
isEffective: false));
|
||||
},
|
||||
child: Text(
|
||||
BlocProvider.of<
|
||||
SmartDoorBloc>(
|
||||
context)
|
||||
.expirationTime,
|
||||
BlocProvider.of<SmartDoorBloc>(context).expirationTime,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: BlocProvider.of<
|
||||
SmartDoorBloc>(
|
||||
context)
|
||||
.expirationTime ==
|
||||
'Select Time'
|
||||
? ColorsManager
|
||||
.textGray
|
||||
: null),
|
||||
color: BlocProvider.of<SmartDoorBloc>(context)
|
||||
.expirationTime == 'Select Time' ? ColorsManager
|
||||
.textGray : null),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -302,8 +238,7 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
),
|
||||
const BodyMedium(
|
||||
textAlign: TextAlign.center,
|
||||
text:
|
||||
'Use the time-limited password at least once within 24 hours after the password takes effect. Otherwise, the password becomes invalid.',
|
||||
text: 'Use the time-limited password at least once within 24 hours after the password takes effect. Otherwise, the password becomes invalid.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
@ -321,12 +256,9 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||
backgroundColor: ColorsManager.primaryColor,
|
||||
onPressed: () async {
|
||||
if (generated == false) {
|
||||
smartDoorBloc.add(
|
||||
GenerateAndSavePasswordTimeLimitEvent(
|
||||
context: context));
|
||||
smartDoorBloc.add(GenerateAndSavePasswordTimeLimitEvent(context: context));
|
||||
} else {
|
||||
if (smartDoorBloc
|
||||
.passwordNameController.text.isNotEmpty) {
|
||||
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||
smartDoorBloc.add(RenamePasswordEvent());
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
|
@ -20,6 +20,7 @@ class SecurityBloc extends Bloc<SecurityEvent, SecurityState> {
|
||||
on<UpdateTimerEvent>(_onUpdateTimer);
|
||||
on<VerifyPassCodeEvent>(verifyCode);
|
||||
on<ChangePasswordEvent>(changePassword);
|
||||
on<DeleteAccountEvent>(onDeleteAccountEvent);
|
||||
}
|
||||
|
||||
void _onSetPassword(SetPassword event, Emitter<SecurityState> emit) {
|
||||
@ -180,7 +181,6 @@ class SecurityBloc extends Bloc<SecurityEvent, SecurityState> {
|
||||
ChangePasswordEvent event, Emitter<SecurityState> emit) async {
|
||||
emit(LoadingForgetState());
|
||||
try {
|
||||
|
||||
final response = await AuthenticationAPI.forgetPassword(
|
||||
email: HomeCubit.user!.email!,
|
||||
otpCode: event.otpCode,
|
||||
@ -196,4 +196,15 @@ class SecurityBloc extends Bloc<SecurityEvent, SecurityState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onDeleteAccountEvent(
|
||||
DeleteAccountEvent event, Emitter<SecurityState> emit) async {
|
||||
emit(LoadingForgetState());
|
||||
try {
|
||||
await AuthenticationAPI.deleteAccount();
|
||||
emit(ChangedPassState());
|
||||
} catch (e) {
|
||||
validate = e.toString();
|
||||
emit(AuthInitialState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,3 +29,5 @@ class ChangePasswordEvent extends SecurityEvent {
|
||||
}
|
||||
|
||||
class VerifyPassCodeEvent extends SecurityEvent {}
|
||||
|
||||
class DeleteAccountEvent extends SecurityEvent {}
|
||||
|
@ -0,0 +1,107 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_event.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_state.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class DeleteAccountPage extends StatelessWidget {
|
||||
const DeleteAccountPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocListener<SecurityBloc, SecurityState>(
|
||||
listener: (context, state) {
|
||||
if (state is ChangedPassState) {
|
||||
AuthCubit.get(context).logout();
|
||||
}
|
||||
},
|
||||
child: DefaultScaffold(
|
||||
title: 'Delete Account',
|
||||
bottomNavBar: SizedBox(
|
||||
height: 150,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Thank you for using Syncrow',
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
BlocBuilder<SecurityBloc, SecurityState>(
|
||||
builder: (context, state) {
|
||||
if (state is LoadingForgetState) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
return ElevatedButton(
|
||||
onPressed: () {
|
||||
context
|
||||
.read<SecurityBloc>()
|
||||
.add(DeleteAccountEvent());
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ColorsManager.blueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
fixedSize: Size(
|
||||
MediaQuery.sizeOf(context).width * 0.8,
|
||||
40,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Delete Account',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ColorsManager.onPrimaryColor),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 80, bottom: 30),
|
||||
child: SvgPicture.asset(Assets.deleteAccountIcon),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: BodyMedium(
|
||||
text: 'Account Verification',
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const BodyMedium(
|
||||
text:
|
||||
'if you confirm to "delete account",the account will be deleted',
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 16,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_bloc.dart';
|
||||
@ -24,13 +23,15 @@ class ChangePasswordPage extends StatelessWidget {
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// In your parent widget or navigator
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => BlocProvider(
|
||||
create: (_) => SecurityBloc(), // Provide the Bloc
|
||||
child: const VerificationCodePage(),
|
||||
create: (_) => SecurityBloc(),
|
||||
child: const VerificationCodePage(
|
||||
title: 'Change Password',
|
||||
isDeleteAccountMode: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,5 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_event.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/view/change_password_page.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/view/verification_code_page.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
@ -23,134 +27,34 @@ class SecurtyView extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
InkWell(
|
||||
SecurityListTileWidget(
|
||||
title: 'Change Password',
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => const ChangePasswordPage(),
|
||||
));
|
||||
},
|
||||
child: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Change Password',
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 15),
|
||||
height: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
)
|
||||
],
|
||||
),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 15),
|
||||
// height: 1,
|
||||
// color: ColorsManager.greyColor,
|
||||
// ),
|
||||
],
|
||||
SecurityListTileWidget(
|
||||
title: 'Delete Account',
|
||||
fontColor: ColorsManager.red,
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => BlocProvider(
|
||||
create: (_) => SecurityBloc()..add(StartTimerEvent()),
|
||||
child: VerificationCodePage(
|
||||
title: '',
|
||||
isDeleteAccountMode: true,
|
||||
),
|
||||
),
|
||||
// InkWell(
|
||||
// onTap: () {},
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// BodyMedium(
|
||||
// text: 'App Lock',
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.arrow_forward_ios,
|
||||
// color: ColorsManager.greyColor,
|
||||
// size: 15,
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 15),
|
||||
// height: 1,
|
||||
// color: ColorsManager.greyColor,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// InkWell(
|
||||
// onTap: () {},
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// BodyMedium(
|
||||
// text: 'User Code',
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.arrow_forward_ios,
|
||||
// color: ColorsManager.greyColor,
|
||||
// size: 15,
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 15),
|
||||
// height: 1,
|
||||
// color: ColorsManager.greyColor,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// InkWell(
|
||||
// onTap: () {},
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// BodyMedium(
|
||||
// text: 'Delete Account',
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.arrow_forward_ios,
|
||||
// color: ColorsManager.greyColor,
|
||||
// size: 15,
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 15),
|
||||
// height: 1,
|
||||
// color: ColorsManager.greyColor,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// InkWell(
|
||||
// onTap: () {},
|
||||
// child: const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// BodyMedium(
|
||||
// text: 'Device Update',
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.arrow_forward_ios,
|
||||
// color: ColorsManager.greyColor,
|
||||
// size: 15,
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -159,3 +63,42 @@ class SecurtyView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SecurityListTileWidget extends StatelessWidget {
|
||||
final String title;
|
||||
final void Function() onTap;
|
||||
final Color? fontColor;
|
||||
const SecurityListTileWidget({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.onTap,
|
||||
this.fontColor,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: title,
|
||||
fontColor: fontColor,
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_event.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_state.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/delete_account/delete_account_page.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/securty/view/set_password_page.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
@ -11,7 +12,13 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||
|
||||
class VerificationCodePage extends StatelessWidget {
|
||||
const VerificationCodePage({super.key});
|
||||
final String title;
|
||||
final bool isDeleteAccountMode;
|
||||
const VerificationCodePage({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.isDeleteAccountMode,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -20,19 +27,29 @@ class VerificationCodePage extends StatelessWidget {
|
||||
create: (context) => SecurityBloc()..add(StartTimerEvent()),
|
||||
child: BlocConsumer<SecurityBloc, SecurityState>(
|
||||
listener: (context, state) {
|
||||
final securityBloc = context.read<SecurityBloc>();
|
||||
if (state is SuccessForgetState) {
|
||||
if (isDeleteAccountMode) {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => BlocProvider.value(
|
||||
value: securityBloc,
|
||||
child: DeleteAccountPage(),
|
||||
),
|
||||
));
|
||||
} else {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => SetPasswordPage(
|
||||
otpCode: otp,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final _bloc = BlocProvider.of<SecurityBloc>(context);
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Change Password',
|
||||
title: title,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 55),
|
||||
@ -86,8 +103,8 @@ class VerificationCodePage extends StatelessWidget {
|
||||
selectedFillColor: Colors.white70,
|
||||
activeFillColor: Colors.white,
|
||||
errorBorderColor: Colors.white,
|
||||
fieldHeight: 55.0,
|
||||
fieldWidth: 55.0,
|
||||
fieldHeight: 45.0,
|
||||
fieldWidth: 45.0,
|
||||
fieldOuterPadding: const EdgeInsets.only(right: 8),
|
||||
borderRadius: BorderRadius.circular(17),
|
||||
borderWidth: 1,
|
||||
@ -109,27 +126,35 @@ class VerificationCodePage extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap:
|
||||
state is TimerState && !state.isButtonEnabled && state.remainingTime != 1
|
||||
onTap: state is TimerState &&
|
||||
!state.isButtonEnabled &&
|
||||
state.remainingTime != 1
|
||||
? null
|
||||
: () {
|
||||
_bloc.add(StartTimerEvent());
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(right: 20, left: 20, top: 15, bottom: 15),
|
||||
padding: const EdgeInsets.only(
|
||||
right: 20, left: 20, top: 15, bottom: 15),
|
||||
decoration: BoxDecoration(
|
||||
color: state is TimerState && !state.isButtonEnabled
|
||||
? ColorsManager.blueButton
|
||||
: ColorsManager.blueColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(20))),
|
||||
child: Center(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "${_bloc.formattedTime(state.remainingTime)} " : "Resend"}',
|
||||
state is TimerState &&
|
||||
!state.isButtonEnabled &&
|
||||
state.remainingTime != 1
|
||||
? "${_bloc.formattedTime(state.remainingTime)} "
|
||||
: "Resend",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: state is TimerState && !state.isButtonEnabled
|
||||
color: state is TimerState &&
|
||||
!state.isButtonEnabled
|
||||
? Colors.white
|
||||
: ColorsManager.onPrimaryColor,
|
||||
),
|
||||
@ -142,18 +167,24 @@ class VerificationCodePage extends StatelessWidget {
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
context.read<SecurityBloc>().add(VerifyPassCodeEvent());
|
||||
context
|
||||
.read<SecurityBloc>()
|
||||
.add(VerifyPassCodeEvent());
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(right: 20, left: 20, top: 15, bottom: 15),
|
||||
padding: const EdgeInsets.only(
|
||||
right: 20, left: 20, top: 15, bottom: 15),
|
||||
decoration: const BoxDecoration(
|
||||
color: ColorsManager.blueColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(20))),
|
||||
child: const Center(
|
||||
child: Text(
|
||||
"Verify",
|
||||
style: TextStyle(
|
||||
fontSize: 16, color: Colors.white, fontWeight: FontWeight.w700),
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -27,15 +27,12 @@ class RoutinesView extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
final selectedSpace = HomeCubit.getInstance().selectedSpace;
|
||||
if (state is DeleteSceneSuccess) {
|
||||
if (state.success)
|
||||
_loadScenesAndAutomations(context, selectedSpace);
|
||||
if (state.success) _loadScenesAndAutomations(context, selectedSpace);
|
||||
}
|
||||
if (state is CreateSceneWithTasks) {
|
||||
if (state.success) {
|
||||
_loadScenesAndAutomations(context, selectedSpace);
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
|
||||
}
|
||||
}
|
||||
return BlocListener<SceneBloc, SceneState>(
|
||||
@ -75,10 +72,11 @@ class RoutinesView extends StatelessWidget {
|
||||
data: Theme.of(context).copyWith(
|
||||
dividerColor: Colors.transparent,
|
||||
),
|
||||
child: Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
RoutinesExpansionTile(
|
||||
title: 'Tap to run automations',
|
||||
title: 'Tap to run routines',
|
||||
emptyRoutinesMessage:
|
||||
'No scenes have been added yet',
|
||||
routines: state.scenes,
|
||||
@ -98,6 +96,7 @@ class RoutinesView extends StatelessWidget {
|
||||
const SizedBox(height: 15),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
@ -112,8 +111,7 @@ class RoutinesView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void _loadScenesAndAutomations(
|
||||
BuildContext context, SpaceModel? selectedSpace) {
|
||||
void _loadScenesAndAutomations(BuildContext context, SpaceModel? selectedSpace) {
|
||||
context.read<SceneBloc>()
|
||||
..add(LoadScenes(selectedSpace!.id, selectedSpace, showInDevice: false))
|
||||
..add(LoadAutomation(selectedSpace.id, selectedSpace.community.uuid));
|
||||
|
@ -100,7 +100,7 @@ class SceneView extends StatelessWidget {
|
||||
initiallyExpanded: true,
|
||||
iconColor: ColorsManager.grayColor,
|
||||
title: const BodyMedium(
|
||||
text: 'Tap to run automations',
|
||||
text: 'Tap to run routines',
|
||||
),
|
||||
children: [
|
||||
if (scenes.isNotEmpty)
|
||||
|
@ -23,7 +23,7 @@ class DeleteRoutineDialog extends StatelessWidget {
|
||||
height: 10,
|
||||
),
|
||||
const BodyLarge(
|
||||
text: 'Delete Automation',
|
||||
text: 'Delete Routine',
|
||||
fontWeight: FontWeight.w700,
|
||||
fontColor: ColorsManager.red,
|
||||
fontSize: 16,
|
||||
@ -39,7 +39,7 @@ class DeleteRoutineDialog extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
Center(child: const Text('Are you sure you want to ')),
|
||||
Center(child: const Text('delete the automation?'))
|
||||
Center(child: const Text('delete the routine?'))
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -52,7 +52,7 @@ class DeleteRoutineButton extends StatelessWidget {
|
||||
},
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'Remove Automation',
|
||||
'Remove Routine',
|
||||
style: TextStyle(color: ColorsManager.red),
|
||||
))
|
||||
// : SceneListTile(
|
||||
|
@ -9,7 +9,7 @@ class EmptyDevicesWidget extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 48),
|
||||
child: Text(
|
||||
"No automations.\nEnable 'Show on Home Screen' to add automations",
|
||||
"No routines.\nEnable 'Show on Home Screen' to add routines",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
|
@ -23,7 +23,7 @@ class EmptyRoutinesWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
BodyMedium(
|
||||
text: 'No automations yet',
|
||||
text: 'No Routines yet',
|
||||
fontColor: ColorsManager.textGray,
|
||||
),
|
||||
],
|
||||
|
@ -1128,7 +1128,7 @@ class Assets {
|
||||
static const String editNameSetting = "assets/icons/edit_name_setting.svg";
|
||||
|
||||
static const String verificationIcon = "assets/icons/verification_icon.svg";
|
||||
|
||||
static const String deleteAccountIcon='assets/icons/delete_account_icon.svg';
|
||||
static const String passwordUnvisibility =
|
||||
"assets/icons/password_unvisibility.svg";
|
||||
static const String passwordVisibility =
|
||||
|
@ -195,6 +195,7 @@ abstract class ApiEndpoints {
|
||||
static const String sendPicture = '/user/profile-picture/{userUuid}';
|
||||
static const String getRegion = '/region';
|
||||
static const String getTimezone = '/timezone';
|
||||
static const String deleteProfile = '/user';
|
||||
|
||||
//multiple-time offline
|
||||
static const String addMultipleTimeTemporaryPassword =
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:syncrow_app/features/auth/model/login_with_email_model.dart';
|
||||
import 'package:syncrow_app/features/auth/model/signup_model.dart';
|
||||
import 'package:syncrow_app/features/auth/model/token.dart';
|
||||
@ -83,4 +84,18 @@ class AuthenticationAPI {
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<void> deleteAccount() async {
|
||||
try {
|
||||
await HTTPService().delete(
|
||||
path: ApiEndpoints.deleteProfile,
|
||||
expectedResponseModel: (p0) {},
|
||||
);
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage =
|
||||
errorData['error']['message'] ?? 'something went wrong';
|
||||
throw Exception(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ class StringsManager {
|
||||
|
||||
static const String dashboard = 'Dashboard';
|
||||
static const String devices = 'Devices';
|
||||
static const String routine = 'Automation';
|
||||
static const String tapToRunRoutine = 'Tap to run automation';
|
||||
static const String routine = 'Routines';
|
||||
static const String tapToRunRoutine = 'Tap to run routine';
|
||||
static const String wizard = 'Wizard';
|
||||
static const String active = 'Active';
|
||||
static const String current = 'Current';
|
||||
@ -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 = 'Remove Automation';
|
||||
static const String deleteScene = 'Remove Routine';
|
||||
static const String deleteAutomation = 'Delete Automation';
|
||||
}
|
||||
|
Reference in New Issue
Block a user