Skip to content

Commit

Permalink
Delete account view with basic bloc (#296)
Browse files Browse the repository at this point in the history
* Delete account view with basic bloc

* Delete account bloc logic

* Fix delete account logic

* Extract delete account button to separate widget

* Extract delete account button to separate widget

* Fix const login route

* Regenerated pod lockfile

* Remove empty app router file

* Fix lint

* Update copy on delete page

* Regenerated pod lockfile

---------

Co-authored-by: kackogut <[email protected]>
Co-authored-by: James Elgar <[email protected]>
Co-authored-by: JElgar <[email protected]>
  • Loading branch information
4 people authored Aug 26, 2024
1 parent 8ded766 commit f8896d2
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ TLDR guide:

1. Install flutter (and get a device setup)
2. Clone the repo
3. Run it - `flutter run`
3. Run build runner - `flutter pub run build_runner build --delete-conflicting-outputs`
4. Run it - `flutter run`

### Where to start? :information_desk_person:

Expand Down
1 change: 1 addition & 0 deletions lib/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class AppRouter extends RootStackRouter {
page: PartnerInfoRoute.page,
),
AutoRoute(path: '/faqs', page: FaqRoute.page),
AutoRoute(path: '/delete_account', page: DeleteAccountRoute.page),
];

Future<void> launchLink(Uri url, {bool isExternal = false}) async {
Expand Down
4 changes: 4 additions & 0 deletions lib/services/user_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ class UserService {
_currentUser = UserProfile.fromApiModel(response.data!);
_currentUserStreamController.add(_currentUser);
}

Future<void> deleteUser() async {
await _causeServiceClient.getMeApi().meDeleteDestroy();
}
}
41 changes: 41 additions & 0 deletions lib/ui/views/delete_account/delete_account_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:nowu/router.gr.dart';
import 'package:nowu/ui/views/delete_account/delete_account_state.dart';

import '../../../services/auth.dart';
import '../../../services/user_service.dart';

const String deleteUserConfirmationText = 'delete me';

class DeleteAccountBloc extends Cubit<DeleteAccountState> {
AuthenticationService _authenticationService;
StackRouter _appRouter;
UserService _userService;

DeleteAccountBloc({
required AuthenticationService authenticationService,
required StackRouter appRouter,
required UserService userService,
}) : _authenticationService = authenticationService,
_appRouter = appRouter,
_userService = userService,
super(const DeleteAccountState());

void updateInputName(String name) {
emit(
state.copyWith(
name: name,
isNameValid: name == deleteUserConfirmationText,
),
);
}

Future<void> deleteAccount() async {
if (!state.isNameValid) return;

await _userService.deleteUser();
await _authenticationService.logout();
_appRouter.pushAndPopUntil(LoginRoute(), predicate: (r) => false);
}
}
11 changes: 11 additions & 0 deletions lib/ui/views/delete_account/delete_account_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'delete_account_state.freezed.dart';

@freezed
class DeleteAccountState with _$DeleteAccountState {
const factory DeleteAccountState({
@Default('') String name,
@Default(false) bool isNameValid,
}) = _DeleteAccountState;
}
90 changes: 90 additions & 0 deletions lib/ui/views/delete_account/delete_account_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../locator.dart';
import '../../../services/auth.dart';
import '../../../services/user_service.dart';
import 'delete_account_bloc.dart';
import 'delete_account_state.dart';

@RoutePage()
class DeleteAccountView extends StatelessWidget {
@override
Widget build(BuildContext context) {
DeleteAccountBloc bloc = DeleteAccountBloc(
authenticationService: locator<AuthenticationService>(),
appRouter: AutoRouter.of(context),
userService: locator<UserService>(),
);

return BlocProvider<DeleteAccountBloc>(
create: (_) => bloc,
child: Scaffold(
appBar: AppBar(
title: const Text('Delete Account'),
),
body: Container(
color: Colors.white,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: Theme.of(context).textTheme.titleMedium,
children: [
const TextSpan(
text:
'Are you sure you want to delete your account? ',
),
const TextSpan(
text: 'This action cannot be undone.',
style: TextStyle(fontWeight: FontWeight.w700),
),
],
),
),
const SizedBox(height: 8),
Text(
'To confirm, please type "$deleteUserConfirmationText" below.',
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
TextField(
onChanged: bloc.updateInputName,
decoration: const InputDecoration(
hintText: deleteUserConfirmationText,
),
),
const SizedBox(height: 8),
DeleteAccountButton(),
],
),
),
),
),
),
);
}
}

class DeleteAccountButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<DeleteAccountBloc, DeleteAccountState>(
builder: (context, state) {
return ElevatedButton(
onPressed: state.isNameValid
? context.read<DeleteAccountBloc>().deleteAccount
: null,
child: const Text('Delete Account'),
);
},
);
}
}
8 changes: 7 additions & 1 deletion lib/ui/views/more/more_view.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Expand All @@ -7,7 +8,6 @@ import 'package:nowu/assets/constants.dart';
import 'package:nowu/assets/icons/customIcons.dart';
import 'package:nowu/router.dart';
import 'package:nowu/router.gr.dart';
import 'package:auto_route/auto_route.dart';
import 'package:nowu/ui/views/authentication/bloc/authentication_bloc.dart';
import 'package:nowu/ui/views/authentication/bloc/authentication_state.dart';

Expand Down Expand Up @@ -119,6 +119,12 @@ List<MenuItemData> getMenuItems(
action: LinkMenuItemAction(PRIVACY_POLICY_URI, isExternal: true),
),
const SectionHeadingMenuItem(title: 'User'),
if (authState is AuthenticationStateAuthenticated)
const ActionMenuItem(
title: 'Delete Account',
icon: FontAwesomeIcons.userMinus,
action: RouteMenuItemAction(DeleteAccountRoute()),
),
if (authState is AuthenticationStateAuthenticated)
ActionMenuItem(
title: 'Log out',
Expand Down
1 change: 1 addition & 0 deletions openapi/openapi-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ paths:
- tr
- tt
- udm
- ug
- uk
- ur
- uz
Expand Down

0 comments on commit f8896d2

Please sign in to comment.