"Change the garlic bed to cucumbers this year" has a year in it, and right now pansy has no notion of one — the editor shows whatever is currently planted, full stop.
The good news is the data already supports seasons and always has: plantings carry planted_at and removed_at, and "clear bed" soft-removes rather than deleting. A season is a date range over data that already exists. No schema change, and specifically no seasons table — v1's parking lot listed a "season/year scenario layer", but a table would duplicate what the dates already say and create a second source of truth about when something was in the ground.
Worth noting the copy feature from #46 is the other half of this: copy last year's layout, edit it, keep both. Scenario planning is a garden copy; season viewing is a filter.
Scope
GET /gardens/:id/full?year=YYYY — include plantings whose [planted_at, removed_at) interval overlaps that calendar year. Absent param keeps today's behaviour (active plantings only), so nothing existing changes.
Undated plantings are always included. Every planting today has a null planted_at, so a rule that excludes them would empty every garden the moment a year is selected. Document it in the handler.
Year selector in the editor chrome; default to the current year. Persist the choice per garden in the editor store (ephemeral state, not server-side).
Historical years render read-only, or at minimum make it unmistakable that you're not looking at now. Editing the past by accident is the failure mode.
Offer only years that actually have data, plus the current one — a free-numeric year field invites typos and empty views.
Out of scope
A seasons table, per above.
Crop rotation warnings ("nightshades here three years running"). Genuinely useful, genuinely a later thing, and it becomes easy once this lands.
None. Pairs naturally with #52/#53 — a year's plantings plus that year's notes is the season record.
Acceptance criteria
Selecting a past year shows what was planted then, including plops since removed.
A planting spanning a year boundary (garlic in October, harvested in July) appears in both years.
Undated plantings appear in every year.
Without the param, /full behaves exactly as it does today — verified by the existing tests still passing unchanged.
Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md)
## Context
"Change the garlic bed to cucumbers **this year**" has a year in it, and right now pansy has no notion of one — the editor shows whatever is currently planted, full stop.
The good news is the data already supports seasons and always has: plantings carry `planted_at` and `removed_at`, and "clear bed" soft-removes rather than deleting. A season is a date range over data that already exists. **No schema change, and specifically no `seasons` table** — v1's parking lot listed a "season/year scenario layer", but a table would duplicate what the dates already say and create a second source of truth about when something was in the ground.
Worth noting the copy feature from #46 is the other half of this: copy last year's layout, edit it, keep both. Scenario planning is a garden copy; season *viewing* is a filter.
## Scope
- [ ] `GET /gardens/:id/full?year=YYYY` — include plantings whose `[planted_at, removed_at)` interval overlaps that calendar year. Absent param keeps today's behaviour (active plantings only), so nothing existing changes.
- [ ] **Undated plantings are always included.** Every planting today has a null `planted_at`, so a rule that excludes them would empty every garden the moment a year is selected. Document it in the handler.
- [ ] Year selector in the editor chrome; default to the current year. Persist the choice per garden in the editor store (ephemeral state, not server-side).
- [ ] Historical years render read-only, or at minimum make it unmistakable that you're not looking at now. Editing the past by accident is the failure mode.
- [ ] Offer only years that actually have data, plus the current one — a free-numeric year field invites typos and empty views.
## Out of scope
- A `seasons` table, per above.
- Crop rotation warnings ("nightshades here three years running"). Genuinely useful, genuinely a later thing, and it becomes easy once this lands.
- Comparing two years side by side.
## Key files
`internal/api/objects.go` (`getGardenFull`) · `internal/service/objects.go` (`assembleFull`) · `internal/store/plantings.go` (`ListActivePlantingsForGarden` — needs a dated sibling) · `web/src/editor/store.ts` · `web/src/pages/GardenEditorPage.tsx`
## Dependencies
None. Pairs naturally with #52/#53 — a year's plantings plus that year's notes is the season record.
## Acceptance criteria
- Selecting a past year shows what was planted then, including plops since removed.
- A planting spanning a year boundary (garlic in October, harvested in July) appears in both years.
- Undated plantings appear in every year.
- Without the param, `/full` behaves exactly as it does today — verified by the existing tests still passing unchanged.
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
"Change the garlic bed to cucumbers this year" has a year in it, and right now pansy has no notion of one — the editor shows whatever is currently planted, full stop.
The good news is the data already supports seasons and always has: plantings carry
planted_atandremoved_at, and "clear bed" soft-removes rather than deleting. A season is a date range over data that already exists. No schema change, and specifically noseasonstable — v1's parking lot listed a "season/year scenario layer", but a table would duplicate what the dates already say and create a second source of truth about when something was in the ground.Worth noting the copy feature from #46 is the other half of this: copy last year's layout, edit it, keep both. Scenario planning is a garden copy; season viewing is a filter.
Scope
GET /gardens/:id/full?year=YYYY— include plantings whose[planted_at, removed_at)interval overlaps that calendar year. Absent param keeps today's behaviour (active plantings only), so nothing existing changes.planted_at, so a rule that excludes them would empty every garden the moment a year is selected. Document it in the handler.Out of scope
seasonstable, per above.Key files
internal/api/objects.go(getGardenFull) ·internal/service/objects.go(assembleFull) ·internal/store/plantings.go(ListActivePlantingsForGarden— needs a dated sibling) ·web/src/editor/store.ts·web/src/pages/GardenEditorPage.tsxDependencies
None. Pairs naturally with #52/#53 — a year's plantings plus that year's notes is the season record.
Acceptance criteria
/fullbehaves exactly as it does today — verified by the existing tests still passing unchanged.