Skip to content

Mobile App

The mobile application is built with Flutter and targets iOS, Android, and Web. It is the primary interface for alumni to browse events, manage their profiles, and interact with the platform.

Tech Stack

CategoryTechnologyVersion
LanguageDart^3.8+
FrameworkFlutter^3.32+
State Managementflutter_bloc (Cubit)^9.0+
NavigationAutoRoute^9.3+
HTTP ClientDio^5.8+
SerializationFreezed + json_serializable^2.5, ^6.9
Error Handlingfpdart (functional)^1.1+
Secure Storageflutter_secure_storage^9.2+
Local Databasesqflite (mobile)^2.4+
Mapsflutter_maplatest
SVG Supportflutter_svglatest
AnalyticsAppMetricanative
Code Generationbuild_runner + freezed_runnerlatest
Logginglogger^2.5+

3-Layer Architecture

Project Structure

text
lib/
├── main.dart                     # Entry point, system UI config
├── app.dart                      # MultiBlocProvider DI, MaterialApp, AutoRoute
├── data/
│   ├── gateways/                 # HTTP interfaces + Dio implementations
│   │   ├── auth_gateway.dart / _impl.dart
│   │   ├── events_gateway.dart / _impl.dart
│   │   ├── profile_gateway.dart / _impl.dart
│   │   ├── users_gateway.dart / _impl.dart
│   │   └── locations_gateway.dart / _impl.dart
│   ├── models/                   # JSON-mapped Freezed data models
│   ├── token/                    # TokenManager + secure storage persistence
│   ├── config/                   # API base URL config (web vs mobile)
│   ├── paths.dart                # API endpoint string constants
│   ├── secrets/                  # AppMetrica key loader
│   └── db/                      # sqflite DB manager
├── application/
│   ├── repositories/             # Business logic interfaces + implementations
│   │   ├── auth/
│   │   ├── events/               # With in-memory caching
│   │   ├── users/
│   │   ├── locations/
│   │   └── reporter/             # AppMetrica / Mock analytics
│   ├── models/                   # Domain models (Freezed)
│   │   ├── profile.dart
│   │   ├── event.dart
│   │   ├── cost.dart
│   │   └── ...
│   └── mappers/                  # DataModel → DomainModel converters
├── presentation/
│   ├── router/                   # AutoRoute config + generated routes
│   ├── blocs/                    # Cubits (one per feature)
│   ├── pages/                    # Screen widgets
│   ├── managers/                 # app_loading_manager.dart (startup orchestration)
│   └── common/
│       ├── constants/            # AppColors, AppTextStyles
│       └── widgets/              # Shared reusable widgets
└── util/
    └── logger.dart

State Management: Cubit Pattern

Cubits are the lighter variant of BLoC — they emit states directly via functions instead of processing events.

Generic LoadedState

All Cubits use a sealed LoadedState<T> class:

text
LoadedState<T>
├── LoadedStateInit()        — initial/idle
├── LoadedStateLoading()     — async operation in progress
├── LoadedStateData(T data)  — success with typed payload
└── LoadedStateError(String) — failure with message

Cubit Inventory

CubitScopeResponsibility
AuthCubitAuth pagesEmail/password login, validation
RegistrationCubitRegistration pageRegistration form + API call
EventsListCubitGlobal (root)Load + cache event list
ProfileCubitGlobal (root)Load current user profile + participation
ProfileEditingCubitEdit profile pageUpdate bio, photo, social links
OneEventCubitEvent detail pageFetch event, join/leave
RootPageCubitRoot pageBottom navigation tab index
PinLocationsCubitMap pageLoad event pins for map
PasswordReset*CubitsPassword reset pagesRequest + confirm reset flow

Dependency Injection

Dependencies are wired at app startup in app.dart using Flutter's MultiBlocProvider:

Services are accessed via context.read<T>() throughout the widget tree.

Data Flow: Load Events

Error Handling Strategy

The app uses fpdart Either<L, R> types in the repository layer:

  • Right<EventModel> — success path
  • Left<AppError> — typed error (network failure, auth error, not found, etc.)

Cubits pattern-match on Either to emit LoadedStateData or LoadedStateError.

Analytics

The analytics reporter is abstracted behind an interface:

ImplementationWhen Used
ReporterAppMetricaProduction builds (uses AppMetrica SDK)
ReporterMockTesting / development (no-op)

Platform Notes

PlatformConfig SourceToken Storage
Android / iOSApp environmentflutter_secure_storage (Keychain/Keystore)
Webwindow.apiBaseUrl injected at build timeBrowser secure storage

IU Alumni Platform Documentation