Commit graph

17 commits

Author SHA1 Message Date
Jens Reinemann
10d19f0321 feat(navigation): implement CRUD navigation and MainActivity integration
ui/navigation/Screen.kt:
- Sealed interface with @Serializable routes: ItemList, ItemForm,
  CategoryManagement, LocationManagement
- ItemForm accepts optional itemId for edit mode (type-safe navigation)

ui/navigation/KrisenvorratNavGraph.kt:
- NavHost with ItemList as start destination
- Screen wiring: ItemList -> ItemForm (create/edit), CategoryManagement,
  LocationManagement with back navigation via popBackStack()

ui/item/ItemListScreen.kt:
- Added onItemClick, onCategoriesClick, onLocationsClick callbacks
- TopAppBar MoreVert dropdown menu for category/location management
- ItemCard now clickable to navigate to edit mode

MainActivity.kt:
- Replaced placeholder with NavHost via KrisenvorratNavGraph
- rememberNavController() as root navigation controller

ui/navigation/ScreenTest.kt:
- 7 tests covering route instantiation, nullable itemId, equality

Closes #28
2026-05-14 01:20:54 +02:00
Jens Reinemann
f0ad946140 feat(item): add ItemFormViewModel and ItemFormScreen for create/edit
ItemFormViewModel:
- Create-Modus (new article) and Edit-Modus (load existing by ID via
  SavedStateHandle navigation argument)
- Form state with all ItemEntity fields as MutableStateFlow
- Validation: name required, quantity > 0, category and location required
- Save function (insert for create, update for edit)
- Loads categories and locations for dropdown selection

ItemFormScreen:
- OutlinedTextField for name, quantity, unit, price, kcal/100g,
  min stock, notes
- ExposedDropdownMenuBox for category and location selection
- Material 3 DatePickerDialog for expiry date (MHD)
- Inline validation error display per field
- Save button in TopAppBar, back navigation on successful save
- UUID generation for new articles

Tests:
- 18 unit tests covering create mode, edit mode, field updates,
  validation (all required fields), and save behavior (insert vs update)

Closes #27
2026-05-14 01:11:36 +02:00
Jens Reinemann
a1cd7e5199 feat(item): add ItemListScreen with grouped display and delete function
ui/item/ItemUiModel.kt:
- UI data class combining entity data with resolved category/location names
- Computed properties isExpired and isExpiringSoon for MHD color coding

ui/item/ItemListViewModel.kt:
- Combines ItemRepository, CategoryRepository, LocationRepository via Flow.combine
- Groups items by category name (sorted alphabetically)
- Delete flow with confirmation dialog state management

ui/item/ItemListScreen.kt:
- LazyColumn with category headers and Material 3 Cards per item
- Shows name, quantity+unit, location, and color-coded expiry date
- Delete via IconButton with AlertDialog confirmation
- Empty state when no items exist
- FAB with onAddItem navigation callback

ui/item/ItemListViewModelTest.kt:
- 9 unit tests covering init, grouping, name resolution,
  delete dialog flow, and alphabetical sorting

Closes #26
2026-05-14 01:03:37 +02:00
Jens Reinemann
a27660fd4a feat(ui): add category and location management screens
Closes #25

ui/category/:
- CategoryListViewModel: StateFlow-based ViewModel with add/delete
  dialog state management, backed by CategoryRepository
- CategoryListScreen: Material 3 Scaffold with LazyColumn, FAB for
  adding, delete confirmation dialog with CASCADE warning

ui/location/:
- LocationListViewModel: same pattern for LocationRepository
- LocationListScreen: same UI pattern for location management

Tests:
- CategoryListViewModelTest: 11 tests covering init, add, delete,
  dialog state, blank name rejection
- LocationListViewModelTest: 11 tests (same coverage)

Dependencies:
- Added lifecycle-runtime-compose for collectAsStateWithLifecycle
- Added kotlinx-coroutines-test for ViewModel unit tests
2026-05-14 00:56:36 +02:00
Jens Reinemann
0c1e06afca test: add unit tests for Room DAOs, LocalDateConverter, and JSON roundtrip
LocalDateConverterTest: added negative test for invalid string input
(DateTimeParseException).

