v1.1.27 deactivate customer

This commit is contained in:
Tibor Bossanyi (Freelancer) 2022-11-26 16:46:06 +01:00
parent dbdcf2f239
commit 98901f2770
10 changed files with 116 additions and 9 deletions

View File

@ -6,6 +6,8 @@ import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../../service/customer_service.dart';
part 'account_event.dart'; part 'account_event.dart';
part 'account_state.dart'; part 'account_state.dart';
@ -21,6 +23,7 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
on<AccountLogout>(_onLogout); on<AccountLogout>(_onLogout);
on<AccountGetTrainees>(_onGetTrainees); on<AccountGetTrainees>(_onGetTrainees);
on<AccountSelectTrainee>(_onSelectTrainees); on<AccountSelectTrainee>(_onSelectTrainees);
on<DeleteAccount>(_onDeleteAccount);
} }
void _load() { void _load() {
@ -56,6 +59,24 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
emit(AccountReady()); emit(AccountReady());
} }
void _onDeleteAccount(DeleteAccount event, Emitter<AccountState> emit) async {
emit(AccountLoading());
await Cache().logout();
customerRepository.customer = event.customer;
customerRepository.emptyTrainees();
loggedIn = false;
//delete local store
int customerId = customerRepository.customer!.customerId!;
await Cache().deleteCustomerId(customerId);
customerRepository.customer = null;
// deactivate user
await CustomerApi().deactivateCustomer(customerId);
emit(AccountReady());
}
void _onGetTrainees(AccountGetTrainees event, Emitter<AccountState> emit) async { void _onGetTrainees(AccountGetTrainees event, Emitter<AccountState> emit) async {
emit(AccountLoading()); emit(AccountLoading());
await customerRepository.getTrainees(); await customerRepository.getTrainees();

View File

@ -20,6 +20,14 @@ class AccountLogin extends AccountEvent {
const AccountLogin(); const AccountLogin();
} }
class DeleteAccount extends AccountEvent {
final Customer customer;
const DeleteAccount ({required this.customer});
@override
List<Object> get props => [customer];
}
class AccountLogInFinished extends AccountEvent { class AccountLogInFinished extends AccountEvent {
final Customer customer; final Customer customer;

View File

@ -95,6 +95,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
Cache().setLoginType(LoginType.email); Cache().setLoginType(LoginType.email);
emit(LoginSuccess()); emit(LoginSuccess());
} on Exception catch (e) { } on Exception catch (e) {
print("Login error: $e" );
emit(LoginError(message: e.toString())); emit(LoginError(message: e.toString()));
} }
} }

View File

