Files
pantree/android/app/build.gradle
Azriel b42497a368 feat(frontend): implement full Android UI — auth, pantry, recipes, shopping lists, settings, navigation
## Summary
Complete Jetpack Compose Android frontend for Pantree Phase 1 MVP.

### Architecture
- MVVM + Repository pattern with Hilt DI
- Room local cache with Flow-based observation
- Retrofit + OkHttp with JWT auth interceptor
- EncryptedSharedPreferences token storage
- ConnectivityObserver for offline detection

### Screens & ViewModels
- Auth: SignIn, SignUp, ForgotPassword, AccountRestore
- Pantry: list, add/edit/delete items, duplicate conflict handling
- Recipes: browse with filter chips (All/Can Make/Partial), search, detail with scale (1×/2×/3×)
- Shopping Lists: list index, detail with check-off, add items, swipe-to-delete
- Settings: profile card, sync now, sign out, delete account

### State coverage — every screen handles all four states
- Loading: CircularProgressIndicator with contextual message
- Error: ErrorState with retry, inline error banners with dismiss
- Empty: EmptyState with icon, title, subtitle, optional CTA
- Success: full content with pull-to-refresh

### Components (CommonComponents.kt)
- LoadingState, InlineLoading
- ErrorState (full-screen with retry)
- EmptyState (icon + title + subtitle + optional action)
- OfflineBanner (read-only mode indicator)
- SyncingIndicator (animated, non-blocking)
- PantreeSnackbarHost
- ConfirmDeleteDialog (human-readable copy)
- SectionHeader

### Data layer
- ApiModels.kt: all request/response DTOs
- NetworkResult<T>: sealed Success/Error/Loading wrapper
- safeApiCall: maps network exceptions to friendly errors
- Repositories: Auth, Pantry, Recipe, Shopping, Sync
- Room entities + DAOs for offline cache
- SyncRepository: full + delta sync with tombstone support

### Navigation
- Screen.kt: sealed class route definitions
- NavGraph.kt: PantreeNavHost (auth/main split) + MainScaffold (bottom nav)
- Bottom navigation: Pantry, Recipes, Lists, Settings

### Theme
- PantreeTheme: warm earthy palette (green primary, orange secondary)
- Light + dark color schemes
- Custom typography scale

### Tests
- AuthViewModelTest: signup, signin, duplicate, pending-deletion, password reset, clearError
- PantryViewModelTest: CRUD, duplicate conflict, offline snackbar vs error
- RecipesViewModelTest: filters, search, detail load, 404 handling, clearDetail
2026-05-10 05:09:35 +00:00

118 lines
3.6 KiB
Groovy

plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}
android {
namespace 'com.pantree.app'
compileSdk 34
defaultConfig {
applicationId "com.pantree.app"
minSdk 26
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.4'
}
packaging {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
// Core
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
implementation 'androidx.activity:activity-compose:1.8.2'
// Compose BOM
implementation platform('androidx.compose:compose-bom:2024.01.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material:material-icons-extended'
// Navigation
implementation 'androidx.navigation:navigation-compose:2.7.6'
// ViewModel + Lifecycle
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
// Hilt DI
implementation 'com.google.dagger:hilt-android:2.50'
kapt 'com.google.dagger:hilt-android-compiler:2.50'
implementation 'androidx.hilt:hilt-navigation-compose:1.1.0'
// Room
implementation 'androidx.room:room-runtime:2.6.1'
implementation 'androidx.room:room-ktx:2.6.1'
kapt 'androidx.room:room-compiler:2.6.1'
// Retrofit + OkHttp
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
// Security (EncryptedSharedPreferences)
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
// Google Sign-In
implementation 'com.google.android.gms:play-services-auth:20.7.0'
// Coil (image loading)
implementation 'io.coil-kt:coil-compose:2.5.0'
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
// DataStore
implementation 'androidx.datastore:datastore-preferences:1.0.0'
// Testing
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
testImplementation 'io.mockk:mockk:1.13.8'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation platform('androidx.compose:compose-bom:2024.01.00')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
}
kapt {
correctErrorTypes true
}