This commit is contained in:
2025-09-26 10:30:59 +03:00
parent aa69776807
commit 394e0040de
82 changed files with 5324 additions and 1998 deletions

View File

@@ -0,0 +1,199 @@
<WORK_ORDER feature="Settings Screen">
<ACTION type="MODIFY" file_path="./app/src/main/java/com/homebox/lens/navigation/Screen.kt">
<DESCRIPTION>Добавить маршрут для экрана настроек в sealed class Screen.</DESCRIPTION>
<INSERT after="// [END_ENTITY: Object('Search')]">
<![CDATA[
// [ENTITY: Object('Settings')]
data object Settings : Screen("settings_screen")
// [END_ENTITY: Object('Settings')]
]]>
</INSERT>
</ACTION>
<ACTION type="CREATE" file_path="./app/src/main/java/com/homebox/lens/ui/screen/settings/SettingsUiState.kt">
<DESCRIPTION>Создать data class для состояния UI экрана настроек.</DESCRIPTION>
<CONTENT>
<![CDATA[
package com.homebox.lens.ui.screen.settings
data class SettingsUiState(
val serverUrl: String = "",
val isLoading: Boolean = false,
val error: String? = null,
val isSaved: Boolean = false
)
]]>
</CONTENT>
</ACTION>
<ACTION type="CREATE" file_path="./app/src/main/java/com/homebox/lens/ui/screen/settings/SettingsViewModel.kt">
<DESCRIPTION>Создать ViewModel для экрана настроек.</DESCRIPTION>
<CONTENT>
<![CDATA[
package com.homebox.lens.ui.screen.settings
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.homebox.lens.domain.repository.CredentialsRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class SettingsViewModel @Inject constructor(
private val credentialsRepository: CredentialsRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(SettingsUiState())
val uiState = _uiState.asStateFlow()
init {
loadCurrentSettings()
}
private fun loadCurrentSettings() {
viewModelScope.launch {
_uiState.value = _uiState.value.copy(isLoading = true)
val credentials = credentialsRepository.getCredentials().first()
_uiState.value = _uiState.value.copy(
serverUrl = credentials?.serverUrl ?: "",
isLoading = false
)
}
}
fun onServerUrlChange(newUrl: String) {
_uiState.value = _uiState.value.copy(serverUrl = newUrl, isSaved = false)
}
fun saveSettings() {
// TODO: Implement saving logic, probably need a use case
// For now, just simulate success
viewModelScope.launch {
_uiState.value = _uiState.value.copy(isLoading = true)
// val success = saveSettingsUseCase(_uiState.value.serverUrl)
_uiState.value = _uiState.value.copy(isLoading = false, isSaved = true)
}
}
}
]]>
</CONTENT>
</ACTION>
<ACTION type="CREATE" file_path="./app/src/main/java/com/homebox/lens/ui/screen/settings/SettingsScreen.kt">
<DESCRIPTION>Создать Composable для UI экрана настроек.</DESCRIPTION>
<CONTENT>
<![CDATA[
package com.homebox.lens.ui.screen.settings
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.homebox.lens.navigation.Screen
import com.homebox.lens.ui.common.MainScaffold
@Composable
fun SettingsScreen(
viewModel: SettingsViewModel = hiltViewModel(),
onNavigateUp: () -> Unit
) {
val uiState by viewModel.uiState.collectAsState()
MainScaffold(
title = "Настройки",
onNavigateUp = onNavigateUp
) { paddingValues ->
SettingsContent(
modifier = Modifier.padding(paddingValues),
uiState = uiState,
onServerUrlChange = viewModel::onServerUrlChange,
onSaveClick = viewModel::saveSettings
)
}
}
@Composable
fun SettingsContent(
modifier: Modifier = Modifier,
uiState: SettingsUiState,
onServerUrlChange: (String) -> Unit,
onSaveClick: () -> Unit
) {
Column(
modifier = modifier
.fillMaxSize()
.padding(16.dp)
) {
OutlinedTextField(
value = uiState.serverUrl,
onValueChange = onServerUrlChange,
label = { Text("URL Сервера") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = onSaveClick,
enabled = !uiState.isLoading,
modifier = Modifier.fillMaxWidth()
) {
if (uiState.isLoading) {
CircularProgressIndicator(modifier = Modifier.size(24.dp))
} else {
Text("Сохранить")
}
}
if (uiState.isSaved) {
Text("Настройки сохранены!", color = MaterialTheme.colorScheme.primary)
}
if (uiState.error != null) {
Text(uiState.error, color = MaterialTheme.colorScheme.error)
}
}
}
]]>
</CONTENT>
</ACTION>
<ACTION type="MODIFY" file_path="./app/src/main/java/com/homebox/lens/navigation/NavGraph.kt">
<DESCRIPTION>Добавить экран настроек в навигационный граф.</DESCRIPTION>
<INSERT after='composable(Screen.Search.route) { SearchScreen(navActions) }'>
<![CDATA[
composable(Screen.Settings.route) {
SettingsScreen(
onNavigateUp = { navActions.navController.navigateUp() }
)
}
]]>
</INSERT>
</ACTION>
<ACTION type="MODIFY" file_path="./app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt">
<DESCRIPTION>Добавить пункт "Настройки" в боковое меню.</DESCRIPTION>
<INSERT after=' onClick = {
navActions.navController.navigate(Screen.LocationsList.route)
scope.launch { drawerState.close() }
}
)'>
<![CDATA[
NavigationDrawerItem(
icon = { Icon(Icons.Default.Settings, contentDescription = null) },
label = { Text("Настройки") },
selected = false,
onClick = {
navActions.navController.navigate(Screen.Settings.route)
scope.launch { drawerState.close() }
}
)
]]>
</INSERT>
</ACTION>
</WORK_ORDER>