CategoryDaoTest, LocationDaoTest: added getAll tests with multiple
entities to verify complete retrieval.

ItemDaoTest: fixed getExpiringSoon test (was calling non-existent
getExpiringSoon(Int) instead of getExpiringSoonByCutoff(LocalDate));
added getAll, getById positive, and getById negative tests.

JsonRoundtripTest (new): verifies lossless export-import roundtrip
with multiple items covering all fields, nullable fields (null
kcalPer100g, null expiryDate), and empty database edge case.

TestFakes (new): extracted shared Fake DAO implementations from
ImportExportRepositoryImplTest to avoid private class redeclaration
errors across test files in the same package.

Closes #22
2026-05-14 00:32:45 +02:00
Jens Reinemann
5825b0351c feat: JSON-Export & Import (Roundtrip-Serialisierung) #21
- ExportData/CategoryExport/LocationExport/ItemExport/SettingExport mit @Serializable
- ImportExportRepository-Interface (exportToJson/importFromJson: Result<Unit>)
- ImportExportRepositoryImpl mit atomarer Transaktion via DatabaseTransaction
- ignoreUnknownKeys=true + Versions-Check (version==1)
- @Upsert upsertAll() in CategoryDao, LocationDao, ItemDao, SettingsDao
- DI-Binding in RepositoryModule + DatabaseTransaction in DatabaseModule
- 5 Unit-Tests (29 passed total)
2026-05-14 00:20:04 +02:00
Jens Reinemann
388532c946 feat(export): add ImportExportRepository with JSON export/import
domain/repository/ImportExportRepository.kt: new interface with
exportToJson() and importFromJson(json) suspend functions.

data/export/ExportData.kt: serializable data class bundling all
entity lists for JSON serialization via kotlinx.serialization.

data/export/ImportExportRepositoryImpl.kt: implementation using
kotlinx.serialization + Dispatchers.IO; exportToJson fetches all
DAOs and serializes, importFromJson deserializes and upserts back.

data/db/dao/{Category,Item,Location,Settings}Dao.kt: added @Upsert
upsertAll() suspend function to each DAO to support bulk import.

di/RepositoryModule.kt: bound ImportExportRepositoryImpl to
ImportExportRepository via Hilt @Binds.

