feat(find): active-filter bar with clear-all (closes #129)
Adds a summary bar that appears at the top of the Find Recipes panel
whenever any filter is active. Shows a count ("3 filters active") and
a Clear all button that resets all Find-tab filters in one tap:
constraints, allergies, excluded ingredients, shopping mode,
pantry-match-only, hard day mode, time budgets (active + total),
max missing, style, category, and all four nutrition limits.
Local input refs (constraintInput, allergyInput, etc.) are also cleared
so the text fields don't show stale uncommitted values after a clear.
This commit is contained in:
parent
30f5620fd5
commit
92fab94ae0
1 changed files with 56 additions and 0 deletions
|
|
@ -95,6 +95,14 @@
|
||||||
<div class="card mb-controls">
|
<div class="card mb-controls">
|
||||||
<h2 class="section-title text-xl mb-md">Find Recipes</h2>
|
<h2 class="section-title text-xl mb-md">Find Recipes</h2>
|
||||||
|
|
||||||
|
<!-- Active-filter summary bar -->
|
||||||
|
<div v-if="activeFilterCount > 0" class="active-filter-bar" role="status">
|
||||||
|
<span class="text-sm">{{ activeFilterCount }} filter{{ activeFilterCount !== 1 ? 's' : '' }} active</span>
|
||||||
|
<button class="btn btn-xs btn-secondary" @click="clearAllFindFilters" aria-label="Clear all active filters">
|
||||||
|
Clear all
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Level Selector -->
|
<!-- Level Selector -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">How far should we stretch?</label>
|
<label class="form-label">How far should we stretch?</label>
|
||||||
|
|
@ -968,6 +976,42 @@ const advancedActive = computed(() =>
|
||||||
!!recipesStore.styleId
|
!!recipesStore.styleId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const activeFilterCount = computed(() => {
|
||||||
|
let n = 0
|
||||||
|
if (recipesStore.constraints.length > 0) n++
|
||||||
|
if (recipesStore.allergies.length > 0) n++
|
||||||
|
if (recipesStore.excludeIngredients.length > 0) n++
|
||||||
|
if (recipesStore.shoppingMode) n++
|
||||||
|
if (recipesStore.pantryMatchOnly) n++
|
||||||
|
if (recipesStore.hardDayMode) n++
|
||||||
|
if (recipesStore.maxActiveMin !== null) n++
|
||||||
|
if (recipesStore.maxTotalMin !== null) n++
|
||||||
|
if (recipesStore.maxMissing !== null) n++
|
||||||
|
if (recipesStore.styleId !== null) n++
|
||||||
|
if (recipesStore.category !== null) n++
|
||||||
|
n += Object.values(recipesStore.nutritionFilters).filter((v) => v !== null).length
|
||||||
|
return n
|
||||||
|
})
|
||||||
|
|
||||||
|
function clearAllFindFilters() {
|
||||||
|
recipesStore.clearConstraints()
|
||||||
|
recipesStore.clearAllergies()
|
||||||
|
recipesStore.clearExcludeIngredients()
|
||||||
|
recipesStore.shoppingMode = false
|
||||||
|
recipesStore.pantryMatchOnly = false
|
||||||
|
recipesStore.hardDayMode = false
|
||||||
|
recipesStore.maxActiveMin = null
|
||||||
|
recipesStore.maxTotalMin = null
|
||||||
|
recipesStore.maxMissing = null
|
||||||
|
recipesStore.styleId = null
|
||||||
|
recipesStore.category = null
|
||||||
|
recipesStore.nutritionFilters = { max_calories: null, max_sugar_g: null, max_carbs_g: null, max_sodium_mg: null }
|
||||||
|
constraintInput.value = ''
|
||||||
|
allergyInput.value = ''
|
||||||
|
excludeIngredientInput.value = ''
|
||||||
|
categoryInput.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
// #46 — count of active nutrition filters so the summary is informative when collapsed
|
// #46 — count of active nutrition filters so the summary is informative when collapsed
|
||||||
const activeNutritionFilterCount = computed(() =>
|
const activeNutritionFilterCount = computed(() =>
|
||||||
Object.values(recipesStore.nutritionFilters ?? {}).filter((v) => v !== null).length
|
Object.values(recipesStore.nutritionFilters ?? {}).filter((v) => v !== null).length
|
||||||
|
|
@ -1387,6 +1431,18 @@ watch(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Filter bar */
|
/* Filter bar */
|
||||||
|
.active-filter-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: var(--spacing-xs) var(--spacing-sm);
|
||||||
|
margin-bottom: var(--spacing-sm);
|
||||||
|
background: var(--color-bg-secondary);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.filter-bar {
|
.filter-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue