Skip to content

Commit

Permalink
회원 탈퇴 로직 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
AlphanoJack committed Aug 16, 2024
1 parent 1cfdcc4 commit b15e678
Show file tree
Hide file tree
Showing 19 changed files with 395 additions and 42 deletions.
20 changes: 20 additions & 0 deletions lib/core/widget/EmailTextWidget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:blueberry_flutter_template/feature/user/provider/GetUserEmailProviderProvider.dart';
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';

class EmailTextWidget extends ConsumerWidget {
const EmailTextWidget({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final userEmail = ref.watch(getUserEmailProvider);
return userEmail.when(
data: (email) => Text(
email,
),
loading: () => const Text(''),
error: (e, s) => const Text(AppStrings.emailTextWidgetError),
);
}
}
20 changes: 20 additions & 0 deletions lib/core/widget/UserSignUpDataTextWidget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:blueberry_flutter_template/feature/user/provider/GetUserSignUpDataProvider.dart';
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';

class UserSignUpTextWidget extends ConsumerWidget {
const UserSignUpTextWidget({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final userSignUpDate = ref.watch(getUserSignUpProvider);
return userSignUpDate.when(
data: (date) => Text(
date,
),
loading: () => const Text(''),
error: (e, s) => const Text(AppStrings.dateTextWidgetError),
);
}
}
11 changes: 6 additions & 5 deletions lib/feature/login/LoginScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ Widget _buildLogin(BuildContext context, WidgetRef ref) {
if (value == null || value.isEmpty) {
return AppStrings.errorMessage_emptyPassword;
}
if (!RegExp(r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$')
.hasMatch(value)) {
return AppStrings.errorMessage_invalidPassword;
}
// if (!RegExp(r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@!#$%^&*()_+\-=\[\]{};:"\\|,.<>/?])[\w@!#$%^&*()_+\-=\[\]{};:"\\|,.<>/?]*$')
// .hasMatch(value)) {
// return AppStrings.errorMessage_invalidPassword;
// }
// 회원가입 시 비밀번호 정규식이 걸려 있기 때문에 여기서 걸 필요 없는거 같아서 우선 주석처리 해둘께요. 추후 삭제 하거나 사용 할지 결정 해야함.
return null;
},
),
Expand Down Expand Up @@ -129,7 +130,7 @@ Widget _buildLogin(BuildContext context, WidgetRef ref) {
try {
await ref
.read(firebaseAuthServiceProvider)
.signInWithEmailPassword(email, password);
.signInWithEmailPassword(context, email, password);
} catch (e) {
showDialog(
context: context,
Expand Down
33 changes: 3 additions & 30 deletions lib/feature/mypage/MyPageScreen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:io';
import 'package:blueberry_flutter_template/feature/mypage/provider/ProfileImageProvider.dart';
import 'package:blueberry_flutter_template/services/FirebaseService.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:easy_engine/easy_engine.dart';
import 'package:firebase_auth/firebase_auth.dart';
Expand Down Expand Up @@ -112,7 +113,7 @@ class MyPageScreen extends ConsumerWidget {
),
const CustomDividerWidget(),
GestureDetector(
onTap: () {},
onTap: () {},
child: const ListTile(
leading: Icon(Icons.chat_bubble_outline),
title: Text(
Expand Down Expand Up @@ -156,35 +157,7 @@ class MyPageScreen extends ConsumerWidget {
//Logout button
GestureDetector(
onTap: () async {
try {
final re = await engine.deleteAccount();
debugPrint(re.toString());
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('회원탈퇴가 완료되었습니다.'),
),
);
}
ref.read(firebaseAuthServiceProvider).signOut();
} on FirebaseFunctionsException catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${e.code}/${e.message}'),
),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Error: $e'), // e.code: internal, e.message: INTERNAL
),
);
}
}
FirebaseService().requestAccountDeletion(context, ref);
},
child: const ListTile(
leading: Icon(Icons.person_off),
Expand Down
19 changes: 19 additions & 0 deletions lib/feature/user/provider/GetUserDeletionDateProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:blueberry_flutter_template/utils/Formatter.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final getUserDeletionDateProvider = StreamProvider<String>((ref) {
final firestore = FirebaseFirestore.instance;
final userId = FirebaseAuth.instance.currentUser!.uid;

return firestore.collection('users').doc(userId).snapshots().map((snapshot) {
final deletionRequestedAt = snapshot.get('scheduledDeletionTime');
if (deletionRequestedAt is Timestamp) {
return formatTimestamp(deletionRequestedAt);
} else {
return AppStrings.dateTextWidgetError;
}
});
});
20 changes: 20 additions & 0 deletions lib/feature/user/provider/GetUserDeletionRequestDateProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:blueberry_flutter_template/utils/Formatter.dart';
import 'package:blueberry_flutter_template/utils/Talker.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final getUserDeletionRequestDateProvider = StreamProvider<String>((ref) {
final firestore = FirebaseFirestore.instance;
final userId = FirebaseAuth.instance.currentUser!.uid;

return firestore.collection('users').doc(userId).snapshots().map((snapshot) {
final deletionRequestedAt = snapshot.get('deletionRequestedAt');
if (deletionRequestedAt is Timestamp) {
return formatTimestamp(deletionRequestedAt);
} else {
return AppStrings.dateTextWidgetError;
}
});
});
12 changes: 12 additions & 0 deletions lib/feature/user/provider/GetUserEmailProviderProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final getUserEmailProvider = StreamProvider<String>((ref) {
final firestore = FirebaseFirestore.instance;
final userId = FirebaseAuth.instance.currentUser!.uid;

return firestore.collection('users').doc(userId).snapshots().map((snapshot) {
return snapshot['email'] as String;
});
});
19 changes: 19 additions & 0 deletions lib/feature/user/provider/GetUserSignUpDataProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:blueberry_flutter_template/utils/Formatter.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final getUserSignUpProvider = StreamProvider<String>((ref) {
final firestore = FirebaseFirestore.instance;
final userId = FirebaseAuth.instance.currentUser!.uid;

return firestore.collection('users').doc(userId).snapshots().map((snapshot) {
final createdAt = snapshot.get('createdAt');
if (createdAt is Timestamp) {
return formatTimestamp(createdAt);
} else {
return AppStrings.dateTextWidgetError;
}
});
});
12 changes: 12 additions & 0 deletions lib/feature/user/restore/RestoreDeletedUserScreen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:blueberry_flutter_template/feature/user/restore/widget/DeletedUserDataWidget.dart';
import 'package:flutter/material.dart';

class RestoreDeletedUserScreen extends StatelessWidget {
static const String name = '/RestoreDeletedUserScreen';
const RestoreDeletedUserScreen({super.key});

@override
Widget build(BuildContext context) {
return const DeletedUserDataWidget();
}
}
28 changes: 28 additions & 0 deletions lib/feature/user/restore/widget/DeletedUserDataWidget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:blueberry_flutter_template/feature/user/restore/widget/DeletionRequestUserInfoTextWidget.dart';
import 'package:blueberry_flutter_template/feature/user/restore/widget/RestoreDeletionUserBottomButtonWidget.dart';
import 'package:flutter/material.dart';


class DeletedUserDataWidget extends StatelessWidget {
const DeletedUserDataWidget({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
// ignore the back button
),
body: const Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: DeletionRequestUserInfoListWidget()
),
RestoreDeletionUserBottomButtonWidget(),
],
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:blueberry_flutter_template/core/widget/EmailTextWidget.dart';
import 'package:blueberry_flutter_template/core/widget/UserSignUpDataTextWidget.dart';
import 'package:blueberry_flutter_template/feature/user/restore/widget/UserDeletionDateTextWidget.dart';
import 'package:blueberry_flutter_template/feature/user/restore/widget/UserDeletionRequestDateTextWidget.dart';
import 'package:flutter/material.dart';

class DeletionRequestUserInfoListWidget extends StatelessWidget {
const DeletionRequestUserInfoListWidget({super.key});

@override
Widget build(BuildContext context) {
final List<Map<String, Widget>> userInfoItems = [
{'아이디: ': const EmailTextWidget()},
{'최초 계정 생성 일: ': const UserSignUpTextWidget()},
{'탈퇴 요청 일: ': const UserDeletionRequestDateTextWidget()},
{'탈퇴 예정 일: ': const UserDeletionDateTextWidget()},
];

return Padding(
padding: const EdgeInsets.all(16.0),
child: ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: userInfoItems.length,
itemBuilder: (context, index) {
final item = userInfoItems[index];
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Row(
children: [
Text(item.keys.first),
item.values.first,
],
),
);
},
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:blueberry_flutter_template/services/FirebaseAuthServiceProvider.dart';
import 'package:blueberry_flutter_template/services/FirebaseService.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class RestoreDeletionUserBottomButtonWidget extends ConsumerWidget {
const RestoreDeletionUserBottomButtonWidget({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
child: RestoreBtn(),
),
const SizedBox(width: 16),
Expanded(
child: cancelBtn(ref),
),
],
),
);
}

