#50 stores provenance and lots; this is where you actually use them — the "what do I have, and where did it come from" surface. In practice that question gets asked twice: at the seed rack in January, and standing over a bed in May.
Scope
PlantFormModal: source URL + vendor fields. The URL renders as a link on the plant card (rel="noopener noreferrer", and treat it as untrusted — #50 caps and scheme-checks it server-side, but don't rely solely on that).
Lots on the plant detail/card: list them with vendor, purchase date, quantity, remaining, germination %. Add / edit / retire a lot.
A low / empty state that reads at a glance — this is the thing you scan for when ordering. Encode it in form, not just number (a chip or a bar), so it survives being skimmed.
PlantPicker (used when placing a plop) shows remaining quantity where a lot exists, and lets you attribute the plop to a specific lot when the plant has more than one. Don't force the choice — one lot should auto-attribute, zero lots should be silent.
Cost display in whole currency from cost_cents; per-seed or per-unit cost is a nice touch if it falls out cheaply.
A plant with a Johnny's URL shows a working link that opens safely.
Two lots of one plant display separately with independent remaining counts.
Placing a plop from a two-lot plant lets you pick the lot; the remaining count updates without a manual refresh.
The catalog is scannable on a phone — this gets used at a seed rack.
Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md)
## Context
#50 stores provenance and lots; this is where you actually use them — the "what do I have, and where did it come from" surface. In practice that question gets asked twice: at the seed rack in January, and standing over a bed in May.
## Scope
- [ ] `PlantFormModal`: source URL + vendor fields. The URL renders as a link on the plant card (`rel="noopener noreferrer"`, and treat it as untrusted — #50 caps and scheme-checks it server-side, but don't rely solely on that).
- [ ] Lots on the plant detail/card: list them with vendor, purchase date, quantity, **remaining**, germination %. Add / edit / retire a lot.
- [ ] A **low / empty** state that reads at a glance — this is the thing you scan for when ordering. Encode it in form, not just number (a chip or a bar), so it survives being skimmed.
- [ ] `PlantPicker` (used when placing a plop) shows remaining quantity where a lot exists, and lets you attribute the plop to a specific lot when the plant has more than one. Don't force the choice — one lot should auto-attribute, zero lots should be silent.
- [ ] Cost display in whole currency from `cost_cents`; per-seed or per-unit cost is a nice touch if it falls out cheaply.
## Out of scope
- Order/reorder workflows, vendor catalogs, barcode scanning.
- Charts. A number and a state chip beat a graph here.
## Key files
`web/src/pages/PlantsPage.tsx` · `web/src/components/plants/PlantFormModal.tsx`, `PlantCard.tsx` · `web/src/editor/PlantPicker.tsx` · `web/src/lib/plants.ts` (+ a new `seedLots.ts`)
## Dependencies
Blocked by #50.
## Acceptance criteria
- A plant with a Johnny's URL shows a working link that opens safely.
- Two lots of one plant display separately with independent remaining counts.
- Placing a plop from a two-lot plant lets you pick the lot; the remaining count updates without a manual refresh.
- The catalog is scannable on a phone — this gets used at a seed rack.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Design: DESIGN.md
Context
#50 stores provenance and lots; this is where you actually use them — the "what do I have, and where did it come from" surface. In practice that question gets asked twice: at the seed rack in January, and standing over a bed in May.
Scope
PlantFormModal: source URL + vendor fields. The URL renders as a link on the plant card (rel="noopener noreferrer", and treat it as untrusted — #50 caps and scheme-checks it server-side, but don't rely solely on that).PlantPicker(used when placing a plop) shows remaining quantity where a lot exists, and lets you attribute the plop to a specific lot when the plant has more than one. Don't force the choice — one lot should auto-attribute, zero lots should be silent.cost_cents; per-seed or per-unit cost is a nice touch if it falls out cheaply.Out of scope
Key files
web/src/pages/PlantsPage.tsx·web/src/components/plants/PlantFormModal.tsx,PlantCard.tsx·web/src/editor/PlantPicker.tsx·web/src/lib/plants.ts(+ a newseedLots.ts)Dependencies
Blocked by #50.
Acceptance criteria