View File

@@ -0,0 +1,7 @@
<QA_TASK>
<TITLE>QA: Проверить реализацию Implement Settings Screen</TITLE>
<PR_ID>PR-current_work_order</PR_ID>
<ISSUE_ID>current_work_order</ISSUE_ID>
<ASSIGNEE>agent-qa</ASSIGNEE>
<LABELS>type::quality-assurance,status::retested</LABELS>
</QA_TASK>

View File

@@ -1,71 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<WORK_ORDER>
<METADATA>
<WORK_ORDER_ID>20250906_100000</WORK_ORDER_ID>
<TITLE>[ARCHITECT -> DEV] Implement Label Management Feature</TITLE>
<DESCRIPTION>
This work order is to implement the full lifecycle of label management,
including creating, viewing, editing, and deleting labels.
This involves creating a new screen for editing labels, a view model to handle the logic,
and integrating it with the existing label list screen.
</DESCRIPTION>
<STATUS>Completed</STATUS>
<ASSIGNEE>agent-developer</ASSIGNEE>
<LABELS>
<LABEL>type::development</LABEL>
<LABEL>feature::label-management</LABEL>
</LABELS>
</METADATA>
<TASKS>
<TASK id="task_1" name="Create LabelEditViewModel">
<DESCRIPTION>
Create a new ViewModel `LabelEditViewModel.kt` in `app/src/main/java/com/homebox/lens/ui/screen/labeledit/`.
This ViewModel should handle the business logic for creating and updating a label.
It should use `GetLabelDetailsUseCase`, `CreateLabelUseCase`, and `UpdateLabelUseCase`.
</DESCRIPTION>
<CHECKLIST>
<ITEM>Create `app/src/main/java/com/homebox/lens/ui/screen/labeledit/LabelEditViewModel.kt`</ITEM>
<ITEM>Inject `GetLabelDetailsUseCase`, `CreateLabelUseCase`, `UpdateLabelUseCase`.</ITEM>
<ITEM>Implement state management for the label editing screen.</ITEM>
<ITEM>Implement methods to create and update a label.</ITEM>
</CHECKLIST>
</TASK>
<TASK id="task_2" name="Create LabelEditScreen">
<DESCRIPTION>
Create a new Jetpack Compose screen `LabelEditScreen.kt` in `app/src/main/java/com/homebox/lens/ui/screen/labeledit/`.
This screen will be used for both creating a new label and editing an existing one.
The UI should be similar to the `LocationEditScreen`.
</DESCRIPTION>
<CHECKLIST>
<ITEM>Create `app/src/main/java/com/homebox/lens/ui/screen/labeledit/LabelEditScreen.kt`</ITEM>
<ITEM>Implement the UI for creating/editing a label (e.g., a text field for the name and a color picker).</ITEM>
<ITEM>Connect the screen to `LabelEditViewModel`.</ITEM>
</CHECKLIST>
</TASK>
<TASK id="task_3" name="Update Navigation">
<DESCRIPTION>
Update the navigation graph to include the new `LabelEditScreen`.
The `LabelsListScreen` should navigate to `LabelEditScreen` when the user wants to create or edit a label.
</DESCRIPTION>
<CHECKLIST>
<ITEM>Add a route for `LabelEditScreen` in `Screen.kt`.</ITEM>
<ITEM>Add the new screen to the `NavGraph.kt`.</ITEM>
<ITEM>Implement navigation from `LabelsListScreen` to `LabelEditScreen`.</ITEM>
</CHECKLIST>
</TASK>
<TASK id="task_4" name="Create GetLabelDetailsUseCase">
<DESCRIPTION>
Create a new UseCase `GetLabelDetailsUseCase.kt` in `domain/src/main/java/com/homebox/lens/domain/usecase/`.
This UseCase will be responsible for getting the details of a single label.
</DESCRIPTION>
<CHECKLIST>
<ITEM>Create `domain/src/main/java/com/homebox/lens/domain/usecase/GetLabelDetailsUseCase.kt`</ITEM>
<ITEM>Implement the logic to get label details from the `ItemRepository`.</ITEM>
</CHECKLIST>
</TASK>
</TASKS>
</WORK_ORDER>