test/.../FakeXxxDao.kt: upsertAll() implemented in all four fake
DAOs for unit test coverage.
2026-05-14 00:09:07 +02:00
Jens Reinemann
4aba9f24a4 chore: Dokumentation, SKILL.md und Drawables aktualisieren 2026-05-13 23:56:56 +02:00
Jens Reinemann
95d8a10ed0 feat(repo): Repository-Schicht implementieren (#20)
- 4 Repository-Interfaces in domain/repository/ (Category, Location, Item, Settings)
- 4 Implementierungsklassen in data/repository/ mit Hilt @Inject
- RepositoryModule mit @Binds-Bindings fuer alle Repositories
- Datumslogik (getExpiringSoon) aus ItemDao in ItemRepositoryImpl verschoben
- 20 Unit-Tests mit Fake-DAOs (4 pro Repository)
2026-05-13 23:50:00 +02:00
Jens Reinemann
7380dbbdea feat(di): Add DatabaseModule with Hilt providers for Room DB and DAOs (#19)
- DatabaseModule: @Module + @InstallIn(SingletonComponent) with @Singleton-scoped
  Room.databaseBuilder provider and four @Provides methods for ItemDao,
  CategoryDao, LocationDao and SettingsDao
- DatabaseModuleTest: smoke-test verifies all four DAO providers return
  non-null objects using an in-memory Room database
2026-05-13 23:31:42 +02:00
Jens Reinemann
b719739451 feat(db): Room-Datenbank & DAOs implementieren (#18)
- KrisenvorratDatabase mit allen 4 Entities und LocalDateConverter
- CategoryDao, LocationDao, ItemDao, SettingsDao mit CRUD und Flow-Queries
- ItemDao.getExpiringSoon(daysUntil) als Default-Interface-Methode
- SettingsDao mit @Upsert (Room 2.6.1)
- Instrumentierungstests für alle 4 DAOs (in-memory DB)
- androidx.room:room-testing zu Dependencies ergänzt
2026-05-13 23:18:48 +02:00
Jens Reinemann
645a110297 feat(#17): Room-Entities & LocalDateConverter
- Add CategoryEntity, LocationEntity, SettingsEntity, ItemEntity
- ItemEntity: FK to Category+Location with CASCADE, indices on FK columns
- LocalDateConverter: LocalDate? <-> String? (ISO-8601) via @TypeConverter
- Add LocalDateConverterTest: 4 unit tests (null/non-null round-trip)
2026-05-13 22:57:43 +02:00
Jens Reinemann
22154cd5b8 chore: bump version to 1.2 (versionCode 3)
Verified via hot-reload workflow on running emulator.
UI shows 'Krisenvorrat' + 'v1.2' (confirmed via screenshot + uiautomator).

Closes #16
2026-05-13 22:33:24 +02:00
Jens Reinemann
6603016369 feat(skills): add hot-reload action and robust screenshot script
android-dev.ps1:
- Added 'hot-reload' action: build + force-stop + install + launch on
  a running emulator/device without restart (saves 60-90s vs deploy-emulator)
- Removed 'screenshot' action (replaced by standalone script)

screenshot.ps1 (new):
- Uses adb pull instead of exec-out pipe to avoid PowerShell's UTF-16
  CRLF corruption of binary data (root cause of all broken screenshots)
- Validates PNG magic bytes after capture
- ADB commands wrapped with configurable timeout (prevents hangs)
- Optional -UiDump flag extracts visible text via uiautomator for
  automated verification without image viewing

SKILL.md:
- Documented hot-reload action

app/build.gradle.kts:
- Version bump 1.0 → 1.1 (versionCode 1 → 2)
2026-05-13 22:27:06 +02:00
Jens Reinemann
c818b0d46e feat(ui): add version number to start screen
app/build.gradle.kts:
- Enabled buildConfig in buildFeatures to expose VERSION_NAME

app/src/main/java/de/krisenvorrat/app/MainActivity.kt:
- Replaced plain Text greeting with centered Column layout
- Shows app title 'Krisenvorrat' (headlineLarge) and version
  'v1.0' via BuildConfig.VERSION_NAME (bodyMedium, onSurfaceVariant)

Verified: built, deployed to emulator, and confirmed via screenshot.
2026-05-13 21:57:21 +02:00
Jens Reinemann
85f3084ffa fix: Build-Fehler beheben (gradle.properties, Theme, Icon) (#13)
- gradle.properties mit android.useAndroidX=true erstellt
- themes.xml: Parent-Theme auf android:Theme.Material.Light.NoActionBar geändert
- ic_launcher_background.xml: Ungültiges <rect> durch <path> ersetzt
2026-05-13 16:18:22 +02:00
Jens Reinemann
040f007cd5 feat: Android-Projekt-Gerüst anlegen (#13)
- Gradle Kotlin DSL (settings.gradle.kts, build.gradle.kts)
- Version Catalog (libs.versions.toml) mit Compose BOM, Hilt, Room,
  Navigation Compose, kotlinx.serialization
- App-Modul (app/build.gradle.kts), minSdk 26, compileSdk 35
- AndroidManifest.xml mit KrisenvorratApp + MainActivity
- KrisenvorratApp (@HiltAndroidApp)
- MainActivity (@AndroidEntryPoint, Jetpack Compose + Material3)
- KrisenvorratTheme (ui/theme/Theme.kt)
- MVVM-Paketstruktur: data/, domain/, presentation/, di/
- Adaptive Launcher-Icons (mipmap-anydpi-v26)
- Gradle Wrapper 8.11.1 (gradlew, gradlew.bat, gradle-wrapper.jar)
2026-05-13 15:24:39 +02:00