From 821a0f5bb370a5500c4443680c4766e720c5209f Mon Sep 17 00:00:00 2001 From: Hiago Lucas Cardeal de Melo Silva Date: Fri, 12 Jun 2026 10:56:45 -0300 Subject: [PATCH 1/3] fix: title delivery filter groups instead of "Default Title" Delivery filter groups other than `shipping` (`dynamic-estimate`, `delivery-options`) reached SearchFilter with no title and rendered the generic "Default Title" placeholder. Assign a heading to every delivery group in getFilters via a name->message-id map, including the code path where no `shipping` group is present. - Estimate (dynamic-estimate), Delivery Option (delivery-options); the shipping group keeps its existing "Shipping" title unchanged. - Unknown groups fall back to the raw name (never "Default Title"). - Add the two new title keys across all locales (non-EN best-effort drafts) and context.json; new getFilters unit tests cover all paths. Co-authored-by: Cursor --- CHANGELOG.md | 8 ++ messages/ar.json | 2 + messages/bg.json | 2 + messages/ca.json | 2 + messages/context.json | 2 + messages/da.json | 2 + messages/de.json | 2 + messages/el.json | 2 + messages/en.json | 2 + messages/es.json | 2 + messages/fi.json | 2 + messages/fr.json | 2 + messages/hu.json | 2 + messages/id.json | 2 + messages/it.json | 2 + messages/ja.json | 2 + messages/jp.json | 2 + messages/ko.json | 2 + messages/nl.json | 2 + messages/nn.json | 2 + messages/no.json | 2 + messages/pl.json | 2 + messages/pt.json | 2 + messages/ro.json | 2 + messages/ru.json | 2 + messages/sk.json | 2 + messages/sl.json | 2 + messages/sv.json | 2 + messages/th.json | 2 + messages/uk.json | 2 + react/__tests__/utils/getFilters.test.js | 106 +++++++++++++++++++++++ react/utils/getFilters.js | 55 +++++++----- 32 files changed, 207 insertions(+), 20 deletions(-) create mode 100644 react/__tests__/utils/getFilters.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index ff04d2328..ae6b0236b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed + +- Delivery filter groups `dynamic-estimate` and `delivery-options` no longer render the placeholder "Default Title" as their heading. They are now titled "Estimate" and "Delivery Option" respectively. Titles are assigned to every delivery group in `getFilters`, including the code path where no `shipping` group is present. + +### Added + +- New filter title keys `store/search.filter.title.dynamic-estimate` ("Estimate") and `store/search.filter.title.delivery-options` ("Delivery Option") across all locales (non-EN copy is a best-effort draft for the Localization team). The `shipping` group keeps its existing "Shipping" title. + ## [3.147.2] - 2026-06-05 ### Fixed diff --git a/messages/ar.json b/messages/ar.json index 4333e1898..fbe18a8b3 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "نطاقات السعر", "store/search.text": "عرض {from}-{to} من {recordsFiltered} نتائج", "store/search.filter.title.shipping": "الشحن", + "store/search.filter.title.dynamic-estimate": "التقدير", + "store/search.filter.title.delivery-options": "خيار التوصيل", "store/search.filter.shipping.name.delivery": "توصيل الى", "store/search.filter.shipping.name.pickup-in-point": "الاستلام في", "store/search.filter.shipping.name.pickup-nearby": "استلام بقرب", diff --git a/messages/bg.json b/messages/bg.json index f77c24cc3..1c7789e65 100644 --- a/messages/bg.json +++ b/messages/bg.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Ценови диапазони", "store/search.text": "Показване на {from}–{to} от {recordsFiltered} резултата", "store/search.filter.title.shipping": "Доставка", + "store/search.filter.title.dynamic-estimate": "Прогноза", + "store/search.filter.title.delivery-options": "Опция за доставка", "store/search.filter.shipping.name.delivery": "Доставка до", "store/search.filter.shipping.name.pickup-in-point": "Вземане от", "store/search.filter.shipping.name.pickup-nearby": "Вземане наблизо", diff --git a/messages/ca.json b/messages/ca.json index bdaf48276..1c102d516 100644 --- a/messages/ca.json +++ b/messages/ca.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Intervals de preus", "store/search.text": "S'estan mostrant de {from} a {to} de {recordsFiltered} resultats", "store/search.filter.title.shipping": "Enviament", + "store/search.filter.title.dynamic-estimate": "Estimació", + "store/search.filter.title.delivery-options": "Opció de lliurament", "store/search.filter.shipping.name.delivery": "Lliura a", "store/search.filter.shipping.name.pickup-in-point": "Recollida a", "store/search.filter.shipping.name.pickup-nearby": "Recollida a prop", diff --git a/messages/context.json b/messages/context.json index 1e04a95a3..8b745e3cb 100644 --- a/messages/context.json +++ b/messages/context.json @@ -66,6 +66,8 @@ "store/search.filter.title.brands": "Brands", "store/search.filter.title.price-ranges": "Price Ranges", "store/search.filter.title.shipping": "Shipping", + "store/search.filter.title.dynamic-estimate": "Heading for the Dynamic Estimate delivery filter group on the PLP: 'Estimate'", + "store/search.filter.title.delivery-options": "Heading for the Delivery Option filter group on the PLP: 'Delivery Option'", "store/search.filter.shipping.name.delivery": "Deliver to", "store/search.filter.shipping.name.pickup-in-point": "Pickup at", "store/search.filter.shipping.name.pickup-nearby": "Pickup nearby", diff --git a/messages/da.json b/messages/da.json index 1c6ede602..e6253f205 100644 --- a/messages/da.json +++ b/messages/da.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Prisintervaller", "store/search.text": "Viser {from}-{to} fra {recordsFiltered} optegnelser", "store/search.filter.title.shipping": "Forsendelse", + "store/search.filter.title.dynamic-estimate": "Estimat", + "store/search.filter.title.delivery-options": "Leveringsmulighed", "store/search.filter.shipping.name.delivery": "Lever til", "store/search.filter.shipping.name.pickup-in-point": "Afhentning ved", "store/search.filter.shipping.name.pickup-nearby": "Afhentning i nærheden", diff --git a/messages/de.json b/messages/de.json index b73663bdd..aa2d1a45f 100644 --- a/messages/de.json +++ b/messages/de.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Preisspannen", "store/search.text": "Anzeigen {from}-{to} aus {recordsFiltered}-Ergebnissen", "store/search.filter.title.shipping": "Versand", + "store/search.filter.title.dynamic-estimate": "Schätzung", + "store/search.filter.title.delivery-options": "Lieferoption", "store/search.filter.shipping.name.delivery": "Liefern an", "store/search.filter.shipping.name.pickup-in-point": "Abholung bei", "store/search.filter.shipping.name.pickup-nearby": "Abholung in der Nähe", diff --git a/messages/el.json b/messages/el.json index 4ef0c42bb..a23fad6b9 100644 --- a/messages/el.json +++ b/messages/el.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Εύρος τιμών", "store/search.text": "Γίνεται εμφάνιση {from}–{to} από {recordsFiltered} αποτελέσματα", "store/search.filter.title.shipping": "Μεταφορά", + "store/search.filter.title.dynamic-estimate": "Εκτίμηση", + "store/search.filter.title.delivery-options": "Επιλογή παράδοσης", "store/search.filter.shipping.name.delivery": "Παράδοση προς", "store/search.filter.shipping.name.pickup-in-point": "Παραλαβή σε", "store/search.filter.shipping.name.pickup-nearby": "Παραλαβή πλησίον", diff --git a/messages/en.json b/messages/en.json index 8a09211a8..9aa8863b4 100644 --- a/messages/en.json +++ b/messages/en.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Price ranges", "store/search.text": "Showing {from}–{to} of {recordsFiltered} results", "store/search.filter.title.shipping": "Shipping", + "store/search.filter.title.dynamic-estimate": "Estimate", + "store/search.filter.title.delivery-options": "Delivery Option", "store/search.filter.shipping.name.delivery": "Deliver to", "store/search.filter.shipping.name.pickup-in-point": "Pickup at", "store/search.filter.shipping.name.pickup-nearby": "Pickup nearby", diff --git a/messages/es.json b/messages/es.json index 4a91ce841..38320bf45 100644 --- a/messages/es.json +++ b/messages/es.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Rangos de precio", "store/search.text": "Mostrando {from}-{to} de {recordsFiltered} resultados", "store/search.filter.title.shipping": "Envío", + "store/search.filter.title.dynamic-estimate": "Estimación", + "store/search.filter.title.delivery-options": "Opción de entrega", "store/search.filter.shipping.name.delivery": "Entregar a", "store/search.filter.shipping.name.pickup-in-point": "Recogida en", "store/search.filter.shipping.name.pickup-nearby": "Recogida en tiendas cercanas", diff --git a/messages/fi.json b/messages/fi.json index 5837e43dd..1383a75e3 100644 --- a/messages/fi.json +++ b/messages/fi.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Hintaluokat", "store/search.text": "Näytetään {from}–{to} {recordsFiltered} tuloksesta", "store/search.filter.title.shipping": "Toimitus", + "store/search.filter.title.dynamic-estimate": "Arvio", + "store/search.filter.title.delivery-options": "Toimitusvaihtoehto", "store/search.filter.shipping.name.delivery": "Toimitus osoitteeseen", "store/search.filter.shipping.name.pickup-in-point": "Nouto myymälästä", "store/search.filter.shipping.name.pickup-nearby": "Nouto läheltä", diff --git a/messages/fr.json b/messages/fr.json index 332f23443..46527101c 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Gammes de prix", "store/search.text": "Afficher les {from}-{to} des {recordsFiltered} résultats", "store/search.filter.title.shipping": "Expédition", + "store/search.filter.title.dynamic-estimate": "Estimation", + "store/search.filter.title.delivery-options": "Option de livraison", "store/search.filter.shipping.name.delivery": "Livrer à", "store/search.filter.shipping.name.pickup-in-point": "Retrait à", "store/search.filter.shipping.name.pickup-nearby": "Retrait à proximité", diff --git a/messages/hu.json b/messages/hu.json index 9669415ea..3746612ee 100644 --- a/messages/hu.json +++ b/messages/hu.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Ártartományok", "store/search.text": "{from}-{to} eredmény megjelenítése a(z) {recordsFiltered} eredményből", "store/search.filter.title.shipping": "Szállítás", + "store/search.filter.title.dynamic-estimate": "Becslés", + "store/search.filter.title.delivery-options": "Szállítási lehetőség", "store/search.filter.shipping.name.delivery": "Szállítás ide", "store/search.filter.shipping.name.pickup-in-point": "Átvétel", "store/search.filter.shipping.name.pickup-nearby": "Átvétel a közelben", diff --git a/messages/id.json b/messages/id.json index a600f322d..5c2f89bcf 100644 --- a/messages/id.json +++ b/messages/id.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Rentang harga", "store/search.text": "Menampilka {from}–{to} dari {recordsFiltered} hasil", "store/search.filter.title.shipping": "Pengiriman", + "store/search.filter.title.dynamic-estimate": "Perkiraan", + "store/search.filter.title.delivery-options": "Opsi pengiriman", "store/search.filter.shipping.name.delivery": "Kirim ke", "store/search.filter.shipping.name.pickup-in-point": "Ambil di", "store/search.filter.shipping.name.pickup-nearby": "Pengambilan terdekat", diff --git a/messages/it.json b/messages/it.json index af0f9b76f..1dabe7d1e 100644 --- a/messages/it.json +++ b/messages/it.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Fasce di prezzo", "store/search.text": "Mostra {from}–{to} di {recordsFiltered} risultati", "store/search.filter.title.shipping": "Spedizione", + "store/search.filter.title.dynamic-estimate": "Stima", + "store/search.filter.title.delivery-options": "Opzione di consegna", "store/search.filter.shipping.name.delivery": "Consegna a", "store/search.filter.shipping.name.pickup-in-point": "Ritiro presso", "store/search.filter.shipping.name.pickup-nearby": "Ritiro nelle vicinanze", diff --git a/messages/ja.json b/messages/ja.json index 66c8f9fa4..5d71cc8b9 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "価格帯", "store/search.text": "{from}-{to} に該当する {recordsFiltered} の記録を表示中", "store/search.filter.title.shipping": "発送方法", + "store/search.filter.title.dynamic-estimate": "配送目安", + "store/search.filter.title.delivery-options": "配送オプション", "store/search.filter.shipping.name.delivery": "宛先", "store/search.filter.shipping.name.pickup-in-point": "集荷場所", "store/search.filter.shipping.name.pickup-nearby": "近くの集荷場所", diff --git a/messages/jp.json b/messages/jp.json index ed8988dbd..cde753149 100644 --- a/messages/jp.json +++ b/messages/jp.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "価格の範囲", "store/search.text": "{from}–{to} に該当する {recordsFiltered} の検索結果を表示中", "store/search.filter.title.shipping": "発送方法", + "store/search.filter.title.dynamic-estimate": "配送目安", + "store/search.filter.title.delivery-options": "配送オプション", "store/search.filter.shipping.name.delivery": "宛先", "store/search.filter.shipping.name.pickup-in-point": "集荷場所", "store/search.filter.shipping.name.pickup-nearby": "近くの集荷場所", diff --git a/messages/ko.json b/messages/ko.json index daf40312b..d380787f2 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "가격 범위", "store/search.text": "{recordsFiltered} 결과 중 {from}–{to} 표시", "store/search.filter.title.shipping": "배송", + "store/search.filter.title.dynamic-estimate": "예상", + "store/search.filter.title.delivery-options": "배송 옵션", "store/search.filter.shipping.name.delivery": "배송 대상", "store/search.filter.shipping.name.pickup-in-point": "픽업 장소", "store/search.filter.shipping.name.pickup-nearby": "근처 픽업", diff --git a/messages/nl.json b/messages/nl.json index e090550bd..28ca910af 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Prijsklasse", "store/search.text": "Toont {from}-{to} van {recordsFiltered} resultaten", "store/search.filter.title.shipping": "Verzending", + "store/search.filter.title.dynamic-estimate": "Schatting", + "store/search.filter.title.delivery-options": "Bezorgoptie", "store/search.filter.shipping.name.delivery": "Leveren aan", "store/search.filter.shipping.name.pickup-in-point": "Afhalen op", "store/search.filter.shipping.name.pickup-nearby": "Afhalen in de buurt van", diff --git a/messages/nn.json b/messages/nn.json index e89bc5cf2..1e2b67106 100644 --- a/messages/nn.json +++ b/messages/nn.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Viser {from}–{to} av {recordsFiltered} resultater", "store/search.filter.title.shipping": "Forsendelse", + "store/search.filter.title.dynamic-estimate": "Estimat", + "store/search.filter.title.delivery-options": "Leveringsalternativ", "store/search.filter.shipping.name.delivery": "Leveres til", "store/search.filter.shipping.name.pickup-in-point": "Hent hos", "store/search.filter.shipping.name.pickup-nearby": "Henting i nærheten", diff --git a/messages/no.json b/messages/no.json index e72a5f5c3..df85116a6 100644 --- a/messages/no.json +++ b/messages/no.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Viser {from}–{to} av {recordsFiltered} resultater", "store/search.filter.title.shipping": "Forsendelse", + "store/search.filter.title.dynamic-estimate": "Estimat", + "store/search.filter.title.delivery-options": "Leveringsalternativ", "store/search.filter.shipping.name.delivery": "Leveres til", "store/search.filter.shipping.name.pickup-in-point": "Hent hos", "store/search.filter.shipping.name.pickup-nearby": "Henting i nærheten", diff --git a/messages/pl.json b/messages/pl.json index 8a1e148c0..f0d8a437f 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Zakresy cenowe", "store/search.text": "Pokazuję {from}-{to} od {recordsFiltered} wpisów", "store/search.filter.title.shipping": "Wysyłka", + "store/search.filter.title.dynamic-estimate": "Szacowany czas", + "store/search.filter.title.delivery-options": "Opcja dostawy", "store/search.filter.shipping.name.delivery": "Dostarcz do", "store/search.filter.shipping.name.pickup-in-point": "Odbiór w", "store/search.filter.shipping.name.pickup-nearby": "Odbiór w pobliżu", diff --git a/messages/pt.json b/messages/pt.json index 8e46e7a9e..527096e04 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Faixas de preço", "store/search.text": "Exibindo {from}–{to} de {recordsFiltered} resultados", "store/search.filter.title.shipping": "Entrega", + "store/search.filter.title.dynamic-estimate": "Estimativa", + "store/search.filter.title.delivery-options": "Opção de entrega", "store/search.filter.shipping.name.delivery": "Entregar em", "store/search.filter.shipping.name.pickup-in-point": "Retirada em", "store/search.filter.shipping.name.pickup-nearby": "Retirada em lojas próximas", diff --git a/messages/ro.json b/messages/ro.json index e104162b9..9934cd89c 100644 --- a/messages/ro.json +++ b/messages/ro.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Intervale de prețuri", "store/search.text": "Afișează {from}-{to} de la {recordsFiltered} înregistrări", "store/search.filter.title.shipping": "Transport", + "store/search.filter.title.dynamic-estimate": "Estimare", + "store/search.filter.title.delivery-options": "Opțiune de livrare", "store/search.filter.shipping.name.delivery": "Livrează la", "store/search.filter.shipping.name.pickup-in-point": "Ridicare la", "store/search.filter.shipping.name.pickup-nearby": "Ridicare în apropiere", diff --git a/messages/ru.json b/messages/ru.json index d51af1a64..38ed6acfd 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Диапазоны цен", "store/search.text": "Показаны результаты {from}—{to} из {recordsFiltered}", "store/search.filter.title.shipping": "Отправка", + "store/search.filter.title.dynamic-estimate": "Оценка", + "store/search.filter.title.delivery-options": "Вариант доставки", "store/search.filter.shipping.name.delivery": "Место доставки", "store/search.filter.shipping.name.pickup-in-point": "Место самовывоза", "store/search.filter.shipping.name.pickup-nearby": "Самовывоз поблизости", diff --git a/messages/sk.json b/messages/sk.json index 94511f973..fe78fb8a3 100644 --- a/messages/sk.json +++ b/messages/sk.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Rozsahy cien", "store/search.text": "Zobrazuje sa {from} – {to} z/zo {recordsFiltered} záznamov", "store/search.filter.title.shipping": "Doprava", + "store/search.filter.title.dynamic-estimate": "Odhad", + "store/search.filter.title.delivery-options": "Možnosť doručenia", "store/search.filter.shipping.name.delivery": "Doručiť na", "store/search.filter.shipping.name.pickup-in-point": "Vyzdvihnúť na", "store/search.filter.shipping.name.pickup-nearby": "Vyzdvihnúť v blízosti", diff --git a/messages/sl.json b/messages/sl.json index 133a6a5b9..d834b1a7e 100644 --- a/messages/sl.json +++ b/messages/sl.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Cenovni razponi", "store/search.text": "Kažem {from}-{to} od {recordsFiltered} rezultatov", "store/search.filter.title.shipping": "Odpošiljanje", + "store/search.filter.title.dynamic-estimate": "Ocena", + "store/search.filter.title.delivery-options": "Možnost dostave", "store/search.filter.shipping.name.delivery": "Dostavi v", "store/search.filter.shipping.name.pickup-in-point": "Prevzemi pri", "store/search.filter.shipping.name.pickup-nearby": "Prevzemite blizu", diff --git a/messages/sv.json b/messages/sv.json index 6fa8d74bb..b0b221fcb 100644 --- a/messages/sv.json +++ b/messages/sv.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Visar {from}–{to} av {recordsFiltered} resultat", "store/search.filter.title.shipping": "Frakt", + "store/search.filter.title.dynamic-estimate": "Uppskattning", + "store/search.filter.title.delivery-options": "Leveransalternativ", "store/search.filter.shipping.name.delivery": "Leverera till", "store/search.filter.shipping.name.pickup-in-point": "Hämta vid", "store/search.filter.shipping.name.pickup-nearby": "Hämtning i närheten", diff --git a/messages/th.json b/messages/th.json index 2374a8fb9..82f818764 100644 --- a/messages/th.json +++ b/messages/th.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "ช่วงราคา", "store/search.text": "กำลังแสดงผล {from}–{to} ของ {recordsFiltered}", "store/search.filter.title.shipping": "การส่ง", + "store/search.filter.title.dynamic-estimate": "ประมาณการ", + "store/search.filter.title.delivery-options": "ตัวเลือกการจัดส่ง", "store/search.filter.shipping.name.delivery": "จัดส่งไปยัง", "store/search.filter.shipping.name.pickup-in-point": "จุดรับสินค้าเอง", "store/search.filter.shipping.name.pickup-nearby": "จุดรับสินค้าบริเวณใกล้เคียง", diff --git a/messages/uk.json b/messages/uk.json index aa1a82470..3e2a7e6fc 100644 --- a/messages/uk.json +++ b/messages/uk.json @@ -67,6 +67,8 @@ "store/search.filter.title.price-ranges": "Цінові діапазони", "store/search.text": "Показано результатів: {from}—{to} з {recordsFiltered}", "store/search.filter.title.shipping": "Відправлення", + "store/search.filter.title.dynamic-estimate": "Оцінка", + "store/search.filter.title.delivery-options": "Варіант доставки", "store/search.filter.shipping.name.delivery": "Місце доставки", "store/search.filter.shipping.name.pickup-in-point": "Місце самовивозу", "store/search.filter.shipping.name.pickup-nearby": "Самовивіз поблизу", diff --git a/react/__tests__/utils/getFilters.test.js b/react/__tests__/utils/getFilters.test.js new file mode 100644 index 000000000..1290c31a9 --- /dev/null +++ b/react/__tests__/utils/getFilters.test.js @@ -0,0 +1,106 @@ +import React from 'react' +import { IntlProvider } from 'react-intl' +import { renderHook } from '@testing-library/react-hooks' + +import getFilters, { + getDeliveryGroupTitle, + SHIPPING_TITLE, + DYNAMIC_ESTIMATE_TITLE, + DELIVERY_OPTION_TITLE, +} from '../../utils/getFilters' + +describe('getDeliveryGroupTitle', () => { + it('maps the shipping group to the shipping title id', () => { + expect(getDeliveryGroupTitle('shipping')).toBe(SHIPPING_TITLE) + }) + + it('maps the delivery-options group to the Delivery Option title id', () => { + expect(getDeliveryGroupTitle('delivery-options')).toBe( + DELIVERY_OPTION_TITLE + ) + }) + + it('maps the dynamic-estimate group to the Estimate title id', () => { + expect(getDeliveryGroupTitle('dynamic-estimate')).toBe( + DYNAMIC_ESTIMATE_TITLE + ) + }) + + it('falls back to the raw group name for unknown groups (never "Default Title")', () => { + expect(getDeliveryGroupTitle('delivery-window')).toBe('delivery-window') + expect(getDeliveryGroupTitle('delivery-window')).not.toBe('Default Title') + }) +}) + +describe('getFilters delivery group titles', () => { + const wrapper = ({ children }) => ( + {}}> + {children} + + ) + + const renderGetFilters = args => + renderHook(() => getFilters(args), { wrapper }).result.current + + const makeGroup = name => ({ + name, + type: 'DELIVERY', + quantity: 1, + facets: [{ key: name, name: 'option', value: 'option', map: name }], + }) + + it('titles dynamic-estimate and delivery-options even when no shipping group is present', () => { + const filters = renderGetFilters({ + deliveries: [ + makeGroup('dynamic-estimate'), + makeGroup('delivery-options'), + ], + }) + + const estimate = filters.find(filter => filter.name === 'dynamic-estimate') + const deliveryOption = filters.find( + filter => filter.name === 'delivery-options' + ) + + expect(estimate.title).toBe(DYNAMIC_ESTIMATE_TITLE) + expect(deliveryOption.title).toBe(DELIVERY_OPTION_TITLE) + expect(estimate.title).not.toBe('Default Title') + expect(deliveryOption.title).not.toBe('Default Title') + }) + + it('titles the shipping group with the shipping title id', () => { + const filters = renderGetFilters({ + deliveries: [ + { + name: 'shipping', + type: 'DELIVERY', + quantity: 1, + facets: [ + { + key: 'shipping', + name: 'delivery', + value: 'delivery', + map: 'shipping', + }, + ], + }, + ], + showShippingMethodFacet: true, + }) + + const shipping = filters.find(filter => filter.name === 'shipping') + + expect(shipping.title).toBe(SHIPPING_TITLE) + }) + + it('falls back to the raw name for an unknown delivery group', () => { + const filters = renderGetFilters({ + deliveries: [makeGroup('delivery-window')], + }) + + const unknown = filters.find(filter => filter.name === 'delivery-window') + + expect(unknown.title).toBe('delivery-window') + expect(unknown.title).not.toBe('Default Title') + }) +}) diff --git a/react/utils/getFilters.js b/react/utils/getFilters.js index 0ae7b7f40..bfa4143c2 100644 --- a/react/utils/getFilters.js +++ b/react/utils/getFilters.js @@ -5,6 +5,10 @@ export const SHIPPING_TITLE = 'store/search.filter.title.shipping' export const CATEGORIES_TITLE = 'store/search.filter.title.categories' export const BRANDS_TITLE = 'store/search.filter.title.brands' export const PRICE_RANGES_TITLE = 'store/search.filter.title.price-ranges' +export const DYNAMIC_ESTIMATE_TITLE = + 'store/search.filter.title.dynamic-estimate' +export const DELIVERY_OPTION_TITLE = + 'store/search.filter.title.delivery-options' export const shippingOptions = { delivery: 'store/search.filter.shipping.name.delivery', @@ -15,6 +19,15 @@ export const shippingOptions = { export const SHIPPING_KEY = 'shipping' +const DELIVERY_GROUP_TITLES = { + [SHIPPING_KEY]: SHIPPING_TITLE, + 'delivery-options': DELIVERY_OPTION_TITLE, + 'dynamic-estimate': DYNAMIC_ESTIMATE_TITLE, +} + +/** Maps a delivery group name to its heading message id; unknown groups fall back to the raw name. */ +export const getDeliveryGroupTitle = name => DELIVERY_GROUP_TITLES[name] ?? name + /** Delivery option facet for PLP URL after postal modal (shipping group from API). */ export function buildDeliveryShippingFacetForNavigation(deliveries, intl) { const shipping = deliveries?.find(d => d.name === SHIPPING_KEY) @@ -41,21 +54,11 @@ const SPECIFICATION_FILTERS_TYPE = 'SpecificationFilters' const defaultShippingValues = ['delivery', 'pickup-in-point', 'pickup-nearby'] -const getDeliveriesFormatted = ( - deliveries, - availableShippingValues, - showShippingFacet -) => { - // eslint-disable-next-line react-hooks/rules-of-hooks - const intl = useIntl() - const shipping = deliveries.find(d => d.name === SHIPPING_KEY) - - if (!shipping) { - return deliveries - } +const formatDeliveryGroup = (group, intl, availableShippingValues) => { + const titled = { ...group, title: getDeliveryGroupTitle(group.name) } - if (!showShippingFacet) { - return deliveries.filter(d => d.name !== SHIPPING_KEY) + if (group.name !== SHIPPING_KEY) { + return titled } const shippingValues = @@ -63,19 +66,31 @@ const getDeliveriesFormatted = ( ? availableShippingValues : defaultShippingValues - const shippingFormatted = { - ...shipping, - title: SHIPPING_TITLE, - facets: shipping.facets + return { + ...titled, + facets: group.facets .filter(facet => shippingValues.includes(facet.name)) .map(facet => ({ ...facet, name: intl.formatMessage({ id: shippingOptions[facet.name] }), })), } +} + +const getDeliveriesFormatted = ( + deliveries, + availableShippingValues, + showShippingFacet +) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const intl = useIntl() + + const visibleDeliveries = showShippingFacet + ? deliveries + : deliveries.filter(d => d.name !== SHIPPING_KEY) - return deliveries.map(facet => - facet.name === SHIPPING_KEY ? shippingFormatted : facet + return visibleDeliveries.map(group => + formatDeliveryGroup(group, intl, availableShippingValues) ) } From d1c88a02e1440c93a86e62f58dab4e6566d85ff2 Mon Sep 17 00:00:00 2001 From: Hiago Lucas Cardeal de Melo Silva Date: Fri, 12 Jun 2026 12:10:27 -0300 Subject: [PATCH 2/3] feat: render dynamic-estimate filter with no title and no collapsible header The Estimate (dynamic-estimate) delivery filter group now renders its options directly, with no group title and no collapsible header, on both desktop and mobile. Other delivery groups are unaffected. - getFilters tags each delivery group with a `hideHeader` flag (true only for dynamic-estimate) alongside its title. The flag is threaded through AvailableFilters -> SearchFilter -> FilterOptionTemplate (desktop) and AccordionFilterContainer -> AccordionFilterGroup -> AccordionFilterItem (mobile); when set, both paths skip the title/caret header and render the options always-expanded. - Remove the now-unused store/search.filter.title.dynamic-estimate key from all locales and context.json. delivery-options keeps its title; shipping keeps "Shipping". - Update getFilters unit tests to assert the hideHeader flag. Co-authored-by: Cursor --- CHANGELOG.md | 12 ++- messages/ar.json | 1 - messages/bg.json | 1 - messages/ca.json | 1 - messages/context.json | 1 - messages/da.json | 1 - messages/de.json | 1 - messages/el.json | 1 - messages/en.json | 1 - messages/es.json | 1 - messages/fi.json | 1 - messages/fr.json | 1 - messages/hu.json | 1 - messages/id.json | 1 - messages/it.json | 1 - messages/ja.json | 1 - messages/jp.json | 1 - messages/ko.json | 1 - messages/nl.json | 1 - messages/nn.json | 1 - messages/no.json | 1 - messages/pl.json | 1 - messages/pt.json | 1 - messages/ro.json | 1 - messages/ru.json | 1 - messages/sk.json | 1 - messages/sl.json | 1 - messages/sv.json | 1 - messages/th.json | 1 - messages/uk.json | 1 - react/__tests__/utils/getFilters.test.js | 29 +++--- react/components/AccordionFilterContainer.js | 1 + react/components/AccordionFilterGroup.js | 2 + react/components/AccordionFilterItem.js | 9 +- react/components/AvailableFilters.js | 10 +- react/components/FilterOptionTemplate.js | 99 +++++++++++--------- react/components/SearchFilter.js | 5 + react/utils/getFilters.js | 14 ++- 38 files changed, 115 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae6b0236b..edcf62250 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed -- Delivery filter groups `dynamic-estimate` and `delivery-options` no longer render the placeholder "Default Title" as their heading. They are now titled "Estimate" and "Delivery Option" respectively. Titles are assigned to every delivery group in `getFilters`, including the code path where no `shipping` group is present. +- Delivery filter group `delivery-options` no longer renders the placeholder "Default Title" as its heading. It is now titled "Delivery Option". Titles are assigned to every titled delivery group in `getFilters`, including the code path where no `shipping` group is present. + +### Changed + +- The `dynamic-estimate` (Estimate) delivery filter group now renders its options with **no title and no collapsible header**, on both desktop and mobile. Its options are always visible instead of being hidden behind a collapsible heading. ### Added -- New filter title keys `store/search.filter.title.dynamic-estimate` ("Estimate") and `store/search.filter.title.delivery-options` ("Delivery Option") across all locales (non-EN copy is a best-effort draft for the Localization team). The `shipping` group keeps its existing "Shipping" title. +- New filter title key `store/search.filter.title.delivery-options` ("Delivery Option") across all locales (non-EN copy is a best-effort draft for the Localization team). The `shipping` group keeps its existing "Shipping" title. + +### Removed + +- Unused filter title key `store/search.filter.title.dynamic-estimate` (the Estimate group no longer shows a title). ## [3.147.2] - 2026-06-05 diff --git a/messages/ar.json b/messages/ar.json index fbe18a8b3..ab9883ba4 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "نطاقات السعر", "store/search.text": "عرض {from}-{to} من {recordsFiltered} نتائج", "store/search.filter.title.shipping": "الشحن", - "store/search.filter.title.dynamic-estimate": "التقدير", "store/search.filter.title.delivery-options": "خيار التوصيل", "store/search.filter.shipping.name.delivery": "توصيل الى", "store/search.filter.shipping.name.pickup-in-point": "الاستلام في", diff --git a/messages/bg.json b/messages/bg.json index 1c7789e65..7e3ef38ee 100644 --- a/messages/bg.json +++ b/messages/bg.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Ценови диапазони", "store/search.text": "Показване на {from}–{to} от {recordsFiltered} резултата", "store/search.filter.title.shipping": "Доставка", - "store/search.filter.title.dynamic-estimate": "Прогноза", "store/search.filter.title.delivery-options": "Опция за доставка", "store/search.filter.shipping.name.delivery": "Доставка до", "store/search.filter.shipping.name.pickup-in-point": "Вземане от", diff --git a/messages/ca.json b/messages/ca.json index 1c102d516..e12d16271 100644 --- a/messages/ca.json +++ b/messages/ca.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Intervals de preus", "store/search.text": "S'estan mostrant de {from} a {to} de {recordsFiltered} resultats", "store/search.filter.title.shipping": "Enviament", - "store/search.filter.title.dynamic-estimate": "Estimació", "store/search.filter.title.delivery-options": "Opció de lliurament", "store/search.filter.shipping.name.delivery": "Lliura a", "store/search.filter.shipping.name.pickup-in-point": "Recollida a", diff --git a/messages/context.json b/messages/context.json index 8b745e3cb..412751c63 100644 --- a/messages/context.json +++ b/messages/context.json @@ -66,7 +66,6 @@ "store/search.filter.title.brands": "Brands", "store/search.filter.title.price-ranges": "Price Ranges", "store/search.filter.title.shipping": "Shipping", - "store/search.filter.title.dynamic-estimate": "Heading for the Dynamic Estimate delivery filter group on the PLP: 'Estimate'", "store/search.filter.title.delivery-options": "Heading for the Delivery Option filter group on the PLP: 'Delivery Option'", "store/search.filter.shipping.name.delivery": "Deliver to", "store/search.filter.shipping.name.pickup-in-point": "Pickup at", diff --git a/messages/da.json b/messages/da.json index e6253f205..ef79790cc 100644 --- a/messages/da.json +++ b/messages/da.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Prisintervaller", "store/search.text": "Viser {from}-{to} fra {recordsFiltered} optegnelser", "store/search.filter.title.shipping": "Forsendelse", - "store/search.filter.title.dynamic-estimate": "Estimat", "store/search.filter.title.delivery-options": "Leveringsmulighed", "store/search.filter.shipping.name.delivery": "Lever til", "store/search.filter.shipping.name.pickup-in-point": "Afhentning ved", diff --git a/messages/de.json b/messages/de.json index aa2d1a45f..3444fd6de 100644 --- a/messages/de.json +++ b/messages/de.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Preisspannen", "store/search.text": "Anzeigen {from}-{to} aus {recordsFiltered}-Ergebnissen", "store/search.filter.title.shipping": "Versand", - "store/search.filter.title.dynamic-estimate": "Schätzung", "store/search.filter.title.delivery-options": "Lieferoption", "store/search.filter.shipping.name.delivery": "Liefern an", "store/search.filter.shipping.name.pickup-in-point": "Abholung bei", diff --git a/messages/el.json b/messages/el.json index a23fad6b9..d5a0d823b 100644 --- a/messages/el.json +++ b/messages/el.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Εύρος τιμών", "store/search.text": "Γίνεται εμφάνιση {from}–{to} από {recordsFiltered} αποτελέσματα", "store/search.filter.title.shipping": "Μεταφορά", - "store/search.filter.title.dynamic-estimate": "Εκτίμηση", "store/search.filter.title.delivery-options": "Επιλογή παράδοσης", "store/search.filter.shipping.name.delivery": "Παράδοση προς", "store/search.filter.shipping.name.pickup-in-point": "Παραλαβή σε", diff --git a/messages/en.json b/messages/en.json index 9aa8863b4..35c5786db 100644 --- a/messages/en.json +++ b/messages/en.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Price ranges", "store/search.text": "Showing {from}–{to} of {recordsFiltered} results", "store/search.filter.title.shipping": "Shipping", - "store/search.filter.title.dynamic-estimate": "Estimate", "store/search.filter.title.delivery-options": "Delivery Option", "store/search.filter.shipping.name.delivery": "Deliver to", "store/search.filter.shipping.name.pickup-in-point": "Pickup at", diff --git a/messages/es.json b/messages/es.json index 38320bf45..dba0bc0ed 100644 --- a/messages/es.json +++ b/messages/es.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Rangos de precio", "store/search.text": "Mostrando {from}-{to} de {recordsFiltered} resultados", "store/search.filter.title.shipping": "Envío", - "store/search.filter.title.dynamic-estimate": "Estimación", "store/search.filter.title.delivery-options": "Opción de entrega", "store/search.filter.shipping.name.delivery": "Entregar a", "store/search.filter.shipping.name.pickup-in-point": "Recogida en", diff --git a/messages/fi.json b/messages/fi.json index 1383a75e3..e4b055c89 100644 --- a/messages/fi.json +++ b/messages/fi.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Hintaluokat", "store/search.text": "Näytetään {from}–{to} {recordsFiltered} tuloksesta", "store/search.filter.title.shipping": "Toimitus", - "store/search.filter.title.dynamic-estimate": "Arvio", "store/search.filter.title.delivery-options": "Toimitusvaihtoehto", "store/search.filter.shipping.name.delivery": "Toimitus osoitteeseen", "store/search.filter.shipping.name.pickup-in-point": "Nouto myymälästä", diff --git a/messages/fr.json b/messages/fr.json index 46527101c..54aa2b6e9 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Gammes de prix", "store/search.text": "Afficher les {from}-{to} des {recordsFiltered} résultats", "store/search.filter.title.shipping": "Expédition", - "store/search.filter.title.dynamic-estimate": "Estimation", "store/search.filter.title.delivery-options": "Option de livraison", "store/search.filter.shipping.name.delivery": "Livrer à", "store/search.filter.shipping.name.pickup-in-point": "Retrait à", diff --git a/messages/hu.json b/messages/hu.json index 3746612ee..aa1f8023e 100644 --- a/messages/hu.json +++ b/messages/hu.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Ártartományok", "store/search.text": "{from}-{to} eredmény megjelenítése a(z) {recordsFiltered} eredményből", "store/search.filter.title.shipping": "Szállítás", - "store/search.filter.title.dynamic-estimate": "Becslés", "store/search.filter.title.delivery-options": "Szállítási lehetőség", "store/search.filter.shipping.name.delivery": "Szállítás ide", "store/search.filter.shipping.name.pickup-in-point": "Átvétel", diff --git a/messages/id.json b/messages/id.json index 5c2f89bcf..202fac7f7 100644 --- a/messages/id.json +++ b/messages/id.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Rentang harga", "store/search.text": "Menampilka {from}–{to} dari {recordsFiltered} hasil", "store/search.filter.title.shipping": "Pengiriman", - "store/search.filter.title.dynamic-estimate": "Perkiraan", "store/search.filter.title.delivery-options": "Opsi pengiriman", "store/search.filter.shipping.name.delivery": "Kirim ke", "store/search.filter.shipping.name.pickup-in-point": "Ambil di", diff --git a/messages/it.json b/messages/it.json index 1dabe7d1e..8f8c6136f 100644 --- a/messages/it.json +++ b/messages/it.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Fasce di prezzo", "store/search.text": "Mostra {from}–{to} di {recordsFiltered} risultati", "store/search.filter.title.shipping": "Spedizione", - "store/search.filter.title.dynamic-estimate": "Stima", "store/search.filter.title.delivery-options": "Opzione di consegna", "store/search.filter.shipping.name.delivery": "Consegna a", "store/search.filter.shipping.name.pickup-in-point": "Ritiro presso", diff --git a/messages/ja.json b/messages/ja.json index 5d71cc8b9..c19d635ba 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "価格帯", "store/search.text": "{from}-{to} に該当する {recordsFiltered} の記録を表示中", "store/search.filter.title.shipping": "発送方法", - "store/search.filter.title.dynamic-estimate": "配送目安", "store/search.filter.title.delivery-options": "配送オプション", "store/search.filter.shipping.name.delivery": "宛先", "store/search.filter.shipping.name.pickup-in-point": "集荷場所", diff --git a/messages/jp.json b/messages/jp.json index cde753149..15d725d60 100644 --- a/messages/jp.json +++ b/messages/jp.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "価格の範囲", "store/search.text": "{from}–{to} に該当する {recordsFiltered} の検索結果を表示中", "store/search.filter.title.shipping": "発送方法", - "store/search.filter.title.dynamic-estimate": "配送目安", "store/search.filter.title.delivery-options": "配送オプション", "store/search.filter.shipping.name.delivery": "宛先", "store/search.filter.shipping.name.pickup-in-point": "集荷場所", diff --git a/messages/ko.json b/messages/ko.json index d380787f2..f6881e879 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "가격 범위", "store/search.text": "{recordsFiltered} 결과 중 {from}–{to} 표시", "store/search.filter.title.shipping": "배송", - "store/search.filter.title.dynamic-estimate": "예상", "store/search.filter.title.delivery-options": "배송 옵션", "store/search.filter.shipping.name.delivery": "배송 대상", "store/search.filter.shipping.name.pickup-in-point": "픽업 장소", diff --git a/messages/nl.json b/messages/nl.json index 28ca910af..548a120c6 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Prijsklasse", "store/search.text": "Toont {from}-{to} van {recordsFiltered} resultaten", "store/search.filter.title.shipping": "Verzending", - "store/search.filter.title.dynamic-estimate": "Schatting", "store/search.filter.title.delivery-options": "Bezorgoptie", "store/search.filter.shipping.name.delivery": "Leveren aan", "store/search.filter.shipping.name.pickup-in-point": "Afhalen op", diff --git a/messages/nn.json b/messages/nn.json index 1e2b67106..df5a63149 100644 --- a/messages/nn.json +++ b/messages/nn.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Viser {from}–{to} av {recordsFiltered} resultater", "store/search.filter.title.shipping": "Forsendelse", - "store/search.filter.title.dynamic-estimate": "Estimat", "store/search.filter.title.delivery-options": "Leveringsalternativ", "store/search.filter.shipping.name.delivery": "Leveres til", "store/search.filter.shipping.name.pickup-in-point": "Hent hos", diff --git a/messages/no.json b/messages/no.json index df85116a6..0f666a558 100644 --- a/messages/no.json +++ b/messages/no.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Viser {from}–{to} av {recordsFiltered} resultater", "store/search.filter.title.shipping": "Forsendelse", - "store/search.filter.title.dynamic-estimate": "Estimat", "store/search.filter.title.delivery-options": "Leveringsalternativ", "store/search.filter.shipping.name.delivery": "Leveres til", "store/search.filter.shipping.name.pickup-in-point": "Hent hos", diff --git a/messages/pl.json b/messages/pl.json index f0d8a437f..4618024e9 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Zakresy cenowe", "store/search.text": "Pokazuję {from}-{to} od {recordsFiltered} wpisów", "store/search.filter.title.shipping": "Wysyłka", - "store/search.filter.title.dynamic-estimate": "Szacowany czas", "store/search.filter.title.delivery-options": "Opcja dostawy", "store/search.filter.shipping.name.delivery": "Dostarcz do", "store/search.filter.shipping.name.pickup-in-point": "Odbiór w", diff --git a/messages/pt.json b/messages/pt.json index 527096e04..28c8d2603 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Faixas de preço", "store/search.text": "Exibindo {from}–{to} de {recordsFiltered} resultados", "store/search.filter.title.shipping": "Entrega", - "store/search.filter.title.dynamic-estimate": "Estimativa", "store/search.filter.title.delivery-options": "Opção de entrega", "store/search.filter.shipping.name.delivery": "Entregar em", "store/search.filter.shipping.name.pickup-in-point": "Retirada em", diff --git a/messages/ro.json b/messages/ro.json index 9934cd89c..35abaebf1 100644 --- a/messages/ro.json +++ b/messages/ro.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Intervale de prețuri", "store/search.text": "Afișează {from}-{to} de la {recordsFiltered} înregistrări", "store/search.filter.title.shipping": "Transport", - "store/search.filter.title.dynamic-estimate": "Estimare", "store/search.filter.title.delivery-options": "Opțiune de livrare", "store/search.filter.shipping.name.delivery": "Livrează la", "store/search.filter.shipping.name.pickup-in-point": "Ridicare la", diff --git a/messages/ru.json b/messages/ru.json index 38ed6acfd..86448681c 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Диапазоны цен", "store/search.text": "Показаны результаты {from}—{to} из {recordsFiltered}", "store/search.filter.title.shipping": "Отправка", - "store/search.filter.title.dynamic-estimate": "Оценка", "store/search.filter.title.delivery-options": "Вариант доставки", "store/search.filter.shipping.name.delivery": "Место доставки", "store/search.filter.shipping.name.pickup-in-point": "Место самовывоза", diff --git a/messages/sk.json b/messages/sk.json index fe78fb8a3..a6d783df1 100644 --- a/messages/sk.json +++ b/messages/sk.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Rozsahy cien", "store/search.text": "Zobrazuje sa {from} – {to} z/zo {recordsFiltered} záznamov", "store/search.filter.title.shipping": "Doprava", - "store/search.filter.title.dynamic-estimate": "Odhad", "store/search.filter.title.delivery-options": "Možnosť doručenia", "store/search.filter.shipping.name.delivery": "Doručiť na", "store/search.filter.shipping.name.pickup-in-point": "Vyzdvihnúť na", diff --git a/messages/sl.json b/messages/sl.json index d834b1a7e..3302f596d 100644 --- a/messages/sl.json +++ b/messages/sl.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Cenovni razponi", "store/search.text": "Kažem {from}-{to} od {recordsFiltered} rezultatov", "store/search.filter.title.shipping": "Odpošiljanje", - "store/search.filter.title.dynamic-estimate": "Ocena", "store/search.filter.title.delivery-options": "Možnost dostave", "store/search.filter.shipping.name.delivery": "Dostavi v", "store/search.filter.shipping.name.pickup-in-point": "Prevzemi pri", diff --git a/messages/sv.json b/messages/sv.json index b0b221fcb..a50d1f9fa 100644 --- a/messages/sv.json +++ b/messages/sv.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Visar {from}–{to} av {recordsFiltered} resultat", "store/search.filter.title.shipping": "Frakt", - "store/search.filter.title.dynamic-estimate": "Uppskattning", "store/search.filter.title.delivery-options": "Leveransalternativ", "store/search.filter.shipping.name.delivery": "Leverera till", "store/search.filter.shipping.name.pickup-in-point": "Hämta vid", diff --git a/messages/th.json b/messages/th.json index 82f818764..f5f76a788 100644 --- a/messages/th.json +++ b/messages/th.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "ช่วงราคา", "store/search.text": "กำลังแสดงผล {from}–{to} ของ {recordsFiltered}", "store/search.filter.title.shipping": "การส่ง", - "store/search.filter.title.dynamic-estimate": "ประมาณการ", "store/search.filter.title.delivery-options": "ตัวเลือกการจัดส่ง", "store/search.filter.shipping.name.delivery": "จัดส่งไปยัง", "store/search.filter.shipping.name.pickup-in-point": "จุดรับสินค้าเอง", diff --git a/messages/uk.json b/messages/uk.json index 3e2a7e6fc..4bc7ae9c7 100644 --- a/messages/uk.json +++ b/messages/uk.json @@ -67,7 +67,6 @@ "store/search.filter.title.price-ranges": "Цінові діапазони", "store/search.text": "Показано результатів: {from}—{to} з {recordsFiltered}", "store/search.filter.title.shipping": "Відправлення", - "store/search.filter.title.dynamic-estimate": "Оцінка", "store/search.filter.title.delivery-options": "Варіант доставки", "store/search.filter.shipping.name.delivery": "Місце доставки", "store/search.filter.shipping.name.pickup-in-point": "Місце самовивозу", diff --git a/react/__tests__/utils/getFilters.test.js b/react/__tests__/utils/getFilters.test.js index 1290c31a9..a538108ca 100644 --- a/react/__tests__/utils/getFilters.test.js +++ b/react/__tests__/utils/getFilters.test.js @@ -4,8 +4,8 @@ import { renderHook } from '@testing-library/react-hooks' import getFilters, { getDeliveryGroupTitle, + shouldHideDeliveryGroupHeader, SHIPPING_TITLE, - DYNAMIC_ESTIMATE_TITLE, DELIVERY_OPTION_TITLE, } from '../../utils/getFilters' @@ -20,18 +20,21 @@ describe('getDeliveryGroupTitle', () => { ) }) - it('maps the dynamic-estimate group to the Estimate title id', () => { - expect(getDeliveryGroupTitle('dynamic-estimate')).toBe( - DYNAMIC_ESTIMATE_TITLE - ) - }) - it('falls back to the raw group name for unknown groups (never "Default Title")', () => { expect(getDeliveryGroupTitle('delivery-window')).toBe('delivery-window') expect(getDeliveryGroupTitle('delivery-window')).not.toBe('Default Title') }) }) +describe('shouldHideDeliveryGroupHeader', () => { + it('hides the header only for the dynamic-estimate group', () => { + expect(shouldHideDeliveryGroupHeader('dynamic-estimate')).toBe(true) + expect(shouldHideDeliveryGroupHeader('delivery-options')).toBe(false) + expect(shouldHideDeliveryGroupHeader('shipping')).toBe(false) + expect(shouldHideDeliveryGroupHeader('delivery-window')).toBe(false) + }) +}) + describe('getFilters delivery group titles', () => { const wrapper = ({ children }) => ( {}}> @@ -49,7 +52,7 @@ describe('getFilters delivery group titles', () => { facets: [{ key: name, name: 'option', value: 'option', map: name }], }) - it('titles dynamic-estimate and delivery-options even when no shipping group is present', () => { + it('hides the header for dynamic-estimate and titles delivery-options even when no shipping group is present', () => { const filters = renderGetFilters({ deliveries: [ makeGroup('dynamic-estimate'), @@ -62,13 +65,13 @@ describe('getFilters delivery group titles', () => { filter => filter.name === 'delivery-options' ) - expect(estimate.title).toBe(DYNAMIC_ESTIMATE_TITLE) + expect(estimate.hideHeader).toBe(true) + expect(deliveryOption.hideHeader).toBe(false) expect(deliveryOption.title).toBe(DELIVERY_OPTION_TITLE) - expect(estimate.title).not.toBe('Default Title') expect(deliveryOption.title).not.toBe('Default Title') }) - it('titles the shipping group with the shipping title id', () => { + it('titles the shipping group with the shipping title id and keeps its header', () => { const filters = renderGetFilters({ deliveries: [ { @@ -91,9 +94,10 @@ describe('getFilters delivery group titles', () => { const shipping = filters.find(filter => filter.name === 'shipping') expect(shipping.title).toBe(SHIPPING_TITLE) + expect(shipping.hideHeader).toBe(false) }) - it('falls back to the raw name for an unknown delivery group', () => { + it('falls back to the raw name for an unknown delivery group and keeps its header', () => { const filters = renderGetFilters({ deliveries: [makeGroup('delivery-window')], }) @@ -102,5 +106,6 @@ describe('getFilters delivery group titles', () => { expect(unknown.title).toBe('delivery-window') expect(unknown.title).not.toBe('Default Title') + expect(unknown.hideHeader).toBe(false) }) }) diff --git a/react/components/AccordionFilterContainer.js b/react/components/AccordionFilterContainer.js index 127272f22..014b319d3 100644 --- a/react/components/AccordionFilterContainer.js +++ b/react/components/AccordionFilterContainer.js @@ -193,6 +193,7 @@ const AccordionFilterContainer = ({ title={filter.title} facets={filter.facets} quantity={filter.quantity} + hideHeader={filter.hideHeader} key={title} className={itemClassName} open={isOpen} diff --git a/react/components/AccordionFilterGroup.js b/react/components/AccordionFilterGroup.js index 1f49ea745..0efb0a7bb 100644 --- a/react/components/AccordionFilterGroup.js +++ b/react/components/AccordionFilterGroup.js @@ -34,6 +34,7 @@ const AccordionFilterGroup = ({ setTruncatedFacetsFetched, onClearFilter, showClearByFilter, + hideHeader, onOpenPostalCodeModal, onOpenPickupModal, }) => { @@ -56,6 +57,7 @@ const AccordionFilterGroup = ({ title={title} open={open} show={show} + hideHeader={hideHeader} onOpen={onOpen} selectedFilters={selectedFilters} appliedFiltersOverview={appliedFiltersOverview} diff --git a/react/components/AccordionFilterItem.js b/react/components/AccordionFilterItem.js index d395f2c53..889171a42 100644 --- a/react/components/AccordionFilterItem.js +++ b/react/components/AccordionFilterItem.js @@ -37,6 +37,7 @@ const AccordionFilterItem = ({ facetKey, showClearByFilter, quantity, + hideHeader = false, }) => { const intl = useIntl() const handles = useCssHandles(CSS_HANDLES) @@ -64,7 +65,7 @@ const AccordionFilterItem = ({ return ( - {(!open || isNavigationCollapsible) && ( + {!hideHeader && (!open || isNavigationCollapsible) && (
)} {!isNavigationCollapsible ? ( - open && children + (hideHeader ? show : open) && children + ) : hideHeader ? ( +
{children}
) : (
{children}
@@ -187,6 +190,8 @@ AccordionFilterItem.propTypes = { facetKey: PropTypes.string, /** Whether a clear button that clear all options in a specific filter should appear beside the filter's name (true) or not (false). */ showClearByFilter: PropTypes.bool, + /** When `true`, renders the options with no title and no collapsible header. */ + hideHeader: PropTypes.bool, } export default AccordionFilterItem diff --git a/react/components/AvailableFilters.js b/react/components/AvailableFilters.js index 027977ba6..87f04bef9 100644 --- a/react/components/AvailableFilters.js +++ b/react/components/AvailableFilters.js @@ -42,7 +42,14 @@ const Filter = ({ onOpenPostalCodeModal, onOpenPickupModal, }) => { - const { type, title, facets, quantity, oneSelectedCollapse = false } = filter + const { + type, + title, + facets, + quantity, + oneSelectedCollapse = false, + hideHeader = false, + } = filter switch (type) { case 'PriceRanges': @@ -69,6 +76,7 @@ const Filter = ({ title={title} facets={facets} quantity={quantity} + hideHeader={hideHeader} oneSelectedCollapse={oneSelectedCollapse} preventRouteChange={preventRouteChange} initiallyCollapsed={initiallyCollapsed} diff --git a/react/components/FilterOptionTemplate.js b/react/components/FilterOptionTemplate.js index a580b0e6e..05f3f979c 100644 --- a/react/components/FilterOptionTemplate.js +++ b/react/components/FilterOptionTemplate.js @@ -80,6 +80,7 @@ const FilterOptionTemplate = ({ title, quantity, collapsable = true, + hideHeader = false, children, filters, initiallyCollapsed = false, @@ -182,7 +183,11 @@ const FilterOptionTemplate = ({ }) const hasScrolled = useHasScrolled(scrollable) - const isOpen = openFiltersMode === 'many' ? open : lastOpenFilter === title + const isOpen = hideHeader + ? true + : openFiltersMode === 'many' + ? open + : lastOpenFilter === title const filteredFacets = useMemo(() => { if (thresholdForFacetSearch === undefined || searchTerm === '') { @@ -339,54 +344,56 @@ const FilterOptionTemplate = ({ return (
-
-
collapsable && handleCollapse()} - onKeyDown={handleKeyDown} - aria-disabled={!collapsable} - > -
- - {title} - {isClearButtonVisible && ( - - { - e.stopPropagation() - - handleClear ? handleClear() : onClear() - }} - > - - - - )} - - {collapsable && ( - +
collapsable && handleCollapse()} + onKeyDown={handleKeyDown} + aria-disabled={!collapsable} + > +
+ + {title} + {isClearButtonVisible && ( + + { + e.stopPropagation() + + handleClear ? handleClear() : onClear() + }} + > + + + )} - > - - )} + {collapsable && ( + + + + )} +
+ {appliedFiltersOverview === 'show' && filters && !selected && ( +
+ {filters + .filter(facet => facet.selected) + .map(facet => facet.name) + .join(', ')} +
+ )}
- {appliedFiltersOverview === 'show' && filters && !selected && ( -
- {filters - .filter(facet => facet.selected) - .map(facet => facet.name) - .join(', ')} -
- )} -
+ )}
DELIVERY_GROUP_TITLES[name] ?? name +/** The dynamic-estimate group renders its options with no title and no collapsible header. */ +export const shouldHideDeliveryGroupHeader = name => + name === DYNAMIC_ESTIMATE_KEY + /** Delivery option facet for PLP URL after postal modal (shipping group from API). */ export function buildDeliveryShippingFacetForNavigation(deliveries, intl) { const shipping = deliveries?.find(d => d.name === SHIPPING_KEY) @@ -55,7 +57,11 @@ const SPECIFICATION_FILTERS_TYPE = 'SpecificationFilters' const defaultShippingValues = ['delivery', 'pickup-in-point', 'pickup-nearby'] const formatDeliveryGroup = (group, intl, availableShippingValues) => { - const titled = { ...group, title: getDeliveryGroupTitle(group.name) } + const titled = { + ...group, + title: getDeliveryGroupTitle(group.name), + hideHeader: shouldHideDeliveryGroupHeader(group.name), + } if (group.name !== SHIPPING_KEY) { return titled From cd23b21f255421b8c191b74704568d3e47cf9e18 Mon Sep 17 00:00:00 2001 From: Hiago Lucas Cardeal de Melo Silva Date: Fri, 12 Jun 2026 14:55:17 -0300 Subject: [PATCH 3/3] feat: estimate first/headerless on desktop, rename shipping to "Shipping method" - dynamic-estimate renders first, directly below the "Filters" heading on desktop with no title, no collapsible header, and no top divider (heading bottom border dropped while present); mobile keeps its "Estimate" title + accordion. - Rename the default shipping-method group heading from "Shipping" to "Shipping method" across all locales (copy-only; message id unchanged). Co-authored-by: Cursor --- CHANGELOG.md | 9 ++--- messages/ar.json | 3 +- messages/bg.json | 3 +- messages/ca.json | 3 +- messages/context.json | 3 +- messages/da.json | 3 +- messages/de.json | 3 +- messages/el.json | 3 +- messages/en.json | 3 +- messages/es.json | 3 +- messages/fi.json | 3 +- messages/fr.json | 3 +- messages/hu.json | 3 +- messages/id.json | 3 +- messages/it.json | 3 +- messages/ja.json | 3 +- messages/jp.json | 3 +- messages/ko.json | 3 +- messages/nl.json | 3 +- messages/nn.json | 3 +- messages/no.json | 3 +- messages/pl.json | 3 +- messages/pt.json | 3 +- messages/ro.json | 3 +- messages/ru.json | 3 +- messages/sk.json | 3 +- messages/sl.json | 3 +- messages/sv.json | 3 +- messages/th.json | 3 +- messages/uk.json | 3 +- react/FilterNavigator.js | 41 +++++++++++++++++++- react/__tests__/utils/getFilters.test.js | 34 ++++++++++++++-- react/components/AccordionFilterContainer.js | 1 - react/components/AccordionFilterGroup.js | 2 - react/components/AccordionFilterItem.js | 9 +---- react/utils/getFilters.js | 23 ++++++++++- 36 files changed, 154 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edcf62250..8db73a236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,15 +13,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -- The `dynamic-estimate` (Estimate) delivery filter group now renders its options with **no title and no collapsible header**, on both desktop and mobile. Its options are always visible instead of being hidden behind a collapsible heading. +- The default shipping-method filter group (`shipping`) heading copy changed from "Shipping" to **"Shipping method"** across all locales (`store/search.filter.title.shipping`; non-EN copy is a best-effort draft for the Localization team). +- The `dynamic-estimate` (Estimate) delivery filter group is now the **first filter shown, over all other filters**. On **desktop** it renders **headerless** (no title, no collapsible header) directly below the "Filters" heading, with **no divider line at its top** (the heading's bottom border is dropped while it is present). On **mobile** it keeps its regular "Estimate" title and collapsible header. ### Added -- New filter title key `store/search.filter.title.delivery-options` ("Delivery Option") across all locales (non-EN copy is a best-effort draft for the Localization team). The `shipping` group keeps its existing "Shipping" title. - -### Removed - -- Unused filter title key `store/search.filter.title.dynamic-estimate` (the Estimate group no longer shows a title). +- New filter title key `store/search.filter.title.delivery-options` ("Delivery Option") across all locales (non-EN copy is a best-effort draft for the Localization team). The `dynamic-estimate` group keeps its "Estimate" title (shown on mobile). ## [3.147.2] - 2026-06-05 diff --git a/messages/ar.json b/messages/ar.json index ab9883ba4..fd6f68f06 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "العلامات التجارية", "store/search.filter.title.price-ranges": "نطاقات السعر", "store/search.text": "عرض {from}-{to} من {recordsFiltered} نتائج", - "store/search.filter.title.shipping": "الشحن", + "store/search.filter.title.shipping": "طريقة الشحن", + "store/search.filter.title.dynamic-estimate": "التقدير", "store/search.filter.title.delivery-options": "خيار التوصيل", "store/search.filter.shipping.name.delivery": "توصيل الى", "store/search.filter.shipping.name.pickup-in-point": "الاستلام في", diff --git a/messages/bg.json b/messages/bg.json index 7e3ef38ee..d32520718 100644 --- a/messages/bg.json +++ b/messages/bg.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Брандове", "store/search.filter.title.price-ranges": "Ценови диапазони", "store/search.text": "Показване на {from}–{to} от {recordsFiltered} резултата", - "store/search.filter.title.shipping": "Доставка", + "store/search.filter.title.shipping": "Метод на доставка", + "store/search.filter.title.dynamic-estimate": "Прогноза", "store/search.filter.title.delivery-options": "Опция за доставка", "store/search.filter.shipping.name.delivery": "Доставка до", "store/search.filter.shipping.name.pickup-in-point": "Вземане от", diff --git a/messages/ca.json b/messages/ca.json index e12d16271..50c66335b 100644 --- a/messages/ca.json +++ b/messages/ca.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Marques", "store/search.filter.title.price-ranges": "Intervals de preus", "store/search.text": "S'estan mostrant de {from} a {to} de {recordsFiltered} resultats", - "store/search.filter.title.shipping": "Enviament", + "store/search.filter.title.shipping": "Mètode d'enviament", + "store/search.filter.title.dynamic-estimate": "Estimació", "store/search.filter.title.delivery-options": "Opció de lliurament", "store/search.filter.shipping.name.delivery": "Lliura a", "store/search.filter.shipping.name.pickup-in-point": "Recollida a", diff --git a/messages/context.json b/messages/context.json index 412751c63..5d81a2aee 100644 --- a/messages/context.json +++ b/messages/context.json @@ -65,7 +65,8 @@ "store/search.filter.placeholder": "Search by {filterName}", "store/search.filter.title.brands": "Brands", "store/search.filter.title.price-ranges": "Price Ranges", - "store/search.filter.title.shipping": "Shipping", + "store/search.filter.title.shipping": "Heading for the default shipping-method filter group on the PLP: 'Shipping method'", + "store/search.filter.title.dynamic-estimate": "Heading for the Dynamic Estimate filter group on the PLP: 'Estimate'", "store/search.filter.title.delivery-options": "Heading for the Delivery Option filter group on the PLP: 'Delivery Option'", "store/search.filter.shipping.name.delivery": "Deliver to", "store/search.filter.shipping.name.pickup-in-point": "Pickup at", diff --git a/messages/da.json b/messages/da.json index ef79790cc..97ba49e6d 100644 --- a/messages/da.json +++ b/messages/da.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Brands", "store/search.filter.title.price-ranges": "Prisintervaller", "store/search.text": "Viser {from}-{to} fra {recordsFiltered} optegnelser", - "store/search.filter.title.shipping": "Forsendelse", + "store/search.filter.title.shipping": "Forsendelsesmetode", + "store/search.filter.title.dynamic-estimate": "Estimat", "store/search.filter.title.delivery-options": "Leveringsmulighed", "store/search.filter.shipping.name.delivery": "Lever til", "store/search.filter.shipping.name.pickup-in-point": "Afhentning ved", diff --git a/messages/de.json b/messages/de.json index 3444fd6de..1b7ac413b 100644 --- a/messages/de.json +++ b/messages/de.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Marken", "store/search.filter.title.price-ranges": "Preisspannen", "store/search.text": "Anzeigen {from}-{to} aus {recordsFiltered}-Ergebnissen", - "store/search.filter.title.shipping": "Versand", + "store/search.filter.title.shipping": "Versandart", + "store/search.filter.title.dynamic-estimate": "Schätzung", "store/search.filter.title.delivery-options": "Lieferoption", "store/search.filter.shipping.name.delivery": "Liefern an", "store/search.filter.shipping.name.pickup-in-point": "Abholung bei", diff --git a/messages/el.json b/messages/el.json index d5a0d823b..d1ef8e69a 100644 --- a/messages/el.json +++ b/messages/el.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Εμπορικές επωνυμίες", "store/search.filter.title.price-ranges": "Εύρος τιμών", "store/search.text": "Γίνεται εμφάνιση {from}–{to} από {recordsFiltered} αποτελέσματα", - "store/search.filter.title.shipping": "Μεταφορά", + "store/search.filter.title.shipping": "Μέθοδος αποστολής", + "store/search.filter.title.dynamic-estimate": "Εκτίμηση", "store/search.filter.title.delivery-options": "Επιλογή παράδοσης", "store/search.filter.shipping.name.delivery": "Παράδοση προς", "store/search.filter.shipping.name.pickup-in-point": "Παραλαβή σε", diff --git a/messages/en.json b/messages/en.json index 35c5786db..66e7a38c8 100644 --- a/messages/en.json +++ b/messages/en.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Brands", "store/search.filter.title.price-ranges": "Price ranges", "store/search.text": "Showing {from}–{to} of {recordsFiltered} results", - "store/search.filter.title.shipping": "Shipping", + "store/search.filter.title.shipping": "Shipping method", + "store/search.filter.title.dynamic-estimate": "Estimate", "store/search.filter.title.delivery-options": "Delivery Option", "store/search.filter.shipping.name.delivery": "Deliver to", "store/search.filter.shipping.name.pickup-in-point": "Pickup at", diff --git a/messages/es.json b/messages/es.json index dba0bc0ed..54f2ae2e8 100644 --- a/messages/es.json +++ b/messages/es.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Marcas", "store/search.filter.title.price-ranges": "Rangos de precio", "store/search.text": "Mostrando {from}-{to} de {recordsFiltered} resultados", - "store/search.filter.title.shipping": "Envío", + "store/search.filter.title.shipping": "Método de envío", + "store/search.filter.title.dynamic-estimate": "Estimación", "store/search.filter.title.delivery-options": "Opción de entrega", "store/search.filter.shipping.name.delivery": "Entregar a", "store/search.filter.shipping.name.pickup-in-point": "Recogida en", diff --git a/messages/fi.json b/messages/fi.json index e4b055c89..608c3d510 100644 --- a/messages/fi.json +++ b/messages/fi.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Brändit", "store/search.filter.title.price-ranges": "Hintaluokat", "store/search.text": "Näytetään {from}–{to} {recordsFiltered} tuloksesta", - "store/search.filter.title.shipping": "Toimitus", + "store/search.filter.title.shipping": "Toimitustapa", + "store/search.filter.title.dynamic-estimate": "Arvio", "store/search.filter.title.delivery-options": "Toimitusvaihtoehto", "store/search.filter.shipping.name.delivery": "Toimitus osoitteeseen", "store/search.filter.shipping.name.pickup-in-point": "Nouto myymälästä", diff --git a/messages/fr.json b/messages/fr.json index 54aa2b6e9..defa40b48 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Marques", "store/search.filter.title.price-ranges": "Gammes de prix", "store/search.text": "Afficher les {from}-{to} des {recordsFiltered} résultats", - "store/search.filter.title.shipping": "Expédition", + "store/search.filter.title.shipping": "Mode d'expédition", + "store/search.filter.title.dynamic-estimate": "Estimation", "store/search.filter.title.delivery-options": "Option de livraison", "store/search.filter.shipping.name.delivery": "Livrer à", "store/search.filter.shipping.name.pickup-in-point": "Retrait à", diff --git a/messages/hu.json b/messages/hu.json index aa1f8023e..f00f19c21 100644 --- a/messages/hu.json +++ b/messages/hu.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Márkák", "store/search.filter.title.price-ranges": "Ártartományok", "store/search.text": "{from}-{to} eredmény megjelenítése a(z) {recordsFiltered} eredményből", - "store/search.filter.title.shipping": "Szállítás", + "store/search.filter.title.shipping": "Szállítási mód", + "store/search.filter.title.dynamic-estimate": "Becslés", "store/search.filter.title.delivery-options": "Szállítási lehetőség", "store/search.filter.shipping.name.delivery": "Szállítás ide", "store/search.filter.shipping.name.pickup-in-point": "Átvétel", diff --git a/messages/id.json b/messages/id.json index 202fac7f7..e9fd85014 100644 --- a/messages/id.json +++ b/messages/id.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Merek", "store/search.filter.title.price-ranges": "Rentang harga", "store/search.text": "Menampilka {from}–{to} dari {recordsFiltered} hasil", - "store/search.filter.title.shipping": "Pengiriman", + "store/search.filter.title.shipping": "Metode pengiriman", + "store/search.filter.title.dynamic-estimate": "Perkiraan", "store/search.filter.title.delivery-options": "Opsi pengiriman", "store/search.filter.shipping.name.delivery": "Kirim ke", "store/search.filter.shipping.name.pickup-in-point": "Ambil di", diff --git a/messages/it.json b/messages/it.json index 8f8c6136f..13fa76f6a 100644 --- a/messages/it.json +++ b/messages/it.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Brand", "store/search.filter.title.price-ranges": "Fasce di prezzo", "store/search.text": "Mostra {from}–{to} di {recordsFiltered} risultati", - "store/search.filter.title.shipping": "Spedizione", + "store/search.filter.title.shipping": "Metodo di spedizione", + "store/search.filter.title.dynamic-estimate": "Stima", "store/search.filter.title.delivery-options": "Opzione di consegna", "store/search.filter.shipping.name.delivery": "Consegna a", "store/search.filter.shipping.name.pickup-in-point": "Ritiro presso", diff --git a/messages/ja.json b/messages/ja.json index c19d635ba..2928cc507 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "ブランド", "store/search.filter.title.price-ranges": "価格帯", "store/search.text": "{from}-{to} に該当する {recordsFiltered} の記録を表示中", - "store/search.filter.title.shipping": "発送方法", + "store/search.filter.title.shipping": "配送方法", + "store/search.filter.title.dynamic-estimate": "配送目安", "store/search.filter.title.delivery-options": "配送オプション", "store/search.filter.shipping.name.delivery": "宛先", "store/search.filter.shipping.name.pickup-in-point": "集荷場所", diff --git a/messages/jp.json b/messages/jp.json index 15d725d60..cdf134146 100644 --- a/messages/jp.json +++ b/messages/jp.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "ブランド", "store/search.filter.title.price-ranges": "価格の範囲", "store/search.text": "{from}–{to} に該当する {recordsFiltered} の検索結果を表示中", - "store/search.filter.title.shipping": "発送方法", + "store/search.filter.title.shipping": "配送方法", + "store/search.filter.title.dynamic-estimate": "配送目安", "store/search.filter.title.delivery-options": "配送オプション", "store/search.filter.shipping.name.delivery": "宛先", "store/search.filter.shipping.name.pickup-in-point": "集荷場所", diff --git a/messages/ko.json b/messages/ko.json index f6881e879..2dfb05c5f 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "브랜드", "store/search.filter.title.price-ranges": "가격 범위", "store/search.text": "{recordsFiltered} 결과 중 {from}–{to} 표시", - "store/search.filter.title.shipping": "배송", + "store/search.filter.title.shipping": "배송 방법", + "store/search.filter.title.dynamic-estimate": "예상", "store/search.filter.title.delivery-options": "배송 옵션", "store/search.filter.shipping.name.delivery": "배송 대상", "store/search.filter.shipping.name.pickup-in-point": "픽업 장소", diff --git a/messages/nl.json b/messages/nl.json index 548a120c6..e736bba3c 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Merken", "store/search.filter.title.price-ranges": "Prijsklasse", "store/search.text": "Toont {from}-{to} van {recordsFiltered} resultaten", - "store/search.filter.title.shipping": "Verzending", + "store/search.filter.title.shipping": "Verzendmethode", + "store/search.filter.title.dynamic-estimate": "Schatting", "store/search.filter.title.delivery-options": "Bezorgoptie", "store/search.filter.shipping.name.delivery": "Leveren aan", "store/search.filter.shipping.name.pickup-in-point": "Afhalen op", diff --git a/messages/nn.json b/messages/nn.json index df5a63149..258c56e19 100644 --- a/messages/nn.json +++ b/messages/nn.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Merker", "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Viser {from}–{to} av {recordsFiltered} resultater", - "store/search.filter.title.shipping": "Forsendelse", + "store/search.filter.title.shipping": "Forsendelsesmetode", + "store/search.filter.title.dynamic-estimate": "Estimat", "store/search.filter.title.delivery-options": "Leveringsalternativ", "store/search.filter.shipping.name.delivery": "Leveres til", "store/search.filter.shipping.name.pickup-in-point": "Hent hos", diff --git a/messages/no.json b/messages/no.json index 0f666a558..73c2a2fc1 100644 --- a/messages/no.json +++ b/messages/no.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Merker", "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Viser {from}–{to} av {recordsFiltered} resultater", - "store/search.filter.title.shipping": "Forsendelse", + "store/search.filter.title.shipping": "Forsendelsesmetode", + "store/search.filter.title.dynamic-estimate": "Estimat", "store/search.filter.title.delivery-options": "Leveringsalternativ", "store/search.filter.shipping.name.delivery": "Leveres til", "store/search.filter.shipping.name.pickup-in-point": "Hent hos", diff --git a/messages/pl.json b/messages/pl.json index 4618024e9..ff41890e1 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Marki", "store/search.filter.title.price-ranges": "Zakresy cenowe", "store/search.text": "Pokazuję {from}-{to} od {recordsFiltered} wpisów", - "store/search.filter.title.shipping": "Wysyłka", + "store/search.filter.title.shipping": "Metoda wysyłki", + "store/search.filter.title.dynamic-estimate": "Szacowany czas", "store/search.filter.title.delivery-options": "Opcja dostawy", "store/search.filter.shipping.name.delivery": "Dostarcz do", "store/search.filter.shipping.name.pickup-in-point": "Odbiór w", diff --git a/messages/pt.json b/messages/pt.json index 28c8d2603..aae1ab32c 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Marcas", "store/search.filter.title.price-ranges": "Faixas de preço", "store/search.text": "Exibindo {from}–{to} de {recordsFiltered} resultados", - "store/search.filter.title.shipping": "Entrega", + "store/search.filter.title.shipping": "Método de envio", + "store/search.filter.title.dynamic-estimate": "Estimativa", "store/search.filter.title.delivery-options": "Opção de entrega", "store/search.filter.shipping.name.delivery": "Entregar em", "store/search.filter.shipping.name.pickup-in-point": "Retirada em", diff --git a/messages/ro.json b/messages/ro.json index 35abaebf1..1aa8054c0 100644 --- a/messages/ro.json +++ b/messages/ro.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Branduri", "store/search.filter.title.price-ranges": "Intervale de prețuri", "store/search.text": "Afișează {from}-{to} de la {recordsFiltered} înregistrări", - "store/search.filter.title.shipping": "Transport", + "store/search.filter.title.shipping": "Metodă de livrare", + "store/search.filter.title.dynamic-estimate": "Estimare", "store/search.filter.title.delivery-options": "Opțiune de livrare", "store/search.filter.shipping.name.delivery": "Livrează la", "store/search.filter.shipping.name.pickup-in-point": "Ridicare la", diff --git a/messages/ru.json b/messages/ru.json index 86448681c..89fab8cee 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Бренды", "store/search.filter.title.price-ranges": "Диапазоны цен", "store/search.text": "Показаны результаты {from}—{to} из {recordsFiltered}", - "store/search.filter.title.shipping": "Отправка", + "store/search.filter.title.shipping": "Способ доставки", + "store/search.filter.title.dynamic-estimate": "Оценка", "store/search.filter.title.delivery-options": "Вариант доставки", "store/search.filter.shipping.name.delivery": "Место доставки", "store/search.filter.shipping.name.pickup-in-point": "Место самовывоза", diff --git a/messages/sk.json b/messages/sk.json index a6d783df1..222567bfe 100644 --- a/messages/sk.json +++ b/messages/sk.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Značky", "store/search.filter.title.price-ranges": "Rozsahy cien", "store/search.text": "Zobrazuje sa {from} – {to} z/zo {recordsFiltered} záznamov", - "store/search.filter.title.shipping": "Doprava", + "store/search.filter.title.shipping": "Spôsob dopravy", + "store/search.filter.title.dynamic-estimate": "Odhad", "store/search.filter.title.delivery-options": "Možnosť doručenia", "store/search.filter.shipping.name.delivery": "Doručiť na", "store/search.filter.shipping.name.pickup-in-point": "Vyzdvihnúť na", diff --git a/messages/sl.json b/messages/sl.json index 3302f596d..b2a87824f 100644 --- a/messages/sl.json +++ b/messages/sl.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Znamke", "store/search.filter.title.price-ranges": "Cenovni razponi", "store/search.text": "Kažem {from}-{to} od {recordsFiltered} rezultatov", - "store/search.filter.title.shipping": "Odpošiljanje", + "store/search.filter.title.shipping": "Način pošiljanja", + "store/search.filter.title.dynamic-estimate": "Ocena", "store/search.filter.title.delivery-options": "Možnost dostave", "store/search.filter.shipping.name.delivery": "Dostavi v", "store/search.filter.shipping.name.pickup-in-point": "Prevzemi pri", diff --git a/messages/sv.json b/messages/sv.json index a50d1f9fa..318e00ff2 100644 --- a/messages/sv.json +++ b/messages/sv.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Varumärken", "store/search.filter.title.price-ranges": "Prisklasser", "store/search.text": "Visar {from}–{to} av {recordsFiltered} resultat", - "store/search.filter.title.shipping": "Frakt", + "store/search.filter.title.shipping": "Fraktmetod", + "store/search.filter.title.dynamic-estimate": "Uppskattning", "store/search.filter.title.delivery-options": "Leveransalternativ", "store/search.filter.shipping.name.delivery": "Leverera till", "store/search.filter.shipping.name.pickup-in-point": "Hämta vid", diff --git a/messages/th.json b/messages/th.json index f5f76a788..e0ab957ea 100644 --- a/messages/th.json +++ b/messages/th.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "แบรนด์", "store/search.filter.title.price-ranges": "ช่วงราคา", "store/search.text": "กำลังแสดงผล {from}–{to} ของ {recordsFiltered}", - "store/search.filter.title.shipping": "การส่ง", + "store/search.filter.title.shipping": "วิธีจัดส่ง", + "store/search.filter.title.dynamic-estimate": "ประมาณการ", "store/search.filter.title.delivery-options": "ตัวเลือกการจัดส่ง", "store/search.filter.shipping.name.delivery": "จัดส่งไปยัง", "store/search.filter.shipping.name.pickup-in-point": "จุดรับสินค้าเอง", diff --git a/messages/uk.json b/messages/uk.json index 4bc7ae9c7..452f318d0 100644 --- a/messages/uk.json +++ b/messages/uk.json @@ -66,7 +66,8 @@ "store/search.filter.title.brands": "Бренди", "store/search.filter.title.price-ranges": "Цінові діапазони", "store/search.text": "Показано результатів: {from}—{to} з {recordsFiltered}", - "store/search.filter.title.shipping": "Відправлення", + "store/search.filter.title.shipping": "Спосіб доставки", + "store/search.filter.title.dynamic-estimate": "Оцінка", "store/search.filter.title.delivery-options": "Варіант доставки", "store/search.filter.shipping.name.delivery": "Місце доставки", "store/search.filter.shipping.name.pickup-in-point": "Місце самовивозу", diff --git a/react/FilterNavigator.js b/react/FilterNavigator.js index 3483d7208..f5472e21d 100644 --- a/react/FilterNavigator.js +++ b/react/FilterNavigator.js @@ -27,6 +27,7 @@ import FilterNavigatorTitleTag from './components/FilterNavigatorTitleTag' import styles from './searchResult.css' import { CATEGORIES_TITLE, + DYNAMIC_ESTIMATE_KEY, shippingOptions, buildDeliveryShippingFacetForNavigation, } from './utils/getFilters' @@ -219,6 +220,22 @@ const FilterNavigator = ({ [deliveries, intl] ) + // On desktop the dynamic-estimate filter renders headerless as the first + // filter, right below the "Filters" title. The title's bottom border is + // dropped while it is present, so the estimate shows no divider at its top. + const estimateFilter = useMemo( + () => filters.find(filter => filter.name === DYNAMIC_ESTIMATE_KEY), + [filters] + ) + + const availableFilters = useMemo( + () => + estimateFilter + ? filters.filter(filter => filter !== estimateFilter) + : filters, + [filters, estimateFilter] + ) + const { pickupModal } = useSearchPickupModal({ navigateToFacet, isOpen: isPickupModalOpen, @@ -289,12 +306,32 @@ const FilterNavigator = ({ className={`${applyModifiers( handles.filter__container, 'title' - )} bb b--muted-4`} + )}${estimateFilter ? '' : ' bb b--muted-4'}`} >
+ {estimateFilter && ( + setIsPostalCodeModalOpen(true)} + onOpenPickupModal={() => setisPickupModalOpen(true)} + /> + )} { @@ -20,6 +21,12 @@ describe('getDeliveryGroupTitle', () => { ) }) + it('maps the dynamic-estimate group to the Estimate title id (used on mobile)', () => { + expect(getDeliveryGroupTitle('dynamic-estimate')).toBe( + DYNAMIC_ESTIMATE_TITLE + ) + }) + it('falls back to the raw group name for unknown groups (never "Default Title")', () => { expect(getDeliveryGroupTitle('delivery-window')).toBe('delivery-window') expect(getDeliveryGroupTitle('delivery-window')).not.toBe('Default Title') @@ -27,7 +34,7 @@ describe('getDeliveryGroupTitle', () => { }) describe('shouldHideDeliveryGroupHeader', () => { - it('hides the header only for the dynamic-estimate group', () => { + it('flags only the dynamic-estimate group as headerless (hidden on desktop)', () => { expect(shouldHideDeliveryGroupHeader('dynamic-estimate')).toBe(true) expect(shouldHideDeliveryGroupHeader('delivery-options')).toBe(false) expect(shouldHideDeliveryGroupHeader('shipping')).toBe(false) @@ -52,11 +59,11 @@ describe('getFilters delivery group titles', () => { facets: [{ key: name, name: 'option', value: 'option', map: name }], }) - it('hides the header for dynamic-estimate and titles delivery-options even when no shipping group is present', () => { + it('flags dynamic-estimate as headerless with the Estimate title and titles delivery-options even when no shipping group is present', () => { const filters = renderGetFilters({ deliveries: [ - makeGroup('dynamic-estimate'), makeGroup('delivery-options'), + makeGroup('dynamic-estimate'), ], }) @@ -66,11 +73,32 @@ describe('getFilters delivery group titles', () => { ) expect(estimate.hideHeader).toBe(true) + expect(estimate.title).toBe(DYNAMIC_ESTIMATE_TITLE) expect(deliveryOption.hideHeader).toBe(false) expect(deliveryOption.title).toBe(DELIVERY_OPTION_TITLE) expect(deliveryOption.title).not.toBe('Default Title') }) + it('orders the dynamic-estimate group first over all other filters', () => { + const filters = renderGetFilters({ + deliveries: [ + makeGroup('delivery-options'), + makeGroup('dynamic-estimate'), + ], + brands: [{ name: 'Samsung', value: 'samsung', selected: false }], + brandsQuantity: 1, + specificationFilters: [ + { + name: 'Color', + quantity: 1, + facets: [{ key: 'color', name: 'Blue', value: 'blue' }], + }, + ], + }) + + expect(filters[0].name).toBe('dynamic-estimate') + }) + it('titles the shipping group with the shipping title id and keeps its header', () => { const filters = renderGetFilters({ deliveries: [ diff --git a/react/components/AccordionFilterContainer.js b/react/components/AccordionFilterContainer.js index 014b319d3..127272f22 100644 --- a/react/components/AccordionFilterContainer.js +++ b/react/components/AccordionFilterContainer.js @@ -193,7 +193,6 @@ const AccordionFilterContainer = ({ title={filter.title} facets={filter.facets} quantity={filter.quantity} - hideHeader={filter.hideHeader} key={title} className={itemClassName} open={isOpen} diff --git a/react/components/AccordionFilterGroup.js b/react/components/AccordionFilterGroup.js index 0efb0a7bb..1f49ea745 100644 --- a/react/components/AccordionFilterGroup.js +++ b/react/components/AccordionFilterGroup.js @@ -34,7 +34,6 @@ const AccordionFilterGroup = ({ setTruncatedFacetsFetched, onClearFilter, showClearByFilter, - hideHeader, onOpenPostalCodeModal, onOpenPickupModal, }) => { @@ -57,7 +56,6 @@ const AccordionFilterGroup = ({ title={title} open={open} show={show} - hideHeader={hideHeader} onOpen={onOpen} selectedFilters={selectedFilters} appliedFiltersOverview={appliedFiltersOverview} diff --git a/react/components/AccordionFilterItem.js b/react/components/AccordionFilterItem.js index 889171a42..d395f2c53 100644 --- a/react/components/AccordionFilterItem.js +++ b/react/components/AccordionFilterItem.js @@ -37,7 +37,6 @@ const AccordionFilterItem = ({ facetKey, showClearByFilter, quantity, - hideHeader = false, }) => { const intl = useIntl() const handles = useCssHandles(CSS_HANDLES) @@ -65,7 +64,7 @@ const AccordionFilterItem = ({ return ( - {!hideHeader && (!open || isNavigationCollapsible) && ( + {(!open || isNavigationCollapsible) && (
)} {!isNavigationCollapsible ? ( - (hideHeader ? show : open) && children - ) : hideHeader ? ( -
{children}
+ open && children ) : (
{children}
@@ -190,8 +187,6 @@ AccordionFilterItem.propTypes = { facetKey: PropTypes.string, /** Whether a clear button that clear all options in a specific filter should appear beside the filter's name (true) or not (false). */ showClearByFilter: PropTypes.bool, - /** When `true`, renders the options with no title and no collapsible header. */ - hideHeader: PropTypes.bool, } export default AccordionFilterItem diff --git a/react/utils/getFilters.js b/react/utils/getFilters.js index d3d7e8320..e26c26c51 100644 --- a/react/utils/getFilters.js +++ b/react/utils/getFilters.js @@ -7,6 +7,8 @@ export const BRANDS_TITLE = 'store/search.filter.title.brands' export const PRICE_RANGES_TITLE = 'store/search.filter.title.price-ranges' export const DELIVERY_OPTION_TITLE = 'store/search.filter.title.delivery-options' +export const DYNAMIC_ESTIMATE_TITLE = + 'store/search.filter.title.dynamic-estimate' export const shippingOptions = { delivery: 'store/search.filter.shipping.name.delivery', @@ -21,12 +23,16 @@ export const DYNAMIC_ESTIMATE_KEY = 'dynamic-estimate' const DELIVERY_GROUP_TITLES = { [SHIPPING_KEY]: SHIPPING_TITLE, 'delivery-options': DELIVERY_OPTION_TITLE, + [DYNAMIC_ESTIMATE_KEY]: DYNAMIC_ESTIMATE_TITLE, } /** Maps a delivery group name to its heading message id; unknown groups fall back to the raw name. */ export const getDeliveryGroupTitle = name => DELIVERY_GROUP_TITLES[name] ?? name -/** The dynamic-estimate group renders its options with no title and no collapsible header. */ +/** + * On desktop the dynamic-estimate group renders its options with no title and + * no collapsible header. On mobile it keeps the regular titled, collapsible header. + */ export const shouldHideDeliveryGroupHeader = name => name === DYNAMIC_ESTIMATE_KEY @@ -135,7 +141,7 @@ const getFilters = ({ })) : [] - return [ + const filters = [ ...deliveriesFormatted, ...mappedSpecificationFilters, !hiddenFacets.brands && @@ -152,6 +158,19 @@ const getFilters = ({ facets: priceRanges, }, ].filter(Boolean) + + // The dynamic-estimate group must be the first filter to show up over all others. + const estimateIndex = filters.findIndex( + filter => filter.name === DYNAMIC_ESTIMATE_KEY + ) + + if (estimateIndex > 0) { + const [estimate] = filters.splice(estimateIndex, 1) + + filters.unshift(estimate) + } + + return filters } export default getFilters