Skip to content

Commit 9014ed1

Browse files
committed
Step 10.1 of modified README
1 parent d3a5c92 commit 9014ed1

File tree

22 files changed

+477
-282
lines changed

22 files changed

+477
-282
lines changed

README.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ Step 9: Add User Roles using Custom Claims. This requires upgrade of plan as we
5757
1. In Emulator we can add user via http://127.0.0.1:4000/auth and add custom claim via UI as {"role":"admin"}. The effect is shown via Product page in Nav instead of Cart page for admin user.
5858
2. Add Function to add the custom claim to make the first user the admin using the Admin SDK
5959
3. Registeration form to collect some data post signUp and enforce email verification from Client side.
60+
6061
* Note! for Emulator check the console to verify using the link provided as email is not sent.
6162
4. Enforcing verify email using a button which appears when SignIn fails due to non verification.
63+
6264
* Fixed the error handling message during login.
6365
* Coverted server side to Typescript
6466
* Enabled Resend verification mail button
@@ -70,14 +72,24 @@ Step 9: Add User Roles using Custom Claims. This requires upgrade of plan as we
7072
* Note that the Server side beforeCreate function can also bypass user creation till verification but the user record (esp password) needs to be stored anyways, so bypassing user creation is not a good idea. Instead, we should use the verified tag in subsequent processing
7173
* Sending emails from server side is possible but by using the web client SDK.
7274
5. TODO: Other Items
75+
7376
* TODO: Using autocomplete for emails is throwing error log in terminal. No impact but need to fix when all is done.
7477
* TODO: Add a job that removes all unverified users after a while automatically. This could be useful if you were victim of bot attacks, but adding the Recaptcha is better precaution. See [https://stackoverflow.com/questions/67148672/how-to-delete-unverified-e-mail-addresses-in-firebase-authentication-flutter/67150606#67150606]
7578
6. Added Roles of Buyer and Seller.
79+
7680
1. Added Access level in increasing order of role order => Buyer then Seller then Admin
7781
2. Created Navigation for each of Admin, Buyer, Seller screens
7882
3. Allowed switch from lower role Navigation to Navigation view till the given role of the user
7983

80-
Step 10: TODO: CRUD
84+
Step 10: TODO: Firebase Remote Config for A/B testing
85+
86+
1. Complete the Screen enum based Navigation framework
87+
2. Config for Navigation element change
88+
* A: Drawer for Account, Settings, Sign Out
89+
* B: Hamburger that opens BottomSheet (Context Menu in larger screen) for the same options
90+
3. Config for adding Search Bar at the Top vs a Bottom Navigation button
91+
92+
Step 11: TODO: CRUD
8193

8294
* Users request role upgrade
8395
* Add this request data to Firebase Datastore
@@ -86,24 +98,18 @@ Step 10: TODO: CRUD
8698
* Allow a Plan attribute via Custome Claims (e.g. Premium user flag) for Buyer and Seller, to add features which are not Navigation linked. Add a button Upgrade to Plan in Drawer that leads to Payment screen. Also certain aspects of premium plan can be visible that leads to upgrade plan screen via middleware
8799
* Nested Category, Sub-Category tree creation
88100

89-
Step 11: TODO: Theming and Custom Settings
101+
Step 12: TODO: Theming and Custom Settings
90102

91103
* Add Persona (like that in Netflix) and create a Persona selection only for Buyer Role
92104
* Add Minimal (Three Color Gradient Pallette) Material Theme. Align it with Persona Templates (like Kids Template in Netflix)
93105
* Dark theme toggle setting based on each Persona of the logged in User
94106

95-
Step 12: TODO: Firebase Remote Config for A/B testing
96-
97-
1. Config for Navigation element change
98-
* A: Drawer for Account, Settings, Sign Out
99-
* B: Hamburger that opens BottomSheet (Context Menu in larger screen) for the same options
100-
2. Config for adding Search Bar at the Top vs a Bottom Navigation button
101-
102107
Step 13: TODO: Large vs Small screen responsiveness
103108

104109
* Drawer: Triggered by Top Left Icon (App Logo). For iOS this icon changes to back button when required. Contains allowed Role List, Screens specified as Drawer. Becomes Left Side Navigation for Horizontal Screens. Can have additional extreme left vertical Navigation Strip. Bottom Navigation Bar also folds into this strip in Horizontal Screens.
105110
* Top Right Icon: used for Login and post Login triggers BottomSheet/Context Menu for Persona Change, Profile, Settings, Change Password, Logout
106111
* Search Bar (Toggle Button for phones) on Top Center with Title
107112
* Status Bottom Bar for desktops only instead of SnackBars
113+
* FAB vs Main Menu
108114

109115
Step 14: TODO: Make own login flow screens. Remove firebase library reference from all but auth_service

assets/icons/logo.png

17.1 KB
Loading

lib/app/middleware/auth_middleware.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// ignore_for_file: avoid_print
22
import 'package:get/get.dart';
33
import 'package:get_flutter_fire/models/role.dart';
4-
5-
import '../../services/auth_service.dart';
6-
import '../routes/app_pages.dart';
4+
import 'package:get_flutter_fire/services/auth_service.dart';
5+
import 'package:get_flutter_fire/app/routes/app_pages.dart';
76

87
Future<GetNavConfig?> loginVerify(bool check, GetNavConfig route,
98
Future<GetNavConfig?> Function(GetNavConfig) redirector) async {
Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,27 @@
11
import 'package:flutter/material.dart';
22

33
import 'package:get/get.dart';
4-
import 'package:get_flutter_fire/services/auth_service.dart';
5-
6-
import '../../../../models/screens.dart';
4+
import 'package:get_flutter_fire/app/routes/app_pages.dart';
5+
import '../../../widgets/screen_widget.dart';
6+
import '../../../../services/auth_service.dart';
77
import '../controllers/cart_controller.dart';
88

99
class CartView extends GetView<CartController> {
1010
const CartView({super.key});
1111
@override
1212
Widget build(BuildContext context) {
13-
return Scaffold(
13+
return ScreenWidget(
1414
appBar: AppBar(
1515
title: Text('${AuthService.to.userName} Cart'),
1616
centerTitle: true,
1717
),
18-
floatingActionButton: FloatingActionButton(
19-
onPressed: () => Get.rootDelegate.toNamed(Screen.CHECKOUT.route),
20-
backgroundColor: Colors.blue,
21-
child: const Icon(
22-
Icons.check_outlined,
23-
color: Colors.white,
24-
),
25-
),
2618
body: const Center(
2719
child: Text(
2820
'CartView is working',
2921
style: TextStyle(fontSize: 20),
3022
),
3123
),
24+
screen: screen!,
3225
);
3326
}
3427
}

lib/app/modules/home/views/home_view.dart

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:get/get.dart';
3-
import '../../../../models/screens.dart';
3+
import '../../../routes/app_pages.dart';
4+
import '../../../widgets/screen_widget.dart';
45
import '../controllers/home_controller.dart';
56

67
class HomeView extends GetView<HomeController> {
@@ -16,26 +17,16 @@ class HomeView extends GetView<HomeController> {
1617
}
1718
var route = controller.chosenRole.value.tabs[0].route;
1819
//This router outlet handles the appbar and the bottom navigation bar
19-
int currentIndex =
20-
controller.chosenRole.value.getCurrentIndexFromRoute(currentRoute);
21-
return Scaffold(
20+
return ScreenWidget(
21+
screen: screen!,
2222
body: GetRouterOutlet(
2323
initialRoute: route,
2424
// anchorRoute: Routes.HOME,
2525
key: Get.nestedKey(route),
2626
),
27-
bottomNavigationBar: BottomNavigationBar(
28-
currentIndex: currentIndex,
29-
onTap: (value) {
30-
controller.chosenRole.value.routeTo(value, delegate);
31-
},
32-
items: controller.chosenRole.value.tabs
33-
.map((Screen tab) => BottomNavigationBarItem(
34-
icon: Icon(tab.icon),
35-
label: tab.label,
36-
))
37-
.toList(),
38-
),
27+
role: controller.chosenRole.value,
28+
delegate: delegate,
29+
currentRoute: currentRoute,
3930
);
4031
},
4132
);

lib/app/modules/login/controllers/login_controller.dart

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,4 @@ class LoginController extends GetxController {
1717

1818
bool get isRegistered =>
1919
AuthService.to.registered.value || AuthService.to.isEmailVerified;
20-
21-
// @override
22-
// onInit() {
23-
// super.onInit();
24-
// showReverificationButton
25-
// .listen((value) => print("$value showReverificationButton set"));
26-
// }
2720
}

lib/app/modules/login/views/login_view.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class LoginView extends GetView<LoginController> {
7070
);
7171
} else if (controller.isAnon) {
7272
ui = RegisterScreen(
73+
providers: [
74+
MyEmailAuthProvider(),
75+
],
7376
showAuthActionSwitch: !controller.isAnon, //if Anon only SignUp
7477
showPasswordVisibilityToggle: true,
7578
headerBuilder: LoginWidgets.headerBuilder,
@@ -108,17 +111,12 @@ class LoginView extends GetView<LoginController> {
108111
List<FirebaseUIAction> getActions() {
109112
return [
110113
// AuthStateChangeAction<CredentialReceived>((context, state) {
111-
// print("***********Not Reaching*************");
112-
// print(state);
113-
// }),
114114
AuthStateChangeAction<AuthFailed>((context, state) => LoginController.to
115115
.errorMessage(context, state, showReverificationButton)),
116116
// AuthStateChangeAction<SignedIn>((context, state) {
117-
// // print("signed In");
118117
// // This is not required due to the AuthMiddleware
119118
// }),
120119
// EmailLinkSignInAction((context) {
121-
// // print("signed in by link");
122120
// final thenTo = Get.rootDelegate.currentConfiguration!.currentPage!
123121
// .parameters?['then'];
124122
// Get.rootDelegate.offNamed(thenTo ?? Routes.PROFILE);

lib/app/modules/profile/controllers/profile_controller.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ class ProfileController extends GetxController {
5656

5757
Future<void> updatePhotoURL(String dest) async {
5858
_photoURL.value = await storage.ref().child(dest).getDownloadURL();
59-
// print(pic);
6059
await currentUser?.updatePhotoURL(_photoURL.value);
6160
Get.snackbar('Success', 'Picture stored and linked');
6261
}

lib/app/modules/profile/views/profile_view.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class ProfileView extends GetView<ProfileController> {
9797
icon: const Icon(Icons.password_rounded),
9898
)
9999
: const SizedBox.shrink(),
100-
ImagePickerButton((String? path) async {
100+
ImagePickerButton(callback: (String? path) async {
101101
if (path != null) {
102102
//Upload to Store
103103
String? dest = await controller.uploadFile(path);

lib/app/modules/root/views/root_view.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,21 @@ class RootView extends GetView<RootController> {
2929
onPressed: () =>
3030
Get.rootDelegate.popRoute(), //Navigator.pop(context),
3131
)
32-
: AuthService.to.isLoggedInValue
33-
? IconButton(
34-
icon: const Icon(Icons.person),
35-
onPressed: () => controller.openDrawer(),
36-
)
37-
: null,
32+
: IconButton(
33+
icon: ImageIcon(
34+
const AssetImage("icons/logo.png"),
35+
color: Colors.grey.shade800,
36+
),
37+
onPressed: () => AuthService.to.isLoggedInValue
38+
? controller.openDrawer()
39+
: {Screen.HOME.doAction()},
40+
),
3841
actions: [
3942
Container(
4043
margin: const EdgeInsets.only(right: 15),
41-
child: Screen.LOGIN.widget)
44+
child: Screen.LOGIN.widget(current))
4245
],
43-
automaticallyImplyLeading: false, //removes drawer icon
46+
// automaticallyImplyLeading: false, //removes drawer icon
4447
),
4548
body: GetRouterOutlet(
4649
initialRoute: AppPages.INITIAL,

0 commit comments

Comments
 (0)