/flutter_auth_app

Flutter auth app with TDD Clean Architecture

Primary LanguageDart


Flutter App Auth ๐Ÿ“ฑ

This is an App with Auth Functions like Login and Register. All API using reqres.in.
This app also implementing Flutter Clean Architecture with TDD.

light-theme.mp4
dark-theme.mp4

Pre-requisites ๐Ÿ“

Technology Recommended Version Installation Guide
Flutter v3.10.x Flutter Official Docs
Dart v3.0.x Installed automatically with Flutter

Get Started ๐Ÿš€

  • Clone this project
  • Run flutter pub get
  • Run flutter gen-l10n to generate localization files
  • Run flutter pub run build_runner build --delete-conflicting-outputs to generate freezes files
  • Run flutter run --flavor stg -t lib/main.dart --dart-define-from-file .env.stg.json for staging or
  • Run flutter run --flavor prd -t lib/main.dart --dart-define-from-file .env.prd.json for production
  • Run Test flutter test
  • To generate launcher icon based on Flavor dart run flutter_launcher_icons
  • To generate mock class dart pub run build_runner build

Feature โœ…

  • BLoC State Management
  • Clean Architecture with TDD
    • Unit Test
    • Widget Test
    • BLoC test
  • Theme Configuration: System, Light, Dark
  • Multi-Language: English, Bahasa
  • Login, Register Example
  • Pagination Example
  • Autofill Username and Password

TODO ๐Ÿ“

  • Integration Test
  • Implement multi-flavor
  • Implement Go Router

Maestro Test ๐Ÿงช

574ae4cc-e3a9-4755-8494-81bfe8763e00.mp4

Architecture Proposal by Resocoder


architecture-proposal

Project Structure


lib
โ”œโ”€โ”€ config.dart
โ”œโ”€โ”€ core
โ”‚   โ”œโ”€โ”€ api
โ”‚   โ”‚   โ”œโ”€โ”€ api.dart
โ”‚   โ”‚   โ”œโ”€โ”€ dio_client.dart
โ”‚   โ”‚   โ”œโ”€โ”€ dio_interceptor.dart
โ”‚   โ”‚   โ”œโ”€โ”€ isolate_parser.dart
โ”‚   โ”‚   โ””โ”€โ”€ list_api.dart
โ”‚   โ”œโ”€โ”€ app_route.dart
โ”‚   โ”œโ”€โ”€ core.dart
โ”‚   โ”œโ”€โ”€ core_mapper.dart
โ”‚   โ”œโ”€โ”€ error
โ”‚   โ”‚   โ”œโ”€โ”€ error.dart
โ”‚   โ”‚   โ”œโ”€โ”€ exceptions.dart
โ”‚   โ”‚   โ””โ”€โ”€ failure.dart
โ”‚   โ”œโ”€โ”€ localization
โ”‚   โ”‚   โ”œโ”€โ”€ generated
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ strings.dart
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ strings_en.dart
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ strings_id.dart
โ”‚   โ”‚   โ”œโ”€โ”€ intl_en.arb
โ”‚   โ”‚   โ”œโ”€โ”€ intl_id.arb
โ”‚   โ”‚   โ”œโ”€โ”€ l10n.dart
โ”‚   โ”‚   โ””โ”€โ”€ localization.dart
โ”‚   โ”œโ”€โ”€ resources
โ”‚   โ”‚   โ”œโ”€โ”€ dimens.dart
โ”‚   โ”‚   โ”œโ”€โ”€ images.dart
โ”‚   โ”‚   โ”œโ”€โ”€ palette.dart
โ”‚   โ”‚   โ”œโ”€โ”€ resources.dart
โ”‚   โ”‚   โ””โ”€โ”€ styles.dart
โ”‚   โ”œโ”€โ”€ usecase
โ”‚   โ”‚   โ””โ”€โ”€ usecase.dart
โ”‚   โ””โ”€โ”€ widgets
โ”‚       โ”œโ”€โ”€ button.dart
โ”‚       โ”œโ”€โ”€ button_notification.dart
โ”‚       โ”œโ”€โ”€ button_text.dart
โ”‚       โ”œโ”€โ”€ circle_image.dart
โ”‚       โ”œโ”€โ”€ color_loaders.dart
โ”‚       โ”œโ”€โ”€ drop_down.dart
โ”‚       โ”œโ”€โ”€ empty.dart
โ”‚       โ”œโ”€โ”€ loading.dart
โ”‚       โ”œโ”€โ”€ my_appbar.dart
โ”‚       โ”œโ”€โ”€ parent.dart
โ”‚       โ”œโ”€โ”€ spacer_h.dart
โ”‚       โ”œโ”€โ”€ spacer_v.dart
โ”‚       โ”œโ”€โ”€ text_f.dart
โ”‚       โ”œโ”€โ”€ toast.dart
โ”‚       โ””โ”€โ”€ widgets.dart
โ”œโ”€โ”€ dependencies_injection.dart
โ”œโ”€โ”€ features
โ”‚   โ”œโ”€โ”€ auth
โ”‚   โ”‚   โ”œโ”€โ”€ auth.dart
โ”‚   โ”‚   โ”œโ”€โ”€ data
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ data.dart
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ datasources
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth_remote_datasources.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ datasources.dart
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ models
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ login_response.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ login_response.freezed.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ login_response.g.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ models.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ register_response.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ register_response.freezed.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ register_response.g.dart
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ repositories
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ auth_repository_impl.dart
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ repositories.dart
โ”‚   โ”‚   โ”œโ”€โ”€ domain
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ domain.dart
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ entities
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ entities.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ login.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ login.freezed.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ register.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ register.freezed.dart
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ repositories
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth_repository.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ repositories.dart
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ usecases
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_login.dart
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_login.freezed.dart
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_login.g.dart
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_register.dart
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_register.freezed.dart
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_register.g.dart
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ usecases.dart
โ”‚   โ”‚   โ””โ”€โ”€ pages
โ”‚   โ”‚       โ”œโ”€โ”€ login
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ cubit
โ”‚   โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ auth_cubit.dart
โ”‚   โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ auth_cubit.freezed.dart
โ”‚   โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ auth_state.dart
โ”‚   โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ cubit.dart
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ login.dart
โ”‚   โ”‚       โ”‚   โ””โ”€โ”€ login_page.dart
โ”‚   โ”‚       โ”œโ”€โ”€ pages.dart
โ”‚   โ”‚       โ””โ”€โ”€ register
โ”‚   โ”‚           โ”œโ”€โ”€ cubit
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ cubit.dart
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ register_cubit.dart
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ register_cubit.freezed.dart
โ”‚   โ”‚           โ”‚   โ””โ”€โ”€ register_state.dart
โ”‚   โ”‚           โ”œโ”€โ”€ register.dart
โ”‚   โ”‚           โ””โ”€โ”€ register_page.dart
โ”‚   โ”œโ”€โ”€ features.dart
โ”‚   โ”œโ”€โ”€ general
โ”‚   โ”‚   โ”œโ”€โ”€ general.dart
โ”‚   โ”‚   โ””โ”€โ”€ pages
โ”‚   โ”‚       โ”œโ”€โ”€ main
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ main.dart
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ main_page.dart
โ”‚   โ”‚       โ”‚   โ””โ”€โ”€ menu_drawer.dart
โ”‚   โ”‚       โ”œโ”€โ”€ pages.dart
โ”‚   โ”‚       โ”œโ”€โ”€ settings
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ cubit
โ”‚   โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ cubit.dart
โ”‚   โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ settings_cubit.dart
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ settings.dart
โ”‚   โ”‚       โ”‚   โ””โ”€โ”€ settings_page.dart
โ”‚   โ”‚       โ””โ”€โ”€ splashscreen
โ”‚   โ”‚           โ”œโ”€โ”€ splash_screen_page.dart
โ”‚   โ”‚           โ””โ”€โ”€ splashscreen.dart
โ”‚   โ””โ”€โ”€ users
โ”‚       โ”œโ”€โ”€ data
โ”‚       โ”‚   โ”œโ”€โ”€ data.dart
โ”‚       โ”‚   โ”œโ”€โ”€ datasources
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ datasources.dart
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ user_remote_datasources.dart
โ”‚       โ”‚   โ”œโ”€โ”€ models
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ models.dart
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ users_response.dart
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ users_response.freezed.dart
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ users_response.g.dart
โ”‚       โ”‚   โ””โ”€โ”€ repositories
โ”‚       โ”‚       โ”œโ”€โ”€ repositories.dart
โ”‚       โ”‚       โ””โ”€โ”€ users_repository_impl.dart
โ”‚       โ”œโ”€โ”€ domain
โ”‚       โ”‚   โ”œโ”€โ”€ domain.dart
โ”‚       โ”‚   โ”œโ”€โ”€ entities
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ entities.dart
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ users.dart
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ users.freezed.dart
โ”‚       โ”‚   โ”œโ”€โ”€ repositories
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ repositories.dart
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ users_repository.dart
โ”‚       โ”‚   โ””โ”€โ”€ usecases
โ”‚       โ”‚       โ”œโ”€โ”€ get_users.dart
โ”‚       โ”‚       โ”œโ”€โ”€ get_users.freezed.dart
โ”‚       โ”‚       โ”œโ”€โ”€ get_users.g.dart
โ”‚       โ”‚       โ””โ”€โ”€ usecases.dart
โ”‚       โ”œโ”€โ”€ pages
โ”‚       โ”‚   โ”œโ”€โ”€ dashboard
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ cubit
โ”‚       โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ cubit.dart
โ”‚       โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ users_cubit.dart
โ”‚       โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ users_cubit.freezed.dart
โ”‚       โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ users_state.dart
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ dashboard.dart
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ dashboard_page.dart
โ”‚       โ”‚   โ””โ”€โ”€ pages.dart
โ”‚       โ””โ”€โ”€ users.dart
โ”œโ”€โ”€ lzyct_app.dart
โ”œโ”€โ”€ main_prd.dart
โ”œโ”€โ”€ main_stg.dart
โ””โ”€โ”€ utils
    โ”œโ”€โ”€ ext
    โ”‚   โ”œโ”€โ”€ context.dart
    โ”‚   โ”œโ”€โ”€ ext.dart
    โ”‚   โ”œโ”€โ”€ string.dart
    โ”‚   โ””โ”€โ”€ text_theme.dart
    โ”œโ”€โ”€ helper
    โ”‚   โ”œโ”€โ”€ common.dart
    โ”‚   โ”œโ”€โ”€ constant.dart
    โ”‚   โ”œโ”€โ”€ data_helper.dart
    โ”‚   โ”œโ”€โ”€ data_helper.freezed.dart
    โ”‚   โ”œโ”€โ”€ go_router_refresh_stream.dart
    โ”‚   โ””โ”€โ”€ helper.dart
    โ”œโ”€โ”€ services
    โ”‚   โ”œโ”€โ”€ firebase
    โ”‚   โ”‚   โ”œโ”€โ”€ firebase.dart
    โ”‚   โ”‚   โ”œโ”€โ”€ firebase_crashlogger.dart
    โ”‚   โ”‚   โ””โ”€โ”€ firebase_services.dart
    โ”‚   โ”œโ”€โ”€ hive
    โ”‚   โ”‚   โ”œโ”€โ”€ hive.dart
    โ”‚   โ”‚   โ””โ”€โ”€ main_box.dart
    โ”‚   โ””โ”€โ”€ services.dart
    โ””โ”€โ”€ utils.dart