View File

@@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<WorkOrder>
<MetaData>
<OrderID>WO-FEAT-DASH-20250925-001</OrderID>
<Title>Refactor Dashboard Feature into a Separate Module</Title>
<Description>Extract the Dashboard screen, ViewModel, and related components from the app module into a new feature:dashboard module to improve modularity, isolation, and build performance.</Description>
<Priority>High</Priority>
<Status>зутвштп</Status>
<CreatedBy>Architect</CreatedBy>
<CreatedDate>2025-09-25</CreatedDate>
<EstimatedEffort>4-6 hours</EstimatedEffort>
</MetaData>
<Requirements>
<Functional>
<Item>
<ID>REQ-001</ID>
<Description>Create a new Android Library module named 'feature:dashboard' under the 'feature/dashboard' directory.</Description>
<AcceptanceCriteria>
<Criterion>The module builds successfully as an Android Library.</Criterion>
<Criterion>It includes plugins for Kotlin, Compose, and Hilt.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-002</ID>
<Description>Configure dependencies for the new module.</Description>
<AcceptanceCriteria>
<Criterion>Depends on ':domain' and ':data' modules.</Criterion>
<Criterion>Includes Compose UI, Navigation Compose, Hilt Navigation Compose, and other necessary AndroidX libraries.</Criterion>
<Criterion>No circular dependencies.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-003</ID>
<Description>Include the new module in settings.gradle.kts.</Description>
<AcceptanceCriteria>
<Criterion>Add 'include(":feature:dashboard")' to settings.gradle.kts.</Criterion>
<Criterion>The project syncs without errors.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-004</ID>
<Description>Move Dashboard-related files to the new module.</Description>
<AcceptanceCriteria>
<Criterion>Move DashboardScreen.kt, DashboardViewModel.kt, DashboardUiState.kt from app/src/main/java/com/homebox/lens/ui/screen/dashboard/ to feature/dashboard/src/main/java/com/homebox/lens/feature/dashboard/.</Criterion>
<Criterion>Update package declarations to 'com.homebox.lens.feature.dashboard'.</Criterion>
<Criterion>Ensure all imports are resolved correctly.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-005</ID>
<Description>Update app module dependencies.</Description>
<AcceptanceCriteria>
<Criterion>Add 'implementation(project(":feature:dashboard"))' to app/build.gradle.kts.</Criterion>
<Criterion>Remove any direct dependencies on moved files.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-006</ID>
<Description>Adapt navigation integration.</Description>
<AcceptanceCriteria>
<Criterion>Create a public composable function or NavGraphBuilder extension in the dashboard module for easy integration (e.g., addDashboardScreen).</Criterion>
<Criterion>Update NavGraph.kt in app to import and use the new navigation builder from feature:dashboard.</Criterion>
<Criterion>Navigation to/from Dashboard works unchanged.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-007</ID>
<Description>Ensure Hilt DI works across modules.</Description>
<AcceptanceCriteria>
<Criterion>DashboardViewModel injects dependencies correctly via Hilt.</Criterion>
<Criterion>No DI-related runtime errors.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>REQ-008</ID>
<Description>Verify build and runtime.</Description>
<AcceptanceCriteria>
<Criterion>The entire project builds successfully (./gradlew build).</Criterion>
<Criterion>Dashboard screen renders and functions as before.</Criterion>
<Criterion>No regressions in other features.</Criterion>
</AcceptanceCriteria>
</Item>
</Functional>
<NonFunctional>
<Item>
<ID>NF-001</ID>
<Description>Follow Semantic Enrichment Protocol for all code changes.</Description>
<AcceptanceCriteria>
<Criterion>All .kt files include [FILE] header, [SEMANTICS], anchors, contracts, and [END_FILE].</Criterion>
<Criterion>No stray comments; use [AI_NOTE] if needed.</Criterion>
</AcceptanceCriteria>
</Item>
<Item>
<ID>NF-002</ID>
<Description>Maintain code quality.</Description>
<AcceptanceCriteria>
<Criterion>Run ktlint and fix any issues.</Criterion>
<Criterion>Add or update unit tests if necessary.</Criterion>
</AcceptanceCriteria>
</Item>
</NonFunctional>
</Requirements>
<ImplementationGuidelines>
<Step>
<ID>STEP-001</ID>
<Description>Create directory structure: feature/dashboard/src/main/java/com/homebox/lens/feature/dashboard/.</Description>
</Step>
<Step>
<ID>STEP-002</ID>
<Description>Generate build.gradle.kts for the new module, mirroring app's Compose/Hilt setup but as library.</Description>
</Step>
<Step>
<ID>STEP-003</ID>
<Description>Update settings.gradle.kts.</Description>
</Step>
<Step>
<ID>STEP-004</ID>
<Description>Move files and update packages/imports.</Description>
</Step>
<Step>
<ID>STEP-005</ID>
<Description>Update app/build.gradle.kts dependencies.</Description>
</Step>
<Step>
<ID>STEP-006</ID>
<Description>Implement navigation extension in dashboard module and update NavGraph.kt.</Description>
<Example>
In dashboard: fun NavGraphBuilder.addDashboardScreen(navController: NavHostController) { composable("dashboard") { DashboardScreen(navController) } }
In app/NavGraph: import com.homebox.lens.feature.dashboard.addDashboardScreen; NavHost { addDashboardScreen(navController) }
</Example>
</Step>
<Step>
<ID>STEP-007</ID>
<Description>Sync project, build, and test runtime behavior.</Description>
</Step>
<Step>
<ID>STEP-008</ID>
<Description>Apply Semantic Enrichment to all modified/created files.</Description>
</Step>
</ImplementationGuidelines>
<TestingRequirements>
<UnitTests>
<Item>Ensure existing DashboardViewModel tests pass if any exist.</Item>
<Item>Add integration test for navigation if needed.</Item>
</UnitTests>
<IntegrationTests>
<Item>Verify app launches and navigates to Dashboard without errors.</Item>
</IntegrationTests>
</TestingRequirements>
<Risks>
<Risk>
<ID>RISK-001</ID>
<Description>Navigation breaks due to package changes.</Description>
<Mitigation>Test navigation immediately after move.</Mitigation>
</Risk>
<Risk>
<ID>RISK-002</ID>
<Description>Hilt injection fails across modules.</Description>
<Mitigation>Ensure shared modules (domain/data) provide dependencies.</Mitigation>
</Risk>
</Risks>
<SuccessCriteria>
<Item>Project builds and runs without errors.</Item>
<Item>Dashboard functionality unchanged.</Item>
<Item>New module is isolated and can be built independently.</Item>
<Item>All code follows Semantic Enrichment Protocol.</Item>
</SuccessCriteria>
</WorkOrder>

