Skip to content

Plan Buddy - Share Khan Project #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 98 additions & 130 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,132 +1,100 @@
# get-flutter-fire
# PlanBuddy - ShreKhan Project

Welcome to the Flutter Todo Task App - PlanBuddy


PlanBuddy is a productivity app designed to help users manage and organize their tasks effectively. It features a clean and intuitive interface where users can view and categorize tasks into "Pending" and "Completed" sections. Users can add new tasks, edit existing ones, and easily switch between different task views using a simple tab interface. The app integrates with Firebase for user authentication and data storage, ensuring seamless synchronization and security.
The main functionalities include:
1) Task Management: Add, edit, and categorize tasks as pending or completed.
2) User Authentication: Sign in and sign out securely using Firebase Authentication.
3) Real-time Data Sync: Store and manage tasks in real-time with Firebase Firestore.
4) PlanBuddy aims to streamline task management and enhance productivity with a user-friendly experience.

==============================================

# Steps

1) . Add the Android Folder
If your existing Flutter project doesn’t have the Android folder, you can generate it with the following command:

* Navigate to Your Project Directory:
`cd path/to/your/project`
* Generate the Android Folder:
`flutter create` .
This command will create the necessary Android folder and its configuration files if they are missing.

2) Firebase Setup
Add Firebase to Your Flutter App:
1. Go to the “Project settings” in the Firebase Console.
2. Under “Your apps,” select the appropriate platform (iOS/Android) and follow the instructions to register your app.
3. Download the google-services.json (for Android) or GoogleService-Info.plist (for iOS) and place them in the respective directories:
* For Android: Place google-services.json in the android/app directory.
* For iOS: Place GoogleService-Info.plist in the ios/Runner directory.
3) Configure Firebase for Flutter:
* Run the following command to generate firebase_options.dart:
`flutterfire configure`
This will create the firebase_options.dart file in your project. Ensure it is properly imported and used in your main.dart file.

4) Update Firebase SDK Dependencies:

* Ensure you have the correct Firebase dependencies in your pubspec.yaml file. Add or update the dependencies as needed:
` dependencies:`
`firebase_core: ^3.4.0`
`firebase_auth: ^5.2.0`
`cloud_firestore: ^5.3.0`
`provider: ^6.1.2`
`intl: ^0.19.0`
`flutter_slidable: ^3.1.1`
`flutter_spinkit: ^5.2.1`
`get_storage: ^2.1.1`
5) Run the App
1. Ensure Firebase Setup:
* Make sure all Firebase configurations are correctly set up, and dependencies are installed.
2. Run the App:
* Use the following command to run the app on your emulator or physical device:
`flutter run`

# Using the App

Sign In: Use the authentication options provided to sign in or create a new user account.
Manage Tasks: Add, edit, and view tasks in the “Pending” and “Completed” sections.
Sign Out: Use the sign-out button in the app to log out of your account.
![alt text](image-1.png) ![alt text](image.png) ![alt text](image-4.png)

# Key Features
1) User Authentication:
* Secure Sign-In/Sign-Out: Manage user accounts securely with Firebase Authentication.
* Sign-In Requirements:
+ Email and Password: Users must provide a valid email address and a password that meets minimum complexity requirements (e.g., at least 6 characters).
* Display Messages: Inform users of any sign-in issues with clear error messages if fields are missing or if the password does not meet requirements.

![alt text](image-2.png) ![alt text](image-3.png)

2) Task Management:
* Create Tasks: Add new tasks with details and due dates(+ icon for adding task).
![alt text](image-6.png) ![alt text](image-7.png)
* Edit Tasks: Modify existing tasks with updated information.
![alt text](image-10.png) ![alt text](image-11.png)
* Delete Tasks: Remove tasks with a swipe gesture.

3) Task Interaction:
* Swipe Actions:
+ Left Swipe: Reveal options to delete or edit tasks.
+ Right Swipe: Mark tasks as completed.
![alt text](image-8.png) ![alt text](image-9.png)
* Completion Handling:
+ Move to Completed Tab: Tasks marked as completed are automatically moved to the "Completed" tab.
+ Strike-Through Effect: Completed tasks are displayed with a strike-through to visually indicate completion.
![alt text](image-12.png) ![alt text](image-13.png)


4) Real-Time Data Sync:
* Firestore Integration: Sync and manage tasks in real-time using Firebase Firestore.
![alt text](image-14.png) ![alt text](image-15.png)
5) Responsive Design:
* Cross-Platform Compatibility: Ensure the app works well on phones, tablets, and desktops with adaptive layouts.
6) User Interaction Enhancements:
* Navigation: Easy navigation through tab-based views for pending and completed tasks.
* Floating Action Button (FAB): Add new tasks quickly using the FAB with an add icon.

