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>
This commit is contained in:
151
Docs/MakeShitWork.md
Normal file
151
Docs/MakeShitWork.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user