Test Project Structure


test
โ”œโ”€โ”€ features
โ”‚   โ”œโ”€โ”€ auth
โ”‚   โ”‚   โ”œโ”€โ”€ data
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ datasources
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ models
โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ login_response_test.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ register_response_test.dart
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ repositories
โ”‚   โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ auth_remote_datasources_test.dart
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ repositories
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ auth_repository_impl_test.dart
โ”‚   โ”‚   โ”œโ”€โ”€ domain
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ usecases
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ post_login_test.dart
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ post_register_test.dart
โ”‚   โ”‚   โ””โ”€โ”€ pages
โ”‚   โ”‚       โ”œโ”€โ”€ login
โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ cubit
โ”‚   โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ auth_cubit_test.dart
โ”‚   โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ auth_cubit_test.mocks.dart
โ”‚   โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ auth_state_test.dart
โ”‚   โ”‚       โ”‚   โ””โ”€โ”€ login_page_test.dart
โ”‚   โ”‚       โ””โ”€โ”€ register
โ”‚   โ”‚           โ”œโ”€โ”€ cubit
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ register_cubit_test.dart
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ register_cubit_test.mocks.dart
โ”‚   โ”‚           โ”‚   โ””โ”€โ”€ register_state_test.dart
โ”‚   โ”‚           โ””โ”€โ”€ register_page_test.dart
โ”‚   โ”œโ”€โ”€ general
โ”‚   โ”‚   โ””โ”€โ”€ pages
โ”‚   โ”‚       โ””โ”€โ”€ settings
โ”‚   โ”‚           โ”œโ”€โ”€ cubit
โ”‚   โ”‚           โ”‚   โ””โ”€โ”€ settings_cubit_test.dart
โ”‚   โ”‚           โ””โ”€โ”€ settings_page_test.dart
โ”‚   โ””โ”€โ”€ users
โ”‚       โ”œโ”€โ”€ data
โ”‚       โ”‚   โ”œโ”€โ”€ datasources
โ”‚       โ”‚   โ”‚   โ”œโ”€โ”€ models
โ”‚       โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ users_response_test.dart
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ repositories
โ”‚       โ”‚   โ”‚       โ””โ”€โ”€ users_remote_datasources_test.dart
โ”‚       โ”‚   โ””โ”€โ”€ repositories
โ”‚       โ”‚       โ””โ”€โ”€ users_repository_impl_test.dart
โ”‚       โ”œโ”€โ”€ domain
โ”‚       โ”‚   โ””โ”€โ”€ usecases
โ”‚       โ”‚       โ””โ”€โ”€ get_users_test.dart
โ”‚       โ””โ”€โ”€ pages
โ”‚           โ””โ”€โ”€ dashboard
โ”‚               โ”œโ”€โ”€ cubit
โ”‚               โ”‚   โ”œโ”€โ”€ users_cubit_test.dart
โ”‚               โ”‚   โ”œโ”€โ”€ users_cubit_test.mocks.dart
โ”‚               โ”‚   โ””โ”€โ”€ users_state_test.dart
โ”‚               โ””โ”€โ”€ dashboard_page_test.dart
โ””โ”€โ”€ helpers
    โ”œโ”€โ”€ fake_path_provider_platform.dart
    โ”œโ”€โ”€ json_reader.dart
    โ”œโ”€โ”€ paths.dart
    โ”œโ”€โ”€ stubs
    โ”‚   โ”œโ”€โ”€ list_user_empty_response.json
    โ”‚   โ”œโ”€โ”€ list_user_response.json
    โ”‚   โ”œโ”€โ”€ login_success_response.json
    โ”‚   โ”œโ”€โ”€ login_unsuccessful_response.json
    โ”‚   โ”œโ”€โ”€ register_success_response.json
    โ”‚   โ””โ”€โ”€ register_unsuccessful_response.json
    โ”œโ”€โ”€ test_mock.dart
    โ””โ”€โ”€ test_mock.mocks.dart



Buy me coffee if you love my works โ˜•๏ธ

buymeacoffe      ko-fi      paypal saweria