diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 506a388..7eab4f5 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -45,6 +45,10 @@ android {
buildFeatures {
compose = true
buildConfig = true
+ aidl = false
+ renderScript = false
+ resValues = true
+ shaders = false
}
composeOptions {
kotlinCompilerExtensionVersion = Versions.composeCompiler
@@ -65,6 +69,8 @@ dependencies {
implementation(project(":data"))
// [MODULE_DEPENDENCY] Domain module (transitively included via data, but explicit for clarity)
implementation(project(":domain"))
+ implementation(project(":ui"))
+ implementation(project(":feature:inventory"))
// [DEPENDENCY] AndroidX
implementation(Libs.coreKtx)
diff --git a/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt b/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt
index 24fe7b7..6cdfff4 100644
--- a/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt
+++ b/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt
@@ -15,7 +15,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.homebox.lens.ui.screen.dashboard.DashboardScreen
-import com.homebox.lens.ui.screen.inventorylist.InventoryListScreen
+import com.homebox.lens.feature.inventory.ui.InventoryScreen
import com.homebox.lens.ui.screen.itemdetails.ItemDetailsScreen
import com.homebox.lens.ui.screen.itemedit.ItemEditScreen
import com.homebox.lens.ui.screen.labelslist.LabelsListScreen
@@ -26,6 +26,8 @@ import com.homebox.lens.ui.screen.search.SearchScreen
import com.homebox.lens.ui.screen.setup.SetupScreen
import com.homebox.lens.ui.screen.settings.SettingsScreen
import com.homebox.lens.ui.screen.splash.SplashScreen
+import com.homebox.lens.navigation.NavigationActions
+import com.homebox.lens.ui.navigation.Screen
// [END_IMPORTS]
// [ENTITY: Function('NavGraph')]
@@ -59,7 +61,9 @@ fun NavGraph(
composable(route = Screen.Setup.route) {
SetupScreen(onSetupComplete = {
navController.navigate(Screen.Dashboard.route) {
- popUpTo(Screen.Setup.route) { inclusive = true }
+ popUpTo(Screen.Setup.route) {
+ inclusive = true
+ }
}
})
}
@@ -69,8 +73,8 @@ fun NavGraph(
navigationActions = navigationActions
)
}
- composable(route = Screen.InventoryList.route) {
- InventoryListScreen(
+ composable(route = Screen.Inventory.route) {
+ InventoryScreen(
currentRoute = currentRoute,
navigationActions = navigationActions
)
@@ -105,7 +109,7 @@ fun NavGraph(
navigationActions = navigationActions,
onLocationClick = { locationId ->
// [AI_NOTE]: Navigate to a pre-filtered inventory list screen
- navController.navigate(Screen.InventoryList.route)
+ navController.navigate(Screen.Inventory.route)
},
onAddNewLocationClick = {
navController.navigate(Screen.LocationEdit.createRoute("new"))
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt
deleted file mode 100644
index 331e62a..0000000
--- a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-// [FILE] InventoryListScreen.kt
-// [SEMANTICS] app, ui, screen, list
-
-package com.homebox.lens.ui.screen.inventorylist
-
-// [IMPORTS]
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.res.stringResource
-import com.homebox.lens.R
-import com.homebox.lens.navigation.NavigationActions
-import com.homebox.lens.ui.common.MainScaffold
-// [END_IMPORTS]
-
-// [ENTITY: Function('InventoryListScreen')]
-// [RELATION: Function('InventoryListScreen')] -> [DEPENDS_ON] -> [Class('NavigationActions')]
-// [RELATION: Function('InventoryListScreen')] -> [CALLS] -> [Function('MainScaffold')]
-/**
- * @summary Composable function for the "Inventory List" screen.
- * @param currentRoute The current route to highlight the active item in the Drawer.
- * @param navigationActions The object with navigation actions.
- */
-@Composable
-fun InventoryListScreen(
- currentRoute: String?,
- navigationActions: NavigationActions
-) {
- MainScaffold(
- topBarTitle = stringResource(id = R.string.inventory_list_title),
- currentRoute = currentRoute,
- navigationActions = navigationActions
- ) {
- // [AI_NOTE]: Implement Inventory List Screen UI
- Text(text = "Inventory List Screen")
- }
-}
-// [END_ENTITY: Function('InventoryListScreen')]
-// [END_FILE_InventoryListScreen.kt]
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt b/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt
deleted file mode 100644
index 7c00c57..0000000
--- a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-// [FILE] InventoryListViewModel.kt
-// [SEMANTICS] app, ui, viewmodel, list
-package com.homebox.lens.ui.screen.inventorylist
-
-// [IMPORTS]
-import androidx.lifecycle.ViewModel
-import dagger.hilt.android.lifecycle.HiltViewModel
-import javax.inject.Inject
-// [END_IMPORTS]
-
-// [ENTITY: ViewModel('InventoryListViewModel')]
-/**
- * @summary ViewModel for the inventory list screen.
- */
-@HiltViewModel
-class InventoryListViewModel @Inject constructor() : ViewModel() {
- // [AI_NOTE]: Implement UI state
-}
-// [END_ENTITY: ViewModel('InventoryListViewModel')]
-// [END_FILE_InventoryListViewModel.kt]
\ No newline at end of file
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt
index 71552ac..0aa08c2 100644
--- a/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt
+++ b/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt
@@ -36,7 +36,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.homebox.lens.R
import com.homebox.lens.domain.model.Label
import com.homebox.lens.navigation.NavigationActions
-import com.homebox.lens.navigation.Screen
+import com.homebox.lens.ui.navigation.Screen
import com.homebox.lens.ui.common.MainScaffold
import timber.log.Timber
// [END_IMPORTS]
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt
index 4fd5277..f7908be 100644
--- a/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt
+++ b/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt
@@ -12,7 +12,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
-import com.homebox.lens.navigation.Screen
+import com.homebox.lens.ui.navigation.Screen
import com.homebox.lens.ui.screen.setup.SetupViewModel
import timber.log.Timber
// [END_IMPORTS]
@@ -50,7 +50,9 @@ fun SplashScreen(
}
navController.navigate(destination) {
- popUpTo(Screen.Splash.route) { inclusive = true }
+ popUpTo(Screen.Splash.route) {
+ inclusive = true
+ }
}
}
}
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
deleted file mode 100644
index 2501676..0000000
--- a/app/src/main/res/values-en/strings.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-
- Homebox Lens
-
-
- Create
- Edit
- Delete
- Search
- Logout
- No location
- Items not found
- Failed to load data. Please try again.
-
-
- Open navigation drawer
- Scan QR code
- Navigate back
- Add new location
- Add new label
-
-
- Dashboard
- Quick Stats
- Recently Added
- Locations
- Labels
- %1$s (%2$d)
-
-
- Total Items
- Total Value
- Total Labels
- Total Locations
-
-
- Locations
- Labels
-
-
- Inventory
-
-
- Details
- Edit Item
- Labels
- Locations
- Search
-
- Save
- Name
- Description
- Quantity
-
-
- Create Location
- Edit Location
-
-
- Locations not found. Press + to add a new one.
- Items: %1$d
- More options
-
-
- Server Setup
- Server URL
- Username
- Password
- Connect
-
-
- Labels
- Navigate back
- Create new label
- Label icon
- No labels found.
- Create Label
- Label Name
- Create
- Cancel
-
-
-
-
- Sync inventory
-
-
- Edit item
- Delete item
- Description
- No description
- Details
- Quantity
- Location
- Labels
-
-
- Create item
- Save item
- Name
- Description
-
-
- Search items...
-
-
- Setup
-
-
- Create label
- Edit label
- Label name
-
-
- Back
- Save
-
-
- Color
- HEX color code
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 69c387d..c5bfe8b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,86 +2,112 @@
Homebox Lens
- Создать
- Редактировать
- Удалить
- Поиск
- Выйти
- Нет локации
- Элементы не найдены
- Не удалось загрузить данные. Пожалуйста, попробуйте еще раз.
+ Create
+ Edit
+ Delete
+ Search
+ Logout
+ No location
+ Items not found
+ Failed to load data. Please try again.
- Открыть боковое меню
- Enter your Homebox server details to connect.
- Сканировать QR-код
- Вернуться назад
- Добавить новую локацию
- Добавить новую метку
-
-
- Синхронизировать инвентарь
-
-
- Редактировать элемент
- Удалить элемент
- Описание
- Нет описания
- Детали
- Количество
- Местоположение
- Метки
-
-
- Создать элемент
- Сохранить элемент
- Название
-
-
- Поиск элементов...
+ Open navigation drawer
+ Scan QR code
+ Navigate back
+ Add new location
+ Add new label
- Главная
- Быстрая статистика
- Недавно добавлено
- Места хранения
- Метки
+ Dashboard
+ Quick Stats
+ Recently Added
+ Locations
+ Labels
%1$s (%2$d)
- Всего вещей
- Общая стоимость
- Всего меток
- Всего локаций
+ Total Items
+ Total Value
+ Total Labels
+ Total Locations
- Локации
- Метки
+ Locations
+ Labels
- Инвентарь
- Детали
- Редактирование
- Метки
- Места хранения
- Поиск
+ Inventory
+
+
+ Details
+ Edit Item
+ Labels
+ Locations
+ Search
+
+ Save
+ Name
+ Description
+ Quantity
+
+
+ Create Location
+ Edit Location
+
+
+ Locations not found. Press + to add a new one.
+ Items: %1$d
+ More options
+
+
+ Server Setup
+ Server URL
+ Username
+ Password
+ Connect
+
+
+ Labels
+ Navigate back
+ Create new label
+ Label icon
+ No labels found.
+ Create Label
+ Label Name
+ Create
+ Cancel
+
+
+ Sync inventory
+
+
+ Edit item
+ Delete item
+ Description
+ No description
+ Details
+ Quantity
+ Location
+ Labels
+
+
+ Create item
+ Save item
+ Name
+ Description
- Сохранить
- Название
- Описание
- Количество
General Information
Location
- Select Location
Labels
Select Labels
+ OK
+ Cancel
Purchase Information
Purchase Price
Purchase From
- Purchase Date
+ Purchase Time
Select Date
- OK
- Cancel
Warranty Information
Lifetime Warranty
Warranty Details
@@ -99,50 +125,26 @@
Sold Price
Sold To
Sold Notes
- Sold Date
+ Sold Time
-
- Создать локацию
- Редактировать локацию
-
-
- Местоположения не найдены. Нажмите +, чтобы добавить новое.
- Предметов: %1$d
- Больше опций
+
+ Search items...
- Настройка
- Настройка сервера
- URL сервера
- Имя пользователя
- Пароль
- Подключиться
-
-
- Метки
-
- Настройки
- Вернуться назад
- Создать новую метку
- Иконка метки
- Метки не найдены.
- Создать метку
- Название метки
- Создать
- Отмена
+ Setup
+ Settings
- Создать метку
- Редактировать метку
- Название метки
- Описание
+ Create label
+ Edit label
+ Label name
- Назад
- Сохранить
-
+ Back
+ Save
- Цвет
- HEX-код цвета
-
+ Color
+ HEX color code
+
+
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt
index dad9d64..c70fa19 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt
@@ -19,10 +19,10 @@ data class ItemSummaryDto(
@Json(name = "name") val name: String,
@Json(name = "assetId") val assetId: String?,
@Json(name = "image") val image: ImageDto?,
- @Json(name = "isArchived") val isArchived: Boolean,
+ @Json(name = "isArchived") val isArchived: Boolean? = false,
@Json(name = "labels") val labels: List,
@Json(name = "location") val location: LocationOutDto?,
- @Json(name = "value") val value: Double,
+ @Json(name = "value") val value: Double? = 0.0,
@Json(name = "createdAt") val createdAt: String,
@Json(name = "updatedAt") val updatedAt: String
)
@@ -39,10 +39,10 @@ fun ItemSummaryDto.toDomain(): ItemSummary {
name = this.name,
assetId = this.assetId,
image = this.image?.toDomain(),
- isArchived = this.isArchived,
+ isArchived = this.isArchived ?: false,
labels = this.labels.map { it.toDomain() },
location = this.location?.toDomain(),
- value = this.value,
+ value = this.value ?: 0.0,
createdAt = this.createdAt,
updatedAt = this.updatedAt
)
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt
index 330a35b..3c9c16a 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt
@@ -16,9 +16,9 @@ data class LocationOutDto(
@Json(name = "name")
val name: String,
@Json(name = "color")
- val color: String?,
+ val color: String? = "#000000",
@Json(name = "isArchived")
- val isArchived: Boolean?,
+ val isArchived: Boolean? = false,
@Json(name = "createdAt")
val createdAt: String,
@Json(name = "updatedAt")
diff --git a/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt b/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt
index 6a73bd2..9edb50c 100644
--- a/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt
+++ b/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt
@@ -103,10 +103,10 @@ fun ItemSummaryDto.toDomain(): DomainItemSummary {
name = this.name,
assetId = this.assetId,
image = this.image?.toDomain(),
- isArchived = this.isArchived,
+ isArchived = this.isArchived ?: false,
labels = this.labels.map { it.toDomain() },
location = this.location?.toDomain(),
- value = this.value,
+ value = this.value ?: 0.0,
createdAt = this.createdAt,
updatedAt = this.updatedAt
)
diff --git a/domain/src/main/java/com/homebox/lens/domain/model/Result.kt b/domain/src/main/java/com/homebox/lens/domain/model/Result.kt
index 448b23a..02604d9 100644
--- a/domain/src/main/java/com/homebox/lens/domain/model/Result.kt
+++ b/domain/src/main/java/com/homebox/lens/domain/model/Result.kt
@@ -21,7 +21,7 @@ sealed class Result {
* @summary Представляет собой неуспешный результат операции.
* @param exception Исключение, которое произошло во время операции.
*/
- data class Error(val exception: Exception) : Result()
+ data class Error(val exception: kotlin.Exception) : Result()
// [END_ENTITY: DataClass('Error')]
}
// [END_ENTITY: SealedClass('Result')]
diff --git a/domain/src/main/java/com/homebox/lens/domain/model/ResultExtensions.kt b/domain/src/main/java/com/homebox/lens/domain/model/ResultExtensions.kt
new file mode 100644
index 0000000..b5004cb
--- /dev/null
+++ b/domain/src/main/java/com/homebox/lens/domain/model/ResultExtensions.kt
@@ -0,0 +1,23 @@
+// [FILE] ResultExtensions.kt
+// [SEMANTICS] domain, model, result, extensions
+package com.homebox.lens.domain.model
+
+// [ENTITY: Function('fold')]
+/**
+ * @summary Extension function to handle success and failure cases of a Result.
+ * @param onSuccess The function to be called if the Result is Success.
+ * @param onFailure The function to be called if the Result is Error.
+ * @return The result of either onSuccess or onFailure.
+ * @param R The return type of the fold operation.
+ */
+inline fun Result.fold(
+ onSuccess: (value: T) -> R,
+ onFailure: (exception: Exception) -> R
+): R {
+ return when (this) {
+ is Result.Success -> onSuccess(data)
+ is Result.Error -> onFailure(exception)
+ }
+}
+// [END_ENTITY: Function('fold')]
+// [END_FILE_ResultExtensions.kt]
\ No newline at end of file
diff --git a/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt b/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt
index ea0afbd..5a2265b 100644
--- a/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt
+++ b/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt
@@ -6,6 +6,7 @@ package com.homebox.lens.domain.usecase
// [IMPORTS]
import com.homebox.lens.domain.model.ItemSummary
import com.homebox.lens.domain.model.PaginationResult
+import com.homebox.lens.domain.model.Result
import com.homebox.lens.domain.repository.ItemRepository
import javax.inject.Inject
// [END_IMPORTS]
@@ -23,10 +24,14 @@ class SearchItemsUseCase @Inject constructor(
/**
* @summary Executes the search operation.
* @param query The search query.
- * @return A pagination result object.
+ * @return A Result object encapsulating either a successful PaginationResult or an Error.
*/
- suspend operator fun invoke(query: String): PaginationResult {
- return itemRepository.searchItems(query)
+ suspend operator fun invoke(query: String): Result> {
+ return try {
+ Result.Success(itemRepository.searchItems(query))
+ } catch (e: Exception) {
+ Result.Error(e)
+ }
}
// [END_ENTITY: Function('invoke')]
}
diff --git a/feature/inventory/build.gradle.kts b/feature/inventory/build.gradle.kts
new file mode 100644
index 0000000..03d31ca
--- /dev/null
+++ b/feature/inventory/build.gradle.kts
@@ -0,0 +1,59 @@
+// [FILE] feature/inventory/build.gradle.kts
+// [SEMANTICS] build, dependencies
+plugins {
+ id("com.android.library")
+ id("org.jetbrains.kotlin.android")
+ id("kotlin-kapt")
+ id("dagger.hilt.android.plugin")
+}
+
+android {
+ namespace = "com.homebox.lens.feature.inventory"
+ compileSdk = Versions.compileSdk
+
+ defaultConfig {
+ minSdk = Versions.minSdk
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+ buildFeatures {
+ compose = true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.composeCompiler
+ }
+}
+
+dependencies {
+ implementation(project(":domain"))
+ implementation(project(":ui"))
+
+ // AndroidX & Lifecycle
+ implementation(Libs.coreKtx)
+ implementation(Libs.lifecycleRuntime)
+ implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
+
+ // Compose
+ implementation(platform(Libs.composeBom))
+ implementation(Libs.composeUi)
+ implementation(Libs.composeUiGraphics)
+ implementation(Libs.composeUiToolingPreview)
+ implementation(Libs.composeMaterial3)
+ implementation(Libs.navigationCompose)
+ implementation(Libs.hiltNavigationCompose)
+
+ // Hilt
+ implementation(Libs.hiltAndroid)
+ kapt(Libs.hiltCompiler)
+
+ // Other
+ implementation(Libs.timber)
+ implementation("io.coil-kt:coil-compose:2.4.0")
+}
+// [END_FILE_feature/inventory/build.gradle.kts]
\ No newline at end of file
diff --git a/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryScreen.kt b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryScreen.kt
new file mode 100644
index 0000000..e993ba7
--- /dev/null
+++ b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryScreen.kt
@@ -0,0 +1,160 @@
+// [FILE] InventoryScreen.kt
+// [SEMANTICS] ui, screen, list, compose
+package com.homebox.lens.feature.inventory.ui
+
+// [IMPORTS]
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.Card
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.hilt.navigation.compose.hiltViewModel
+import coil.compose.AsyncImage
+import coil.request.ImageRequest
+import com.homebox.lens.domain.model.ItemSummary
+import com.homebox.lens.navigation.NavigationActions
+import com.homebox.lens.ui.navigation.Screen
+import com.homebox.lens.ui.R // Import R from ui module
+import com.homebox.lens.ui.common.MainScaffold
+// [END_IMPORTS]
+
+// [ENTITY: Function('InventoryScreen')]
+// [RELATION: Function('InventoryScreen')] -> [DEPENDS_ON] -> [Class('NavigationActions')]
+// [RELATION: Function('InventoryScreen')] -> [CALLS] -> [Function('MainScaffold')]
+// [RELATION: Function('InventoryScreen')] -> [CONSUMES_STATE] -> [ViewModel('InventoryViewModel')]
+/**
+ * @summary Composable function for the "Inventory" screen.
+ * @param currentRoute The current route to highlight the active item in the Drawer.
+ * @param navigationActions The object with navigation actions.
+ * @param viewModel The ViewModel for this screen.
+ */
+@Composable
+fun InventoryScreen(
+ currentRoute: String?,
+ navigationActions: NavigationActions,
+ viewModel: InventoryViewModel = hiltViewModel()
+) {
+ val uiState by viewModel.uiState.collectAsState()
+
+ MainScaffold(
+ topBarTitle = stringResource(id = R.string.inventory_list_title),
+ currentRoute = currentRoute,
+ navigationActions = navigationActions
+ ) { innerPadding ->
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(innerPadding),
+ contentAlignment = Alignment.Center
+ ) {
+ when (val state = uiState) {
+ is InventoryUiState.Loading -> CircularProgressIndicator()
+ is InventoryUiState.Success -> InventoryList(
+ items = state.items,
+ onItemClick = { itemId ->
+ navigationActions.navigateToItemDetails(itemId)
+ }
+ )
+ is InventoryUiState.Error -> Text(text = state.message)
+ }
+ }
+ }
+}
+// [END_ENTITY: Function('InventoryScreen')]
+
+// [ENTITY: Function('InventoryList')]
+// [RELATION: Function('InventoryList')] -> [DEPENDS_ON] -> [DataClass('ItemSummary')]
+// [RELATION: Function('InventoryList')] -> [CALLS] -> [Function('ItemRow')]
+/**
+ * @summary Displays a list of inventory items.
+ * @param items The list of items to display.
+ * @param onItemClick Callback invoked when an item is clicked.
+ */
+@Composable
+private fun InventoryList(
+ items: List,
+ onItemClick: (String) -> Unit
+) {
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ contentPadding = PaddingValues(8.dp)
+ ) {
+ items(items) { item ->
+ ItemRow(item = item, onItemClick = onItemClick)
+ }
+ }
+}
+// [END_ENTITY: Function('InventoryList')]
+
+// [ENTITY: Function('ItemRow')]
+// [RELATION: Function('ItemRow')] -> [DEPENDS_ON] -> [DataClass('ItemSummary')]
+/**
+ * @summary Displays a single row in the inventory list.
+ * @param item The item to display.
+ * @param onItemClick Callback invoked when the row is clicked.
+ */
+@Composable
+private fun ItemRow(
+ item: ItemSummary,
+ onItemClick: (String) -> Unit
+) {
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 4.dp)
+ .clickable { onItemClick(item.id) },
+ ) {
+ Row(
+ modifier = Modifier.padding(8.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ AsyncImage(
+ model = ImageRequest.Builder(LocalContext.current)
+ .data(item.image?.path)
+ .crossfade(true)
+ .build(),
+ placeholder = painterResource(R.drawable.ic_placeholder),
+ error = painterResource(R.drawable.ic_placeholder),
+ contentDescription = item.name,
+ contentScale = ContentScale.Crop,
+ modifier = Modifier.size(64.dp)
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Column(modifier = Modifier.weight(1f)) {
+ Text(
+ text = item.name,
+ style = MaterialTheme.typography.titleMedium,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ item.location?.let {
+ Text(
+ text = it.name,
+ style = MaterialTheme.typography.bodySmall,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ }
+ // [AI_NOTE]: Quantity is not present in ItemSummary, so it's omitted for now.
+ // Placeholder: quantity will be added later when ItemSummary is updated to include it.
+ }
+ }
+}
+// [END_ENTITY: Function('ItemRow')]
+
+// [END_FILE_InventoryScreen.kt]
\ No newline at end of file
diff --git a/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryUiState.kt b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryUiState.kt
new file mode 100644
index 0000000..a2fc4e3
--- /dev/null
+++ b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryUiState.kt
@@ -0,0 +1,40 @@
+// [FILE] InventoryUiState.kt
+// [SEMANTICS] ui, state_management, sealed_state
+package com.homebox.lens.feature.inventory.ui
+
+// [IMPORTS]
+import com.homebox.lens.domain.model.ItemSummary
+// [END_IMPORTS]
+
+// [ENTITY: SealedInterface('InventoryUiState')]
+/**
+ * @summary Represents the different states of the Inventory screen.
+ * @invariant Only one state can be active at a time.
+ */
+sealed interface InventoryUiState {
+ // [END_ENTITY: SealedInterface('InventoryUiState')]
+
+ // [ENTITY: Object('Loading')]
+ /**
+ * @summary Represents the loading state, where the list of items is being fetched.
+ */
+ object Loading : InventoryUiState
+ // [END_ENTITY: Object('Loading')]
+
+ // [ENTITY: DataClass('Success')]
+ /**
+ * @summary Represents the success state, where the list of items is available.
+ * @param items The list of inventory items.
+ */
+ data class Success(val items: List) : InventoryUiState
+ // [END_ENTITY: DataClass('Success')]
+
+ // [ENTITY: DataClass('Error')]
+ /**
+ * @summary Represents the error state, where an error occurred while fetching items.
+ * @param message The error message.
+ */
+ data class Error(val message: String) : InventoryUiState
+ // [END_ENTITY: DataClass('Error')]
+}
+// [END_FILE_InventoryUiState.kt]
\ No newline at end of file
diff --git a/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryViewModel.kt b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryViewModel.kt
new file mode 100644
index 0000000..67e5d62
--- /dev/null
+++ b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryViewModel.kt
@@ -0,0 +1,77 @@
+// [FILE] InventoryViewModel.kt
+// [SEMANTICS] ui, viewmodel, state_management
+package com.homebox.lens.feature.inventory.ui
+
+// [IMPORTS]
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.homebox.lens.domain.usecase.SearchItemsUseCase
+import com.homebox.lens.domain.model.PaginationResult
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import timber.log.Timber
+import com.homebox.lens.domain.model.fold
+import javax.inject.Inject
+// [END_IMPORTS]
+
+// [ENTITY: ViewModel('InventoryViewModel')]
+// [RELATION: ViewModel('InventoryViewModel')] -> [DEPENDS_ON] -> [UseCase('SearchItemsUseCase')]
+// [RELATION: ViewModel('InventoryViewModel')] -> [EMITS_STATE] -> [SealedInterface('InventoryUiState')]
+/**
+ * @summary ViewModel for the Inventory screen.
+ * @param searchItemsUseCase The use case to search for inventory items.
+ * @invariant The ViewModel manages the UI state and business logic for the inventory screen.
+ */
+@HiltViewModel
+class InventoryViewModel @Inject constructor(
+ private val searchItemsUseCase: SearchItemsUseCase
+) : ViewModel() {
+
+ // [ENTITY: DataStructure('uiState')]
+ private val _uiState = MutableStateFlow(InventoryUiState.Loading)
+ val uiState: StateFlow = _uiState.asStateFlow()
+ // [END_ENTITY: DataStructure('uiState')]
+
+ init {
+ fetchInventoryItems()
+ }
+
+ // [ENTITY: Function('fetchInventoryItems')]
+ // [RELATION: Function('fetchInventoryItems')] -> [CALLS] -> [UseCase('SearchItemsUseCase')]
+ // [RELATION: Function('fetchInventoryItems')] -> [MODIFIES_STATE_OF] -> [DataStructure('uiState')]
+ /**
+ * @summary Fetches the list of inventory items.
+ * @sideeffect Updates the `uiState` with the result of the operation.
+ */
+ private fun fetchInventoryItems() {
+ viewModelScope.launch {
+ _uiState.value = InventoryUiState.Loading
+ Timber.d("[DEBUG][INVENTORY_VIEW_MODEL][FETCH_START] Fetching inventory items.")
+ try {
+ val result = searchItemsUseCase(query = "")
+
+ result.fold(
+ onSuccess = { paginationResult ->
+ @Suppress("UNCHECKED_CAST")
+ val items = paginationResult.items as List
+ _uiState.value = InventoryUiState.Success(items)
+ Timber.i("[INFO][INVENTORY_VIEW_MODEL][FETCH_SUCCESS] Successfully fetched %d items.", items.size)
+ },
+ onFailure = { throwable: Exception ->
+ _uiState.value = InventoryUiState.Error(throwable.message ?: "Unknown error")
+ Timber.e(throwable, "[ERROR][INVENTORY_VIEW_MODEL][FETCH_FAILURE] Error fetching inventory items: %s", throwable.message)
+ }
+ )
+ } catch (e: Exception) {
+ _uiState.value = InventoryUiState.Error(e.message ?: "An unexpected error occurred")
+ Timber.e(e, "[ERROR][INVENTORY_VIEW_MODEL][FETCH_UNEXPECTED] Unexpected error fetching inventory items: %s", e.message)
+ }
+ }
+ }
+ // [END_ENTITY: Function('fetchInventoryItems')]
+}
+// [END_ENTITY: ViewModel('InventoryViewModel')]
+// [END_FILE_InventoryViewModel.kt]
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 9f9a3fb..3535841 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,6 +21,8 @@ rootProject.name = "HomeboxLens"
include(":app")
include(":data")
include(":domain")
+include(":ui")
+include(":feature:inventory")
+include(":data:semantic-ktlint-rules")
// [END_FILE_settings.gradle.kts]
-include(":data:semantic-ktlint-rules")
diff --git a/tasks/20251005_migrate_moshi_to_ksp.xml b/tasks/20251005_migrate_moshi_to_ksp.xml
deleted file mode 100644
index 1c04347..0000000
--- a/tasks/20251005_migrate_moshi_to_ksp.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-
- Миграция Moshi с Kapt на KSP
-
- Устранить предупреждение "Kapt support in Moshi Kotlin Code Gen is deprecated".
- Это требует миграции генерации кода Moshi с `kapt` на `KSP` (Kotlin Symbol Processing).
-
-
-
- Добавить плагин KSP в корневой файл `build.gradle.kts`.
-
- apply_diff
-
-
- build.gradle.kts
-
-
- >>>>>> REPLACE
-]]>
-
- 9
-
-
-
-
-
-
- Применить плагин KSP и заменить зависимость `kapt` на `ksp` для Moshi в файле `data/build.gradle.kts`.
-
- apply_diff
-
-
- data/build.gradle.kts
-
-
- >>>>>> REPLACE
-]]>
-
- 6
-
-
-
- >>>>>> REPLACE
-]]>
-
- 53
-
-
-
-
-
-
-
-]]>
\ No newline at end of file
diff --git a/tasks/20251005_remove_package_from_manifest.xml b/tasks/20251005_remove_package_from_manifest.xml
deleted file mode 100644
index 569ee11..0000000
--- a/tasks/20251005_remove_package_from_manifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
- Удаление атрибута package из AndroidManifest.xml
-
- Устранить предупреждение "Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported".
- Это требует удаления устаревшего атрибута `package` из файла `app/src/main/AndroidManifest.xml`.
-
-
-
- Удалить атрибут `package` из тега `manifest` в файле `app/src/main/AndroidManifest.xml`.
-
- apply_diff
-
-
- app/src/main/AndroidManifest.xml
-
-
-
-=======
-
->>>>>>> REPLACE
-]]>
-
- 2
-
-
-
-
-
-
-
-]]>
\ No newline at end of file
diff --git a/tasks/20251005_update_gradle_and_java.xml b/tasks/20251005_update_gradle_and_java.xml
deleted file mode 100644
index f7f9788..0000000
--- a/tasks/20251005_update_gradle_and_java.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-
- Устранение предупреждений сборки Gradle
-
- Необходимо устранить два типа предупреждений, возникающих при сборке проекта:
- 1. Использование устаревшего метода `Configuration.fileCollection(Spec)` в плагине `org.jetbrains.kotlin.android`.
- 2. Использование устаревшей версии Java 8 для компиляции.
-
-
-
- Обновить версию Android Gradle Plugin (AGP) и плагина Kotlin в корневом файле `build.gradle.kts`.
-
- apply_diff
-
-
- build.gradle.kts
-
-
- >>>>>> REPLACE
-]]>
-
- 5
-
-
-
-
-
-
- Обновить версию Java до 17 в файлах сборки всех модулей. Начать с `data/build.gradle.kts`.
-
- apply_diff
-
-
- data/build.gradle.kts
-
-
- >>>>>> REPLACE
-]]>
-
- 29
-
-
-
-
-
-
- Применить аналогичные изменения для `app/build.gradle.kts` и других модулей. (Примечание: этот шаг потребует поиска и изменения всех `build.gradle.kts` файлов в проекте).
-
- search_files
-
- .
- build\.gradle\.kts
-
-
-
-
-
-]]>
\ No newline at end of file
diff --git a/tasks/20251006_add_missing_string_resources.xml b/tasks/20251006_add_missing_string_resources.xml
new file mode 100644
index 0000000..a41a4c4
--- /dev/null
+++ b/tasks/20251006_add_missing_string_resources.xml
@@ -0,0 +1,65 @@
+
+
+ 20251006_add_missing_string_resources
+ Architect
+ 2025-10-06T06:05:22Z
+ Homebox-Lens
+ Add Missing String Resources to Resolve Build Failure
+
+ The project build is currently failing due to multiple 'Unresolved reference' errors in `ItemEditScreen.kt` and `SettingsScreen.kt`. These errors are caused by missing string resources. To fix this, the specified string resources must be added to the `app/src/main/res/values/strings.xml` file.
+
+
+ app/src/main/res/values/strings.xml
+
+
+ - The project must compile successfully without any 'Unresolved reference' errors related to string resources.
+ - All new strings must be added to `app/src/main/res/values/strings.xml`.
+ - The new strings should have meaningful English values.
+
+
+ - Changes should be limited to the `app/src/main/res/values/strings.xml` file. No other files should be modified unless absolutely necessary to resolve the primary issue.
+
+
+ app/src/main/res/values/strings.xml
+
+
+
+ The new strings are for the item editing screen and settings screen. The text should be clear and concise.
+
+
+ The following string resources are missing and must be added to `app/src/main/res/values/strings.xml`:
+ - `item_edit_general_information`
+ - `item_edit_location`
+ - `item_edit_labels`
+ - `item_edit_select_labels`
+ - `dialog_ok`
+ - `dialog_cancel`
+ - `item_edit_purchase_information`
+ - `item_edit_purchase_price`
+ - `item_edit_purchase_from`
+ - `item_edit_purchase_time`
+ - `item_edit_select_date`
+ - `item_edit_warranty_information`
+ - `item_edit_lifetime_warranty`
+ - `item_edit_warranty_details`
+ - `item_edit_warranty_expires`
+ - `item_edit_identification`
+ - `item_edit_asset_id`
+ - `item_edit_serial_number`
+ - `item_edit_manufacturer`
+ - `item_edit_model_number`
+ - `item_edit_status_notes`
+ - `item_edit_archived`
+ - `item_edit_insured`
+ - `item_edit_notes`
+ - `item_edit_sold_information`
+ - `item_edit_sold_price`
+ - `item_edit_sold_to`
+ - `item_edit_sold_notes`
+ - `item_edit_sold_time`
+ - `screen_title_settings`
+
+
+
+]]>
\ No newline at end of file
diff --git a/tasks/work_order_inventory_screen.xml b/tasks/work_order_inventory_screen.xml
deleted file mode 100644
index 6e27d00..0000000
--- a/tasks/work_order_inventory_screen.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
- 1
- 25
-
-
- filesystem
-
- tasks/temp
-
-
-
-
-
- xml_file
-
- logs/metrics
-
-
-
-
-
- xml_file
-
- logs/main
-
-
-
-
-
- Создать полнофункциональный экран "Inventory", который будет отображать список предметов инвентаря. Экран должен использовать существующую архитектуру и компоненты.
-
-
-
- Linux
- /usr/bin/zsh
-
-
- Homebox Lens
- Android (Jetpack Compose)
- Kotlin
- Gradle
- MVVM, Clean Architecture
-
-
-
-
- domain/src/main/java/com/homebox/lens/domain/model/ItemSummary.kt
-
-
- app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt
-
-
-
-
- Создан новый Gradle-модуль `feature:inventory`.
-
-
- В модуле `feature:inventory` реализован `InventoryScreen`, `InventoryViewModel` и `InventoryUiState`.
-
-
- `InventoryViewModel` использует `SearchItemsUseCase` для получения списка предметов.
-
-
- `InventoryScreen` отображает список предметов, используя `ItemSummary` в качестве модели представления для каждого элемента списка.
-
-
- Новый экран интегрирован в навигацию приложения.
-
-
- Весь новый код соответствует стайлгайду проекта и семантически корректен.
-
-
-
-
- Создание модуля
- Создать новый feature-модуль с именем `inventory`.
-
-
- Реализация ViewModel
- Создать `InventoryViewModel` который будет запрашивать данные из `SearchItemsUseCase` и управлять состоянием экрана `InventoryUiState`.
-
-
- Реализация UI
- Создать `InventoryScreen`, который будет отображать список `ItemSummary` из `InventoryUiState`. Для каждого элемента списка создать `ItemRow` composable.
-
-
- Интеграция навигации
- Добавить `InventoryScreen` в граф навигации приложения.
-
-
- Рефакторинг
- Удалить старый `InventoryListScreen` из `app` модуля, если он больше не нужен.
-
-
-
\ No newline at end of file
diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts
new file mode 100644
index 0000000..fc00fe4
--- /dev/null
+++ b/ui/build.gradle.kts
@@ -0,0 +1,55 @@
+// [FILE] ui/build.gradle.kts
+// [SEMANTICS] build, dependencies, ui
+plugins {
+ id("com.android.library")
+ id("org.jetbrains.kotlin.android")
+ id("kotlin-kapt") // Add kapt for Hilt
+}
+
+android {
+ namespace = "com.homebox.lens.ui"
+ compileSdk = Versions.compileSdk
+
+ defaultConfig {
+ minSdk = Versions.minSdk
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+ buildFeatures {
+ compose = true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.composeCompiler
+ }
+}
+
+dependencies {
+ // AndroidX
+ implementation(Libs.coreKtx)
+ implementation(Libs.lifecycleRuntime) // For androidx.lifecycle:lifecycle-runtime-ktx
+
+ // Compose
+ implementation(platform(Libs.composeBom))
+ implementation(Libs.composeUi)
+ implementation(Libs.composeUiGraphics)
+ implementation(Libs.composeUiToolingPreview)
+ implementation(Libs.composeMaterial3)
+ implementation(Libs.activityCompose)
+ implementation("androidx.compose.material:material-icons-extended-android:1.6.8")
+ implementation(Libs.navigationCompose) // For NavigationActions
+ implementation(Libs.hiltNavigationCompose) // For Hilt with Compose
+
+ // Hilt
+ implementation(Libs.hiltAndroid)
+ kapt(Libs.hiltCompiler)
+
+ // Other
+ implementation(Libs.timber)
+}
+// [END_FILE_ui/build.gradle.kts]
\ No newline at end of file
diff --git a/app/src/main/java/com/homebox/lens/navigation/NavigationActions.kt b/ui/src/main/java/com/homebox/lens/navigation/NavigationActions.kt
similarity index 81%
rename from app/src/main/java/com/homebox/lens/navigation/NavigationActions.kt
rename to ui/src/main/java/com/homebox/lens/navigation/NavigationActions.kt
index 24e80f7..08a666d 100644
--- a/app/src/main/java/com/homebox/lens/navigation/NavigationActions.kt
+++ b/ui/src/main/java/com/homebox/lens/navigation/NavigationActions.kt
@@ -1,10 +1,11 @@
// [FILE] NavigationActions.kt
-// [SEMANTICS] app, ui, navigation, actions
+// [SEMANTICS] ui, navigation, actions
package com.homebox.lens.navigation
// [IMPORTS]
import androidx.navigation.NavHostController
import timber.log.Timber
+import com.homebox.lens.ui.navigation.Screen
// [END_IMPORTS]
// [ENTITY: Class('NavigationActions')]
@@ -64,10 +65,19 @@ class NavigationActions(private val navController: NavHostController) {
}
// [END_ENTITY: Function('navigateToSearch')]
+ // [ENTITY: Function('navigateToInventory')]
+ fun navigateToInventory() {
+ Timber.i("[INFO][ACTION][navigate_to_inventory] Navigating to Inventory.")
+ navController.navigate(Screen.Inventory.route) {
+ launchSingleTop = true
+ }
+ }
+ // [END_ENTITY: Function('navigateToInventory')]
+
// [ENTITY: Function('navigateToInventoryListWithLabel')]
fun navigateToInventoryListWithLabel(labelId: String) {
Timber.i("[INFO][ACTION][navigate_to_inventory_with_label] Navigating to Inventory with label: %s", labelId)
- val route = Screen.InventoryList.withFilter("label", labelId)
+ val route = Screen.Inventory.withFilter("label", labelId)
navController.navigate(route)
}
// [END_ENTITY: Function('navigateToInventoryListWithLabel')]
@@ -75,7 +85,7 @@ class NavigationActions(private val navController: NavHostController) {
// [ENTITY: Function('navigateToInventoryListWithLocation')]
fun navigateToInventoryListWithLocation(locationId: String) {
Timber.i("[INFO][ACTION][navigate_to_inventory_with_location] Navigating to Inventory with location: %s", locationId)
- val route = Screen.InventoryList.withFilter("location", locationId)
+ val route = Screen.Inventory.withFilter("location", locationId)
navController.navigate(route)
}
// [END_ENTITY: Function('navigateToInventoryListWithLocation')]
@@ -87,6 +97,13 @@ class NavigationActions(private val navController: NavHostController) {
}
// [END_ENTITY: Function('navigateToCreateItem')]
+ // [ENTITY: Function('navigateToItemDetails')]
+ fun navigateToItemDetails(itemId: String) {
+ Timber.i("[INFO][ACTION][navigate_to_item_details] Navigating to Item Details with ID: %s", itemId)
+ navController.navigate(Screen.ItemDetails.createRoute(itemId))
+ }
+ // [END_ENTITY: Function('navigateToItemDetails')]
+
// [ENTITY: Function('navigateToLogout')]
fun navigateToLogout() {
Timber.i("[INFO][ACTION][navigate_to_logout] Navigating to Logout.")
@@ -104,4 +121,4 @@ class NavigationActions(private val navController: NavHostController) {
// [END_ENTITY: Function('navigateBack')]
}
// [END_ENTITY: Class('NavigationActions')]
-// [END_FILE_NavigationActions.kt]
+// [END_FILE_NavigationActions.kt]
\ No newline at end of file
diff --git a/app/src/main/java/com/homebox/lens/navigation/Screen.kt b/ui/src/main/java/com/homebox/lens/navigation/Screen.kt
similarity index 92%
rename from app/src/main/java/com/homebox/lens/navigation/Screen.kt
rename to ui/src/main/java/com/homebox/lens/navigation/Screen.kt
index ff428e9..67e50f6 100644
--- a/app/src/main/java/com/homebox/lens/navigation/Screen.kt
+++ b/ui/src/main/java/com/homebox/lens/navigation/Screen.kt
@@ -1,6 +1,6 @@
// [FILE] Screen.kt
-// [SEMANTICS] app, ui, navigation, routes
-package com.homebox.lens.navigation
+// [SEMANTICS] ui, navigation, routes
+package com.homebox.lens.ui.navigation
// [ENTITY: SealedClass('Screen')]
/**
@@ -21,11 +21,11 @@ sealed class Screen(val route: String) {
data object Dashboard : Screen("dashboard_screen")
// [END_ENTITY: Object('Dashboard')]
- // [ENTITY: Object('InventoryList')]
- data object InventoryList : Screen("inventory_list_screen") {
+ // [ENTITY: Object('Inventory')]
+ data object Inventory : Screen("inventory_screen") {
// [ENTITY: Function('withFilter')]
/**
- * @summary Creates a route for the inventory list screen with a filter parameter.
+ * @summary Creates a route for the inventory screen with a filter parameter.
* @param key The filter key (e.g., "label" or "location").
* @param value The filter value (e.g., the ID of the label or location).
* @return A string of the full route with a query parameter.
@@ -34,13 +34,13 @@ sealed class Screen(val route: String) {
fun withFilter(key: String, value: String): String {
require(key.isNotBlank()) { "Filter key cannot be blank." }
require(value.isNotBlank()) { "Filter value cannot be blank." }
- val constructedRoute = "inventory_list_screen?$key=$value"
+ val constructedRoute = "inventory_screen?$key=$value"
check(constructedRoute.contains("?$key=$value")) { "Route must contain the filter query." }
return constructedRoute
}
// [END_ENTITY: Function('withFilter')]
}
- // [END_ENTITY: Object('InventoryList')]
+ // [END_ENTITY: Object('Inventory')]
// [ENTITY: Object('ItemDetails')]
data object ItemDetails : Screen("item_details_screen/{itemId}") {
@@ -127,4 +127,4 @@ sealed class Screen(val route: String) {
// [END_ENTITY: Object('Settings')]
}
// [END_ENTITY: SealedClass('Screen')]
-// [END_FILE_Screen.kt]
+// [END_FILE_Screen.kt]
\ No newline at end of file
diff --git a/app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt b/ui/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt
similarity index 89%
rename from app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt
rename to ui/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt
index ff9b896..eeec9c3 100644
--- a/app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt
+++ b/ui/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt
@@ -1,5 +1,5 @@
// [FILE] AppDrawer.kt
-// [SEMANTICS] app, ui, common, navigation
+// [SEMANTICS] ui, common, navigation
package com.homebox.lens.ui.common
// [IMPORTS]
@@ -21,9 +21,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
-import com.homebox.lens.R
+import com.homebox.lens.ui.R
import com.homebox.lens.navigation.NavigationActions
-import com.homebox.lens.navigation.Screen
+import com.homebox.lens.ui.navigation.Screen
// [END_IMPORTS]
// [ENTITY: Function('AppDrawerContent')]
@@ -65,6 +65,14 @@ internal fun AppDrawerContent(
onCloseDrawer()
}
)
+ NavigationDrawerItem(
+ label = { Text(stringResource(id = R.string.inventory_list_title)) },
+ selected = currentRoute == Screen.Inventory.route,
+ onClick = {
+ navigationActions.navigateToInventory()
+ onCloseDrawer()
+ }
+ )
NavigationDrawerItem(
label = { Text(stringResource(id = R.string.nav_locations)) },
selected = currentRoute == Screen.LocationsList.route,
@@ -102,4 +110,4 @@ internal fun AppDrawerContent(
}
}
// [END_ENTITY: Function('AppDrawerContent')]
-// [END_FILE_AppDrawer.kt]
+// [END_FILE_AppDrawer.kt]
\ No newline at end of file
diff --git a/app/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt b/ui/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt
similarity index 96%
rename from app/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt
rename to ui/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt
index c7d7821..7a9c353 100644
--- a/app/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt
+++ b/ui/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt
@@ -1,6 +1,5 @@
// [FILE] MainScaffold.kt
-// [SEMANTICS] app, ui, common, scaffold
-
+// [SEMANTICS] ui, common, scaffold
package com.homebox.lens.ui.common
// [IMPORTS]
@@ -11,7 +10,7 @@ import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.res.stringResource
-import com.homebox.lens.R
+import com.homebox.lens.ui.R
import com.homebox.lens.navigation.NavigationActions
import kotlinx.coroutines.launch
// [END_IMPORTS]
diff --git a/ui/src/main/res/drawable/ic_placeholder.xml b/ui/src/main/res/drawable/ic_placeholder.xml
new file mode 100644
index 0000000..d1dcd5f
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_placeholder.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f760c6
--- /dev/null
+++ b/ui/src/main/res/values/strings.xml
@@ -0,0 +1,19 @@
+
+
+ Создать
+ Поиск
+ Выйти
+
+
+ Открыть боковое меню
+
+
+ Главная
+
+
+ Локации
+ Метки
+
+
+ Инвентарь
+
\ No newline at end of file