# 05. Upload Page with Optional Second Image and Species Selector meta: id: multi-image-user-feedback-05 feature: multi-image-user-feedback priority: P1 depends_on: [multi-image-user-feedback-01] tags: [ui, frontend, upload] objective: - Enhance the upload page to support an optional second image upload and a species search/select field. - Show live confidence indicators that update as the user provides more information. deliverables: - `src/app/upload/page.tsx` — updated upload flow - `src/components/ImageUpload.tsx` — updated to support multiple uploads - `src/components/SpeciesSelector.tsx` — new species search/dropdown component - `src/components/ConfidencePreview.tsx` — new inline confidence indicator steps: 1. Create `src/components/SpeciesSelector.tsx`: - Searchable dropdown with all 531 plant species from the knowledge base - Uses `fuse.js` for fuzzy matching (lightweight, fast client-side search) - Props: `value: string | null`, `onChange: (species: string | null) => void`, `disabled?: boolean` - States: empty, searching, selected, clearable - Shows common name and scientific name in results - Keyboard-navigable: up/down arrows, enter to select, escape to close - Mobile-friendly with full-screen overlay on small screens 2. Create `src/components/ConfidencePreview.tsx`: - Small inline bar showing estimated confidence based on info provided - Props: `numImages: number`, `speciesProvided: boolean`, `className?: string` - Dynamics: - 1 image, no species → "Low confidence — add another photo or identify the plant" - 1 image + species → "Medium confidence" - 2 images, no species → "Medium confidence — getting clearer" - 2 images + species → "High confidence — good data for diagnosis" - Animated transitions between states - Uses the same color scheme as ConfidenceBadge (green/amber/red) 3. Update `src/components/ImageUpload.tsx`: - Change from single-image to multi-image upload flow - After first successful upload, show a "Add another photo (optional)" button - Second upload uses the same ImageUpload internals but is secondary in visual weight - Store both `imageId` responses for the identify request - Add `uploadedImages: UploadResponse[]` tracking - Expose method to clear all images 4. Update `src/app/upload/page.tsx`: - Add state for: firstImageId, secondImageId, selectedSpecies - Add `SpeciesSelector` component below the upload zone(s) - Add `ConfidencePreview` component showing live confidence estimate - Add a "Continue to Diagnosis" button that becomes more prominent as more info is provided - On submit: - Build `IdentifyOptions` with secondImageId and/or userSpecies if provided - Pass `options` in the identify API call (or query params to results page) - Navigate to `/results/{firstImageId}?options={encodedOptions}` 5. Handle edge cases: - User adds second image, then removes it → gracefully falls back to single-image - User selects species, then wants to change it → searchable select supports re-selection - No species match found → user can type free-form (stored as-is) - Upload of second image fails → component shows inline error but allows retry without blocking the first image 6. Optimistic UI guidance: - Add a small info panel below the confidence preview explaining _why_ more info helps - Text: "Adding a second photo from a different angle helps our AI make a more accurate diagnosis. Identifying the plant species narrows down the possible diseases." tests: - Unit: SpeciesSelector renders, searches, selects, clears - Unit: SpeciesSelector keyboard navigation works - Unit: ConfidencePreview renders correct messages for each combination - Unit: ImageUpload supports 2-image flow - Integration: Full upload flow with 2 images + species → verify all data in request - A11y: verify aria-labels, roles, keyboard navigation acceptance_criteria: - User can upload a second image (optional, after first succeeds) - User can search and select a plant species from a dropdown - Confidence preview bar updates dynamically as info is added - "Continue to Diagnosis" button is prominent once at least 1 image is uploaded - Navigate to results page with all options encoded validation: - `npx tsc --noEmit` passes - Manual test: upload flow with 0/1/2 images and with/without species - Responsive test: works on mobile viewport (375px width) notes: - The species list comes from the knowledge base (`/api/plants` endpoint) - `fuse.js` is already lightweight (~15KB gzipped) and can be client-imported - The options are passed as URL query params to the results page since we navigate before the identify API call