This codebase provides a boilerplate code utilizing the following three technologies:

1. Flutter 3.0 - For UX and uses Dart languange. See [https://flutter.dev/]
2. GetX - State management for Flutter. See [https://github.com/jonataslaw/getx/tree/4.6.1]
3. Firebase - For Backend as a Service. See [https://firebase.google.com/]
1. Easy Authentication flow
2. Server side functions
3. Remote Configurations which can be used for A/B testing

This was created as part of my own learning process and you will find that git commits were made according to the Steps listed below. You can use the git version history to check each commit and learn step by step, as I did.

I am also using this codebase as an experiment towards hiring people (freshers especially but not limited to them) for my development team. If you are in Mumbai and are interested to join my team, you can use this codebase in the following manner:

* Fork the codebase
* Add your own firebase_options.dart (follow steps and see firebase_options.template)
* **Build your own application using this as a base (integrating any existing project of yours also works)**, or complete a TODO or fix a bug (only if you have no other ideas)
* Send me a Pull Request. Mention a way of connecting with you in the commit message along with details of commit. Also modify ReadMe to say what you have changed in detail.
* I will go through the request and then connect with you if I find the entry to be interesting and take an interview round.

## The Steps

Step 1: Use Get CLI [https://pub.dev/packages/get_cli]

`get create project`

Step 2: Copy code from [https://github.com/jonataslaw/getx/tree/4.6.1/example_nav2/lib]

Step 3: Integrate FlutterFire Authentication

- Tutorials [https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps#0] for inspiration
- Firebase Documentation [https://firebase.google.com/docs/auth/flutter/start]
- Blog [www.medium.com/TBD]
- To compile the code ensure that you generate your own firebase_options.dart by running

`flutterfire configure`

Step 4: Add Google OAuth [https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps#6]. Note ensure you do the steps for Android and iOS as the code for it is not in Github

Step 5: Add Guest User/Anonymous login with a Cart and Checkout use case [https://firebase.google.com/docs/auth/flutter/anonymous-auth]

* delete unlinked anonymous user post logout

Step 6: Add ImagePicker and Firebase Storage for profile image

* Create PopupMenu button for web [https://api.flutter.dev/flutter/material/PopupMenuButton-class.html]
* BottomSheet for phones and single file button for desktops
* GetX and Image Picker [https://stackoverflow.com/questions/66559553/flutter-imagepicker-with-getx]
* Add FilePicker [https://medium.com/@onuaugustine07/pick-any-file-file-picker-flutter-f82c0144e27c]
* Firebase Storage [https://mercyjemosop.medium.com/select-and-upload-images-to-firebase-storage-flutter-6fac855970a9] and [https://firebase.google.com/docs/storage/flutter/start]

Modify the Firebase Rules
`service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow write: if request.auth.uid != null; allow read: if true; } } }`

Fix CORS [https://stackoverflow.com/questions/37760695/firebase-storage-and-access-control-allow-origin]
* PList additions [https://medium.com/unitechie/flutter-tutorial-image-picker-from-camera-gallery-c27af5490b74]

Step 7: Additional Auth flow items

1. Add a Change Password Screen. The Flutter Fire package does not have this screen.
2. TODO: Add ReCaptcha to login flow for password authentication for Web only
* Phone Auth on Web has a ReCaptcha already [https://firebase.flutter.dev/docs/auth/phone/]. Tried to use that library but it is very cryptic.
* Use the following instead [https://stackoverflow.com/questions/60675575/how-to-implement-recaptcha-into-a-flutter-app] or [https://medium.com/cloudcraftz/securing-your-flutter-web-app-with-google-recaptcha-b556c567f409] or [https://pub.dev/packages/g_recaptcha_v3]
3. TODO: Ensure Reset Password has Email verification
4. TODO: Add Phone verification [https://firebase.google.com/docs/auth/flutter/phone-auth]
* See [https://github.com/firebase/flutterfire/issues/4189].
5. TODO: Add 2FA with SMS Pin. This screen is available in the Flutter Fire package

Step 8: Add Firebase Emulator to test on laptop instead of server so that we can use Functions without upgrading the plan to Blaze. See [https://firebase.google.com/docs/emulator-suite/install_and_configure]

Step 9: Add User Roles using Custom Claims. This requires upgrade of plan as we need to use Firebase Functions. Instead using Emulator.

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.
2. Add Function to add the custom claim to make the first user the admin using the Admin SDK
3. Registeration form to collect some data post signUp and enforce email verification from Client side.

* Note! for Emulator check the console to verify using the link provided as email is not sent.
4. Enforcing verify email using a button which appears when SignIn fails due to non verification.

* Fixed the error handling message during login.
* Coverted server side to Typescript
* Enabled Resend verification mail button
* Approach 1 - Use Email Link Authentication and signIn, assuming it marks email as verified also. We cannot send the verification mail as is, since that can be sent only if signed in (which was allowed only for first login post signup)
* Refer https://firebase.google.com/docs/auth/flutter/email-link-auth
* TODO Enable Deep Linking: According to https://firebase.google.com/docs/dynamic-links/flutter/receive, the Flutter feature is being deprecated and we should use the AppLinks (Android), UniversalLinks(iOS) instead. Leaving this for future as adding complexity.
* We could use the server side handling instead of deep linking. See [https://firebase.google.com/docs/auth/custom-email-handler?hl=en&authuser=0#web]. However, this requires changing the email template for the URL which is not possible in Emulator. Using the continueURL instead does not work as oobCode is already expired. This handling also uses the web client sdk. Thus it is better to go with the below method instead.
* Approach 2 - (Hack) send a create request with suffix ".verify" added in email when button clicked. Use the server side beforeCreate to catch this and send verification mail
* 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
* Sending emails from server side is possible but by using the web client SDK.
5. TODO: Other Items

* TODO: Using autocomplete for emails is throwing error log in terminal. No impact but need to fix when all is done.
* 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]
6. Added Roles of Buyer and Seller.

1. Added Access level in increasing order of role order => Buyer then Seller then Admin
2. Created Navigation for each of Admin, Buyer, Seller screens
3. Allowed switch from lower role Navigation to Navigation view till the given role of the user

Step 10: Firebase Remote Config for A/B testing. See [https://firebase.google.com/docs/remote-config]

1. Complete the Screen enum based Navigation framework
2. Config useBottomSheetForProfileOptions for Navigation element to be one of the following
* False: Drawer for Account, Settings, Sign Out
* True: Hamburger that opens BottomSheet (Context Menu in larger screen) for the same options
3. TODO: Config for adding Search Bar at the Top vs a Bottom Navigation button

Step 11: TODO: CRUD

* Users request role upgrade
* Add this request data to Firebase Datastore
* Create ListView with slidable tiles for approvals
* Admin SDK used by admin user via workflow on this request data and is approved from app
* 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
* Nested Category, Sub-Category tree creation

Step 12: TODO: Theming and Custom Settings

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

Step 13: TODO: Large vs Small screen responsiveness

* 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.
* Top Right Icon: used for Login and post Login triggers BottomSheet/Context Menu for Persona Change, Profile, Settings, Change Password, Logout
* Search Bar (Toggle Button for phones) on Top Center with Title
* Status Bottom Bar for desktops only instead of SnackBars
* FAB vs Main Menu

Step 14: TODO: Make own login flow screens. Remove firebase library reference from all but auth_service
31 changes: 26 additions & 5 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
analyzer:
errors:
constant_identifier_names: ignore
include: package:flutter_lints/flutter.yaml
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
# include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:

# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
29 changes: 29 additions & 0 deletions android/app/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "595805963796",
"project_id": "todoapp-c66c4",
"storage_bucket": "todoapp-c66c4.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:595805963796:android:f84190cec3451b3c778901",
"android_client_info": {
"package_name": "com.todoapp.app"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyDN9dQSVEf2yXQ_O6WLEqWqkJzqwV2JTbE"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.todoapp.app;

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity()
Binary file removed assets/icons/logo.png
Binary file not shown.
Binary file removed assets/images/dash.png
Binary file not shown.
Binary file removed assets/images/flutterfire_300x.png
Binary file not shown.
1 change: 1 addition & 0 deletions firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"flutter":{"platforms":{"dart":{"lib/firebase_options.dart":{"projectId":"quizapps-5ab17","configurations":{"android":"1:549769041276:android:4269afe02da1569a40c0f9"}}}}}}
Binary file added image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions ios/Flutter/Generated.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=C:\Users\priyal\flutter
FLUTTER_APPLICATION_PATH=C:\Users\priyal\get-flutter-fire
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib\main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json
13 changes: 13 additions & 0 deletions ios/Flutter/flutter_export_environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=C:\Users\priyal\flutter"
export "FLUTTER_APPLICATION_PATH=C:\Users\priyal\get-flutter-fire"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
19 changes: 19 additions & 0 deletions ios/Runner/GeneratedPluginRegistrant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Generated file. Do not edit.
//

// clang-format off

#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h

#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN

@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end

NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */
Loading