Skip to content

Add in-app pet purchase flow (RND-1965)#2946

Draft
hugokallstrom wants to merge 21 commits into
feat/in-app-car-purchasefrom
feat/in-app-pet-purchase
Draft

Add in-app pet purchase flow (RND-1965)#2946
hugokallstrom wants to merge 21 commits into
feat/in-app-car-purchasefrom
feat/in-app-pet-purchase

Conversation

@hugokallstrom
Copy link
Copy Markdown
Contributor

Summary

  • Add feature-purchase-pet module that handles both SE_PET_DOG and SE_PET_CAT from one entry point.
  • Cross-sell taps to pet-insurance / djurforsakring land on a species picker (dog vs cat), then a form (pet name, breed, birth date, gender, neutered, dog-owner-history / outside-access, address, zip), then existing common purchase screens (tier → summary → BankID signing → success).
  • Three use cases under TDD: CreatePetSessionAndPriceIntent, GetPetBreeds (new priceIntentAvailableBreeds query), SubmitPetFormAndGetOffers. 12 unit tests, all passing.
  • Mirrors feature-purchase-car structure; reuses purchase-common unchanged.
  • Two small design-system tweaks justified by this flow: RadioGroup Labeled styles now forward fillMaxWidth to the inner Surface, and DropdownWithDialog puts 4dp between dialog items.

Architecture

feature-purchase-pet -> purchase-common (no feature-to-feature deps). Form state lives in the ViewModel for dropdowns/pickers (survives back navigation from tier select); text fields stay in local rememberSaveable to avoid cursor-jump from round-trip updates — same pattern as the car form.

Open items

  • Cross-sell URL slugs (pet-insurance / djurforsakring) were derived from racoon + storefront. Verified against staging in the emulator with a real impersonated member.
  • Hardcoded English copy with // TODO: Add ... to Lokalise comments per CLAUDE.md. Strings to migrate once the Lokalise keys exist.

Spec & plan

  • Design spec: docs/superpowers/specs/2026-05-21-pet-purchase-flow-design.md
  • Implementation plan: docs/superpowers/plans/2026-05-21-pet-purchase-flow.md

Test plan

  • ./gradlew :feature-purchase-pet:test — 12/12 pass
  • ./gradlew assembleDebug — succeeds
  • ./gradlew ktlintCheck — clean
  • Manual emulator verification: cross-sell tap → species picker → form → tier → summary → signing → success
  • Verify mixed-breed dog selection submits breeds: [] without backend error
  • Verify backend userError (e.g. underage pet) surfaces in ErrorDialog
  • Confirm cross-sell URL slugs against actual Storyblok cross-sells in staging

🤖 Generated with Claude Code

hugokallstrom and others added 21 commits May 21, 2026 07:24
Mirrors the car purchase architecture for SE_PET_DOG and SE_PET_CAT.
One feature-purchase-pet module handles both species; differs from
car by needing a breeds query (PriceIntentAvailableBreeds) and one
species-conditional last question.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
16-task plan with TDD-style steps, full code in each step, and
explicit verification commands. Mirrors the apartment/car plan
structure. Includes manual emulator verification per the
verifying-android-changes-in-emulator skill.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ance

Pet insurance has a single web cross-sell URL slug (pet-insurance / djurforsakring)
that doesn't distinguish dog vs cat — the species is chosen on the landing page.
Mirror that on Android by adding a SpeciesPicker destination that runs before
the form. PetPurchaseGraphDestination no longer carries productName.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- RadioGroup Labeled styles now propagate fillMaxWidth to the inner Surface,
  so a labeled radio container can fill its parent's width when given a
  fillMaxWidth modifier.
- DropdownWithDialog dialog adds 4dp spacing between items for readability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace gender / yes-no dropdowns with horizontal radio rows in a
  labeled card (using Labeled.HorizontalFlow style).
- Birth-date value uses bodySmall to match HedvigTextField Medium tokens.
- Custom error text on radio rows and the birth-date picker uses the
  same color and style as DropdownWithDialog (textSecondary, Label).
- Hoist dropdown/picker fields (selectedBreed, birthDate, gender,
  isNeutered, speciesAnswer) into the ViewModel so they survive
  back-navigation from tier select. Text fields stay in local
  rememberSaveable to avoid cursor-jump from round-trip updates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…se-car

Captures the pre-existing UnknownIssueId/UnstableApi warnings that the
hedvig.gradle.plugin emits on every module — same baseline shape as
sibling modules.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@notion-workspace
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant