feat(planner): the places search also finds the description and the notes

The search box of the places list matched only name and address. It now also reads what was written about a place, through one helper the desktop list, its filter counts and the phone's browser share. (#2252)
This commit is contained in:
Maurice
2026-10-01 09:30:42 +02:00
parent 81ebc31698
commit f7782b9ef7
5 changed files with 59 additions and 12 deletions
+34
View File
@@ -0,0 +1,34 @@
// FE-UTIL-PLACESEARCH-001 to FE-UTIL-PLACESEARCH-004
import { describe, it, expect } from 'vitest'
import { placeMatchesSearch } from './placeSearch'
const place = {
name: 'Café Central',
address: 'Herrengasse 14, Wien',
description: 'Classic Viennese coffee house',
notes: 'Book a table ahead',
}
describe('placeMatchesSearch', () => {
it('FE-UTIL-PLACESEARCH-001: an empty or blank query matches every place', () => {
expect(placeMatchesSearch(place, '')).toBe(true)
expect(placeMatchesSearch(place, ' ')).toBe(true)
})
it('FE-UTIL-PLACESEARCH-002: finds the name and the address, ignoring case', () => {
expect(placeMatchesSearch(place, 'central')).toBe(true)
expect(placeMatchesSearch(place, 'HERRENGASSE')).toBe(true)
})
it('FE-UTIL-PLACESEARCH-003: also finds the description and the notes (#2252)', () => {
expect(placeMatchesSearch(place, 'viennese')).toBe(true)
expect(placeMatchesSearch(place, 'table ahead')).toBe(true)
})
it('FE-UTIL-PLACESEARCH-004: missing fields are skipped, and a miss is a miss', () => {
const bare = { name: 'Stop', address: null, description: undefined, notes: null }
expect(placeMatchesSearch(bare, 'stop ')).toBe(true)
expect(placeMatchesSearch(bare, 'nowhere')).toBe(false)
expect(placeMatchesSearch(place, 'pizza')).toBe(false)
})
})
+18
View File
@@ -0,0 +1,18 @@
import type { Place } from '../types'
type Searchable = Pick<Place, 'name' | 'address' | 'description' | 'notes'>
/**
* Whether a place matches the search box of the places list (#2252). Name and
* address as before, and also the description and the notes, so a place found
* by what was written about it ("vegan", "book ahead") turns up too. One helper
* for the desktop list, its filter counts and the phone's browser, so the three
* can never disagree about what a search finds.
*/
export function placeMatchesSearch(place: Searchable, query: string): boolean {
const q = query.trim().toLowerCase()
if (!q) return true
return [place.name, place.address, place.description, place.notes].some(
field => !!field && field.toLowerCase().includes(q),
)
}