View File

@@ -0,0 +1,80 @@
# Work Order: Update Item Creation and Edit to Full API Compliance
## METADATA
- **FEATURE_NAME**: Item Creation and Edit Screen Enhancement
- **REQUESTED_BY**: user
- **TIMESTAMP**: 2025-09-25T07:15:00Z
## OVERVIEW
This work order outlines the steps required to update the Item creation and editing functionality in the Homebox Lens mobile application to fully comply with the Homebox API specification. This includes enhancing the UI to capture all required fields and updating the ViewModel to correctly map these fields to the domain models.
## REQUIREMENTS GAPS
Current implementation in `app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditScreen.kt` and `app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModel.kt` only handles a subset of the fields defined in `tech_spec/api_summary.md`.
Missing UI fields for `Item`:
- `assetId`
- `notes`
- `serialNumber`
- `value`
- `purchasePrice`
- `purchaseDate`
- `warrantyUntil`
- `parentId`
Missing ViewModel mappings:
- All the above fields are hardcoded to `null` in `ItemCreate` and `ItemUpdate` objects.
## STEPS
### STEP 1: Enhance UI Layer (ItemEditScreen.kt)
#### Description
Update the `ItemEditScreen` composable to include input fields for all missing item properties.
#### Action
- Add `TextField` or appropriate input components for `assetId`, `notes`, `serialNumber`, `value`, `purchasePrice`.
- Add `DatePicker` components for `purchaseDate` and `warrantyUntil`.
- Add `TextField` for `parentId`.
- Implement a multi-select component for `labelIds` to allow selecting multiple labels from a list.
- Ensure `locationId` selection is properly implemented (verify existing functionality).
### STEP 2: Update ViewModel Layer (ItemEditViewModel.kt)
#### Description
Update `ItemEditViewModel` to handle the new UI fields and correctly map them to domain models.
#### Action
- Update `ItemEditUiState` sealed interface or data class to include all new fields from STEP 1.
- Add corresponding handler functions like `onAssetIdChanged`, `onNotesChanged`, etc., to update the UI state.
- Modify `createItem` and `updateItem` functions to properly map all fields from `uiState` to `ItemCreate` and `ItemUpdate` domain models instead of hardcoding them to `null`.
### STEP 3: Integrate QR Scanner with Item Creation
#### Description
Modify the QR scanner feature to automatically populate the `assetId` field when navigating to the item creation screen.
#### Action
- Update `ScanScreen` to navigate to `ItemEditScreen` with the scanned barcode as pre-filled `assetId`.
- Add navigation logic in `ScanViewModel` to handle the transition.
- Ensure `ItemEditScreen` can receive and use this pre-filled value.
### STEP 4: Update Project Manifest
#### Description
Update `tech_spec/PROJECT_MANIFEST.xml` to reflect the changes in item creation/editing functionality.
#### Action
- Add a new `<FEATURE>` entry for "Item Creation and Edit Enhancement" or update the existing one if it already covers item creation.
- Include all relevant components, classes, and properties in the manifest.
### STEP 5: Create Engineer Task
#### Description
Create a task for the engineer to implement the outlined changes.
#### Action
- Save this work order to a file in the `tasks` directory.
- Switch to Engineer and provide this work order as a task.