# BikeSetup Android App Android client for the BikeSetup backend. Built with Kotlin, Jetpack Compose, and Ktor. ## Stack - **UI**: Jetpack Compose + Material 3 (dark theme default) - **Architecture**: MVVM with ViewModels, single-activity - **Navigation**: Jetpack Navigation Compose - **DI**: Koin - **Networking**: Ktor client (OkHttp engine) with automatic cookie jar for session auth - **Serialization**: Kotlinx Serialization - **Testing**: JUnit, MockK, coroutine test utilities, Robolectric, Compose UI test APIs ## Project Structure ``` com.bikeloam.app/ ├── data/ │ ├── model/ # Auth, Catalog, Build, Review DTOs │ ├── network/ # Ktor HttpClient + BikeApiClient │ └── repository/ # BikeRepository (Result-wrapped API calls) ├── di/ │ └── AppModule.kt # Koin module wiring ├── navigation/ │ └── BikeAppNavGraph.kt └── ui/ ├── screen/ # 10 Composable screens ├── theme/ # Material3 theme + colors └── viewmodel/ # 9 ViewModels (MVVM) ``` ## Setup 1. Install Android SDK and set the path in `local.properties`: ```properties sdk.dir=/path/to/your/Android/Sdk ``` 2. Generate the Gradle wrapper jar (if missing): ```bash gradle wrapper ``` Or open the project in Android Studio. 3. Start the backend server: ```bash cd .. npm run dev ``` 4. Build the app: ```bash ./gradlew assembleDebug ``` 5. Install on an emulator or device: ```bash ./gradlew installDebug ``` 6. Run JVM unit tests: ```bash ./gradlew testDebugUnitTest ``` ## API Configuration The debug build points to `http://10.0.2.2:3000` (emulator localhost). For a physical device, update `BASE_URL` in `app/build.gradle.kts` to your machine's LAN IP (e.g., `http://192.168.1.x:3000`). ```kotlin buildConfigField("String", "BASE_URL", "\"http://YOUR_IP:3000\"") ``` ## Features - **Splash + Auth Gate**: On cold start, checks `/api/auth/me`. Authenticated users skip Login. - **Authentication**: Register / Login / Logout via cookie-based JWT sessions. - **Catalog Browsing**: Fetches frames, forks, shocks, and tires from `/api/catalog`. - **Build Management**: Create builds with component selection dropdowns. View build details with resolved component names. - **Ride Reviews**: Submit post-ride reviews with 1–10 sliders and issue checkboxes. - **AI Recommendations**: Fetches setup recommendations from `/api/ai/recommend`. ## Tests Unit tests live under `app/src/test/java/com/bikeloam/app/` and cover the repository, all ViewModels, network layer, and Compose screens: - `BikeRepositoryTest` - `NetworkClientTest` - `SplashViewModelTest` - `LoginViewModelTest` - `RegisterViewModelTest` - `HomeViewModelTest` - `BuildListViewModelTest` - `CreateBuildViewModelTest` - `BuildDetailViewModelTest` - `ReviewViewModelTest` - `RecommendationViewModelTest` - `LoginScreenTest` (Compose UI – Robolectric) - `HomeScreenTest` (Compose UI – Robolectric) Use `MainDispatcherRule` for coroutine dispatcher replacement in ViewModel tests. Run the full JVM suite with: ```bash ./gradlew testDebugUnitTest ``` ## Architecture Notes - **Session cookies** are handled automatically by Ktor's `HttpCookies` plugin. - **No `local.properties`** should be committed (it's `.gitignore`d). - **Network security config** allows cleartext HTTP for development (`10.0.2.2`). ## Next Steps / Known Limitations - No individual `GET /api/builds/:id` endpoint exists on the backend; the detail screen fetches the full list and filters by ID. - Component images are not yet loaded (Coil is included but image URLs aren't resolved from the backend yet). - Add offline caching (Room) for catalog and builds if desired.