Add month sowing chips and update filters for responsive design

This commit is contained in:
Brenda Wallace committed 2026-11-04 07:39:36 +00:00
1 parent bd08ad6b3a
commit 6dd5ff724c
7 files changed
+81 -13

No files matched your search

+18 -4
View File
@@ -39,16 +39,30 @@ module SeedFiltersHelper
['Shared for trading', { shared: 1 }]]
end
# "Sow now": this month, and next in the last days of it.
def seed_sow_now_label
"Sow now (#{Seed.sow_now_months.map { |month| Date::MONTHNAMES[month] }.join(' & ')})"
end
# Every month as a chip, for a screen wide enough to show them all.
def seed_month_chips
[['Any month', { sow_month: nil }],
[seed_sow_now_label, { sow_month: 'now' }],
*Date::MONTHNAMES.compact.each_with_index.map { |name, index| [name, { sow_month: index + 1 }] }]
end
# The chips in their labelled groups. How far away only means something on
# other people's seeds, and sharing only on a gardener's own: everyone's are
# all shared.
# all shared. The months are chips on a wide screen and a select on a narrow
# one, so that group says it is `wide_only`.
def seed_filter_groups(everyone:)
[['Source', seed_source_chips],
[['Month to sow', seed_month_chips, true],
['Source', seed_source_chips],
(['Distance', seed_distance_chips] if everyone && current_member&.latitude),
(['Sharing', seed_sharing_chips] unless everyone),
['Heirloom or hybrid', seed_heirloom_chips],
['Planted', seed_planted_chips]].compact.map do |label, chips|
{ label:, chips: chips.map { |chip_label, params| { label: chip_label, params: } } }
['Planted', seed_planted_chips]].compact.map do |label, chips, wide_only|
{ label:, wide_only: wide_only || false, chips: chips.map { |chip_label, params| { label: chip_label, params: } } }
end
end
+1 -1
View File
@@ -182,7 +182,7 @@ module SeedsHelper
{
groups: everyone ? SEED_GROUPS + [%w(gardener Gardener)] : SEED_GROUPS,
filters: seed_filter_groups(everyone:),
sow_now: "Sow now (#{Seed.sow_now_months.map { |month| Date::MONTHNAMES[month] }.join(' & ')})",
sow_now: seed_sow_now_label,
gardeners: (seed_friend_names if everyone),
months: Date::MONTHNAMES.compact.each_with_index.map { |name, index| [index + 1, name] },
clear: seed_filters_off.merge(crop: nil),
+3 -3
View File
@@ -181,7 +181,7 @@ export default function SeedLibrary({scope: initialScope, tabs: initialTabs, htm
<Choice params={clear} search={pendingSearch} className="seed-clear" onChoose={show}>Clear all filters</Choice>
)}
</div>
<div className="seed-filter-row">
<div className="seed-filter-row d-lg-none">
<div className="seed-field">
<label className="seed-field-label" htmlFor="seed-month">Month to sow</label>
<select
@@ -221,8 +221,8 @@ export default function SeedLibrary({scope: initialScope, tabs: initialTabs, htm
</div>
</div>
)}
{filters.map(({label, chips}) => (
<div className="seed-filter-row" key={label}>
{filters.map(({label, chips, wide_only: wideOnly}) => (
<div className={`seed-filter-row${wideOnly ? ' d-none d-lg-flex' : ''}`} key={label}>
<div className="seed-field">
<span className="seed-field-label">{label}</span>
<ul className="seed-chips">{chips.map(chip)}</ul>
@@ -24,6 +24,11 @@ const props = {
],
},
{label: 'Planted', chips: [{label: 'Not planted yet', params: {planted: 'no'}}]},
{
label: 'Month to sow',
wide_only: true,
chips: [{label: 'Any month', params: {sow_month: null}}, {label: 'September', params: {sow_month: 9}}],
},
],
months: [[1, 'January'], [9, 'September']],
sow_now: 'Sow now (November)',
@@ -232,6 +237,21 @@ describe('SeedLibrary', () => {
expect(screen.queryByLabelText('Gardener')).not.toBeInTheDocument();
});
it('offers every month as a chip for a wide screen', () => {
setup();
expect(screen.getByRole('link', {name: 'September'})).toHaveAttribute('href', '/seeds?sow_month=9');
});
it('shows the month chips on wide screens only', () => {
setup();
expect(screen.getByRole('link', {name: 'September'}).closest('.seed-filter-row')).toHaveClass('d-none', 'd-lg-flex');
});
it('shows the month select on narrow screens only', () => {
setup();
expect(screen.getByLabelText('Month to sow').closest('.seed-filter-row')).toHaveClass('d-lg-none');
});
it('keeps the filters in force when another is chosen', () => {
window.history.replaceState({}, '', '/seeds?from=bought&group=year');
setup();
+7
View File
@@ -57,6 +57,13 @@ describe "changing the seeds shown without reloading", :js do
it { expect(page).to have_current_path member_seeds_path(owner) }
end
context "when choosing a month" do
before { click_link 'September' }
it { expect(page).to have_seed_params(sow_month: 9) }
it { expect(page).to have_css('.seed-chip.active', text: 'September') }
end
context "when choosing mine after choosing a chip" do
include_context 'signed in member'
+1 -1
View File
@@ -36,7 +36,7 @@ describe "removing seed library filters", :js do
end
context "when choosing any sowing month" do
before { select 'Any month', from: 'Month to sow' }
before { click_link 'Any month' }
it { expect(page).to have_seed_params(from: 'retail', heirloom: 'heirloom', planted: 'no', crop: tomato.slug, group: 'year') }
end
+31 -4
View File
@@ -3,6 +3,8 @@
require 'rails_helper'
describe SeedFiltersHelper do
include ActiveSupport::Testing::TimeHelpers
describe '#seed_view_path' do
before do
allow(helper.request).to receive_messages(path: '/seeds', query_parameters: { 'from' => 'bought', 'page' => '3', 'utm' => 'x' })
@@ -50,21 +52,46 @@ describe SeedFiltersHelper do
context 'with the member\'s own seeds' do
let(:everyone) { false }
it { expect(groups.pluck(:label)).to eq ['Source', 'Sharing', 'Heirloom or hybrid', 'Planted'] }
it { expect(groups.pluck(:label)).to eq ['Month to sow', 'Source', 'Sharing', 'Heirloom or hybrid', 'Planted'] }
end
context 'with everyone\'s seeds' do
let(:everyone) { true }
let(:distance) { groups.find { |group| group[:label] == 'Distance' }[:chips] }
it { expect(groups.pluck(:label)).to eq ['Source', 'Distance', 'Heirloom or hybrid', 'Planted'] }
it { expect(groups.second[:chips].pluck(:label)).to eq ['Anywhere', 'Within 50 km', 'Within 10 km'] }
it { expect(groups.pluck(:label)).to eq ['Month to sow', 'Source', 'Distance', 'Heirloom or hybrid', 'Planted'] }
it { expect(distance.pluck(:label)).to eq ['Anywhere', 'Within 50 km', 'Within 10 km'] }
end
context 'with everyone\'s seeds when signed out' do
let(:everyone) { true }
let(:viewer) { nil }
it { expect(groups.pluck(:label)).to eq ['Source', 'Heirloom or hybrid', 'Planted'] }
it { expect(groups.pluck(:label)).to eq ['Month to sow', 'Source', 'Heirloom or hybrid', 'Planted'] }
end
end
describe 'month chips' do
let(:chips) { helper.seed_month_chips }
before { travel_to Date.new(2026, 11, 4) }
it { expect(chips.first.first).to eq 'Any month' }
it { expect(chips.second.first).to eq 'Sow now (November)' }
it { expect(chips.second.last).to eq(sow_month: 'now') }
it { expect(chips.size).to eq 14 }
it { expect(chips.assoc('September').last).to eq(sow_month: 9) }
it { expect(helper.seed_filter_groups(everyone: false).first[:wide_only]).to be true }
it { expect(helper.seed_filter_groups(everyone: false).second[:wide_only]).to be false }
end
describe '#seed_sow_now_label' do
it 'names this month early in it' do
travel_to(Date.new(2026, 11, 4)) { expect(helper.seed_sow_now_label).to eq 'Sow now (November)' }
end
it 'names next month too near the end of this one' do
travel_to(Date.new(2026, 11, 28)) { expect(helper.seed_sow_now_label).to eq 'Sow now (November & December)' }
end
end
end