ElevatedButton cancelBtn(WidgetRef ref) {
return ElevatedButton(
onPressed: () async {
ref.read(firebaseAuthServiceProvider).signOut();
},
child: const Text('나가기'),
);
}

ElevatedButton RestoreBtn() {
return ElevatedButton(
onPressed: () async {
await FirebaseService().cancelAccountDeletion();
},
child: const Text('복원 하기'),
);
}
}
20 changes: 20 additions & 0 deletions lib/feature/user/restore/widget/UserDeletionDateTextWidget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:blueberry_flutter_template/feature/user/provider/GetUserDeletionDateProvider.dart';
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';

class UserDeletionDateTextWidget extends ConsumerWidget {
const UserDeletionDateTextWidget({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final userDeletionDate = ref.watch(getUserDeletionDateProvider);
return userDeletionDate.when(
data: (date) => Text(
date,
),
loading: () => const Text(''),
error: (e, s) => const Text(AppStrings.dateTextWidgetError),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:blueberry_flutter_template/feature/user/provider/GetUserDeletionRequestDateProvider.dart';
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';

class UserDeletionRequestDateTextWidget extends ConsumerWidget {
const UserDeletionRequestDateTextWidget({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final userDeletionRequestDate = ref.watch(getUserDeletionRequestDateProvider);
return userDeletionRequestDate.when(
data: (date) => Text(
date,
),
loading: () => const Text(''),
error: (e, s) => const Text(AppStrings.dateTextWidgetError),
);
}
}
7 changes: 7 additions & 0 deletions lib/router/RouterProvider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:blueberry_flutter_template/feature/admin/AdminUserListPage.dart'
import 'package:blueberry_flutter_template/feature/chat/ChatScreen.dart';
import 'package:blueberry_flutter_template/feature/payment/widget/WebPaymentWidget.dart';
import 'package:blueberry_flutter_template/feature/setting/SettingScreen.dart';
import 'package:blueberry_flutter_template/feature/user/restore/RestoreDeletedUserScreen.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
Expand Down Expand Up @@ -138,6 +139,12 @@ final routerProvider = Provider<GoRouter>((ref) {
name: ProfileDetailScreen.name,
builder: (context, state) =>
ResponsiveLayoutBuilder(context, const ProfileDetailScreen()),
),
GoRoute(
path: 'restoredeleteduser',
name: RestoreDeletedUserScreen.name,
builder: (context, state) =>
ResponsiveLayoutBuilder(context, const RestoreDeletedUserScreen()),
)
],
),
Expand Down
Loading

0 comments on commit b15e678

Please sign in to comment.