Files
PlantGuide/Docs/MakeShitWork.md
Trey t 136dfbae33 Add PlantGuide iOS app with plant identification and care management
- Implement camera capture and plant identification workflow
- Add Core Data persistence for plants, care schedules, and cached API data
- Create collection view with grid/list layouts and filtering
- Build plant detail views with care information display
- Integrate Trefle botanical API for plant care data
- Add local image storage for captured plant photos
- Implement dependency injection container for testability
- Include accessibility support throughout the app

Bug fixes in this commit:
- Fix Trefle API decoding by removing duplicate CodingKeys
- Fix LocalCachedImage to load from correct PlantImages directory
- Set dateAdded when saving plants for proper collection sorting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 12:18:01 -06:00

152 lines
6.0 KiB
Markdown

# Make Shit Work - Base User Flow Plan
**Goal:** Ensure the core plant identification flow works end-to-end
## User Flow Under Review
```
1. User takes photo of plant
2. App calls PlantNet API to identify plant
3. App displays identification results (match list with confidence %)
4. User selects a plant from results (REPORTED NOT WORKING)
5. User taps "Save to Collection"
6. Plant is saved to user's collection
```
---
## Investigation Tasks
### Phase 1: Verify Data Flow (Read-Only)
- [ ] **T1.1** - Trace camera capture to IdentificationView handoff
- File: `Presentation/Scenes/Camera/CameraView.swift`
- File: `Presentation/Scenes/Camera/CameraViewModel.swift`
- Verify: `capturedImage` is correctly passed to IdentificationView
- [ ] **T1.2** - Verify PlantNet API call works
- File: `Data/DataSources/Remote/PlantNetAPI/PlantNetAPIService.swift`
- File: `Domain/UseCases/Identification/IdentifyPlantOnlineUseCase.swift`
- Test: Add logging to confirm API is called and returns results
- Check: API key validity, rate limits, response parsing
- [ ] **T1.3** - Verify predictions are mapped correctly
- File: `Data/Mappers/PlantNetMapper.swift`
- File: `Presentation/Scenes/Identification/IdentificationViewModel.swift`
- Verify: `PlantNetResultDTO``ViewPlantPrediction` mapping preserves all fields
- [ ] **T1.4** - Inspect results list rendering
- File: `Presentation/Scenes/Identification/IdentificationView.swift` (lines 267-278)
- Verify: `predictions` array is populated and displayed
- Check: `ForEach` enumerates correctly, `PredictionRow` renders
---
### Phase 2: Debug Selection Issue (PRIORITY)
- [ ] **T2.1** - Analyze `selectPrediction()` implementation
- File: `Presentation/Scenes/Identification/IdentificationViewModel.swift`
- Find: `selectPrediction(_ prediction:)` method
- Check: Does it update `@Published var selectedPrediction`?
- Check: Is there a state conflict preventing updates?
- [ ] **T2.2** - Check tap gesture binding in IdentificationView
- File: `Presentation/Scenes/Identification/IdentificationView.swift`
- Verify: `.onTapGesture { viewModel.selectPrediction(prediction) }`
- Check: Is gesture attached to correct view hierarchy?
- Check: Any overlapping gestures or hit testing issues?
- [ ] **T2.3** - Verify visual selection feedback
- File: `Presentation/Scenes/Identification/Components/PredictionRow.swift` (if exists)
- Check: `isSelected` property updates row appearance
- Check: Border color / checkmark renders when selected
- [ ] **T2.4** - Test auto-selection of first result
- File: `Presentation/Scenes/Identification/IdentificationViewModel.swift`
- Code: `selectedPrediction = predictions.first`
- Verify: This runs after API results are received
- Check: Does it fire before user interaction is possible?
---
### Phase 3: Verify Save to Collection
- [ ] **T3.1** - Trace save button action
- File: `Presentation/Scenes/Identification/IdentificationView.swift`
- Find: "Save to Collection" button action
- Verify: Calls `viewModel.saveToCollection()`
- [ ] **T3.2** - Verify `saveToCollection()` uses selected prediction
- File: `Presentation/Scenes/Identification/IdentificationViewModel.swift`
- Check: Does it use `selectedPrediction` (not first prediction)?
- Check: What happens if `selectedPrediction` is nil?
- [ ] **T3.3** - Verify prediction-to-plant mapping
- File: `Data/Mappers/PredictionToPlantMapper.swift`
- Verify: `ViewPlantPrediction``Plant` conversion is correct
- Check: All required fields populated
- [ ] **T3.4** - Verify SavePlantUseCase execution
- File: `Domain/UseCases/Collection/SavePlantUseCase.swift`
- Trace: Repository save call
- Check: Core Data persistence actually commits
- [ ] **T3.5** - Verify plant appears in collection
- File: `Data/Repositories/InMemoryPlantRepository.swift` (current impl)
- File: `Data/DataSources/Local/CoreData/CoreDataPlantStorage.swift`
- Check: Which repository is active? (DI container)
- Check: Fetch returns saved plants
---
## Fix Tasks (After Investigation)
### If Selection Not Working
- [ ] **F1** - Fix tap gesture if not firing
- [ ] **F2** - Fix `selectPrediction()` state update
- [ ] **F3** - Ensure selected state propagates to view
### If Save Not Working
- [ ] **F4** - Fix `saveToCollection()` to use selected prediction
- [ ] **F5** - Fix repository persistence if needed
- [ ] **F6** - Ensure save success/error state updates UI
---
## Key Files Reference
| Component | File Path |
|-----------|-----------|
| Camera View | `PlantGuide/Presentation/Scenes/Camera/CameraView.swift` |
| Camera VM | `PlantGuide/Presentation/Scenes/Camera/CameraViewModel.swift` |
| Identification View | `PlantGuide/Presentation/Scenes/Identification/IdentificationView.swift` |
| Identification VM | `PlantGuide/Presentation/Scenes/Identification/IdentificationViewModel.swift` |
| PlantNet API | `PlantGuide/Data/DataSources/Remote/PlantNetAPI/PlantNetAPIService.swift` |
| API DTOs | `PlantGuide/Data/DataSources/Remote/PlantNetAPI/DTOs/PlantNetDTOs.swift` |
| PlantNet Mapper | `PlantGuide/Data/Mappers/PlantNetMapper.swift` |
| Prediction→Plant Mapper | `PlantGuide/Data/Mappers/PredictionToPlantMapper.swift` |
| Save Use Case | `PlantGuide/Domain/UseCases/Collection/SavePlantUseCase.swift` |
| Plant Repository | `PlantGuide/Data/Repositories/InMemoryPlantRepository.swift` |
| Core Data Storage | `PlantGuide/Data/DataSources/Local/CoreData/CoreDataPlantStorage.swift` |
| DI Container | `PlantGuide/Core/DI/DIContainer.swift` |
---
## Success Criteria
1. User can take a photo and see identification results
2. User can tap any result row and see it visually selected
3. User can tap "Save to Collection" and the SELECTED plant is saved
4. Saved plant appears in collection view
5. No crashes or error states during flow
---
## Notes
- Selection issue reported by user - investigate Phase 2 first
- Repository may be InMemory (lost on restart) vs CoreData (persistent)
- Check DI container for which repository implementation is wired