- The "add note" affordance no longer hides from viewers (it claimed
parity with the bed inspector but gated on !readOnly). A viewer now sees
"📓 Notes about this plant" and can open the plop's journal to read it;
the composer stays edit-gated, so they can't write. Real parity now.
- onScopePlantingChange is required, matching onScopeChange (its bed twin),
so a caller can't pass a plop scope with no way to clear it. Dropped the
now-dead guard on the "Show all" button.
- Pulled the plop-over-bed scope-label priority into one `scopeLabel`,
shared by the filter's sibling logic and the composer, so they can't
drift; trimmed the invariant comment that was restated a third time.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ
journal_entries.planting_id was modelled, accepted by the API, and the
JournalPanel already rendered a "planting" badge for such entries — but
nothing in the UI ever created one. A badge for a state the UI couldn't
produce.
Give the plop the same "add note" affordance the bed inspector has:
- PlopInspector gains an onAddNote button ("📓 Add a note about this
plant"), shown only to an editor (a viewer can't write notes).
- The editor store gains a journalPlantingId scope beside journalObjectId.
The two are mutually exclusive — each setter clears the other — so the
journal filter is never double-scoped.
- JournalPanel filters by plantingId when that scope is set, shows a
"Notes about one planting · Show all" banner, and its composer attaches
new notes to the plop. Empty-state copy updated to match.
Two taps from a selected plant to typing, mirroring the bed flow. No
backend change — the API already accepted plantingId.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