@ -212,6 +212,12 @@ class Cache with Logging {
return this.authToken; return this.authToken;
} }
Future<void> deleteCustomerId(int customerId) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.remove(Cache.customerIdKey);
}
Future<void> saveActiveExercisePlan(ExercisePlan exercisePlan, List<ExercisePlanDetail> exercisePlanDetails) async { Future<void> saveActiveExercisePlan(ExercisePlan exercisePlan, List<ExercisePlanDetail> exercisePlanDetails) async {
this.activeExercisePlan = exercisePlan; this.activeExercisePlan = exercisePlan;
this.activeExercisePlanDetails = exercisePlanDetails; this.activeExercisePlanDetails = exercisePlanDetails;

View File

@ -204,7 +204,7 @@ class UserRepository with Logging {
Future<void> getUser() async { Future<void> getUser() async {
final User modelUser = this.user; final User modelUser = this.user;
String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password); String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password);
try {
if (rc == FirebaseApi.SIGN_IN_OK) { if (rc == FirebaseApi.SIGN_IN_OK) {
await CustomerApi().getUserByEmail(modelUser.email!); await CustomerApi().getUserByEmail(modelUser.email!);
await Cache().afterFirebaseLogin(); await Cache().afterFirebaseLogin();
@ -212,6 +212,9 @@ class UserRepository with Logging {
log("Exception: user not found or password is wrong"); log("Exception: user not found or password is wrong");
throw Exception("Customer does not exist or the password is wrong"); throw Exception("Customer does not exist or the password is wrong");
} }
} on NotFoundException catch (_) {
throw Exception("Customer does not exist or the password is wrong");
}
} }
Future<void> resetPassword() async { Future<void> resetPassword() async {

View File

@ -92,6 +92,8 @@ class APIClient with Common, Logging {
} else { } else {
throw Exception("Network Error, please try again later"); throw Exception("Network Error, please try again later");
} }
} on NotFoundException catch(e) {
throw NotFoundException(message: "Not Found");
} on Exception catch (e) { } on Exception catch (e) {
print("Post Exception: $e"); print("Post Exception: $e");
await Sentry.captureException(e); await Sentry.captureException(e);
@ -128,6 +130,8 @@ class APIClient with Common, Logging {
} else { } else {
throw Exception("Network Error, please try again later"); throw Exception("Network Error, please try again later");
} }
} on NotFoundException catch(e) {
throw NotFoundException(message: "Not Found");
} on Exception catch (e) { } on Exception catch (e) {
print("Post Exception: $e"); print("Post Exception: $e");
await Sentry.captureException(e); await Sentry.captureException(e);

View File

@ -32,6 +32,11 @@ class CustomerApi with Logging {
await _client.post("customers/update_firebase_uid/" + customerId.toString(), uid); await _client.post("customers/update_firebase_uid/" + customerId.toString(), uid);
} }
Future<void> deactivateCustomer(int customerId) async {
log(" ===== deactivate : $customerId");
await _client.post("customers/deactivate/$customerId", "");
}
Future<void> addCustomer(Customer customer) async { Future<void> addCustomer(Customer customer) async {
customer.dateAdd = DateTime.now(); customer.dateAdd = DateTime.now();
customer.dateChange = DateTime.now(); customer.dateChange = DateTime.now();

View File

@ -53,6 +53,7 @@ enum TrackingEvent {
tutorial_activate, tutorial_activate,
terms_of_use, terms_of_use,
data_privacy, data_privacy,
delete_account,
faq, faq,
training_plan_open, training_plan_open,
training_plan_start, training_plan_start,
@ -60,7 +61,7 @@ enum TrackingEvent {
training_plan_finished, training_plan_finished,
training_plan_custom, training_plan_custom,
trial, trial,
feedback_email feedback_email,
} }
T enumFromString<T>(Iterable<T> values, String value) { T enumFromString<T>(Iterable<T> values, String value) {

View File

@ -14,6 +14,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart'; import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
import '../util/enums.dart';
import '../util/track.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class AccountPage extends StatelessWidget with Trans { class AccountPage extends StatelessWidget with Trans {
// ignore: close_sinks // ignore: close_sinks
@ -152,6 +155,9 @@ class AccountPage extends StatelessWidget with Trans {
), ),
devices(context, accountBloc), devices(context, accountBloc),
loginOut(context, accountBloc), loginOut(context, accountBloc),
Divider(),
Divider(),
deleteAccount(accountBloc),
//messaging(), //messaging(),
//getMyTrainees(context, accountBloc), //getMyTrainees(context, accountBloc),
]); ]);
@ -241,6 +247,29 @@ class AccountPage extends StatelessWidget with Trans {
return element; return element;
} }
ListTile deleteAccount(AccountBloc accountBloc) {
return ListTile(
leading: Icon(Icons.delete_forever),
title: TextButton(
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(t("Delete Account"), style: TextStyle(color: Color.fromARGB(255, 202, 10, 10))),
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white70,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
if (accountBloc.loggedIn)
{
deleteAccountConfirmationDialog(accountBloc),
}
},
),
);
}
Widget getMyTrainees(BuildContext context, AccountBloc accountBloc) { Widget getMyTrainees(BuildContext context, AccountBloc accountBloc) {
if (accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer!.trainer == 0) { if (accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer!.trainer == 0) {
return ListTile( return ListTile(
@ -303,6 +332,35 @@ class AccountPage extends StatelessWidget with Trans {
)); ));
} }
void deleteAccountConfirmationDialog(AccountBloc accountBloc) {
showCupertinoDialog(
useRootNavigator: true,
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text(t("Are you sure to delete your account?")),
content: Column(children: [
Divider(),
Text(t("Your training data, historical data, goals, 1RMs will be completly lost!")),
]),
actions: [
TextButton(
child: Text(t("No")),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: Text(t("Yes")),
onPressed: () => {
if (accountBloc.customerRepository.customer != null && accountBloc.customerRepository.customer!.customerId != null) {
Track().track(TrackingEvent.delete_account),
accountBloc.add(DeleteAccount(customer: accountBloc.customerRepository.customer!)),
},
Navigator.pop(context),
},
)
],
));
}
void confirmationDialog(AccountBloc accountBloc) { void confirmationDialog(AccountBloc accountBloc) {
showCupertinoDialog( showCupertinoDialog(
useRootNavigator: true, useRootNavigator: true,

View File

@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.1.27+115 version: 1.1.27+116
environment: environment:
sdk: ">=2.18.4 <3.0.0" sdk: ">=2.18.4 <3.0.0"