Skip to content

Commit 230a674

Browse files
fix: add filter when retrieving beaches
1 parent dcb9d2d commit 230a674

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-9
lines changed

frontend/cypress/e2e/main_window/search_places.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ context('Search Places', () => {
1414
})
1515

1616
it('A user can search a beach and zoom on it when it is selected', () => {
17-
cy.getDataCy('location-search-input').type("Plan d'eau, Étel, 56410", { delay: 400 })
17+
cy.getDataCy('location-search-input').type("plan d'eau, étel, 56410", { delay: 400 })
1818
cy.get('.rs-auto-complete-item').first().click()
1919
cy.url().should('include', '/#@-356522.93,6049418.48,14.00')
2020
})
Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
11
{
22
"request": {
33
"method": "GET",
4-
"url": "/geoserver/wfs?service=WFS&version=1.1.0&request=GetFeature&typename=monitorenv:beaches&outputFormat=application/json&srsname=EPSG:4326"
4+
"urlPathPattern": "/geoserver/wfs",
5+
"queryParameters": {
6+
"service": {
7+
"equalTo": "WFS"
8+
},
9+
"version": {
10+
"equalTo": "1.1.0"
11+
},
12+
"request": {
13+
"equalTo": "GetFeature"
14+
},
15+
"typename": {
16+
"equalTo": "monitorenv:beaches"
17+
},
18+
"outputFormat": {
19+
"equalTo": "application/json"
20+
},
21+
"srsname": {
22+
"equalTo": "EPSG:4326"
23+
},
24+
"CQL_FILTER": {
25+
"matches": ".*plan.*eau.*étel.*56410.*"
26+
}
27+
}
528
},
629
"response": {
730
"status": 200,
@@ -10,6 +33,6 @@
1033
"Access-Control-Allow-Origin": "*",
1134
"Access-Control-Allow-Methods": "*"
1235
},
13-
"body": "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"id\":\"beaches.1527\",\"geometry\":{\"type\":\"MultiPoint\",\"coordinates\":[[6.7288,43.3924]]},\"geometry_name\":\"geom\",\"properties\":{\"id\":1527,\"name\":\"La Galiote\",\"official_name\":\"Fréjus\",\"postcode\":\"83370\",\"insee\":\"83061\"},\"bbox\":[6.7288,43.3924,6.7288,43.3924]},{\"type\":\"Feature\",\"id\":\"beaches.789\",\"geometry\":{\"type\":\"MultiPoint\",\"coordinates\":[[-3.2027,47.6536]]},\"geometry_name\":\"geom\",\"properties\":{\"id\":789,\"name\":\"Plan D'eau\",\"official_name\":\"Étel\",\"postcode\":\"56410\",\"insee\":\"56055\"},\"bbox\":[-3.2027,47.6536,-3.2027,47.6536]},{\"type\":\"Feature\",\"id\":\"beaches.233\",\"geometry\":{\"type\":\"MultiPoint\",\"coordinates\":[[-2.347,47.2663]]},\"geometry_name\":\"geom\",\"properties\":{\"id\":233,\"name\":\"Plage Des Libraires\",\"official_name\":\"Pornichet\",\"postcode\":\"44380\",\"insee\":\"44132\"},\"bbox\":[-2.347,47.2663,-2.347,47.2663]},{\"type\":\"Feature\",\"id\":\"beaches.2009\",\"geometry\":{\"type\":\"MultiPoint\",\"coordinates\":[[55.2234,-21.0534]]},\"geometry_name\":\"geom\",\"properties\":{\"id\":2009,\"name\":\"Plage Des Roches Noires\",\"official_name\":\"Saint-Paul\",\"postcode\":\"97460\",\"insee\":\"97415\"},\"bbox\":[55.2234,-21.0534,55.2234,-21.0534]}],\"totalFeatures\":4,\"numberMatched\":4,\"numberReturned\":4,\"timeStamp\":\"2025-08-26T07:12:52.375Z\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"urn:ogc:def:crs:EPSG::4326\"}},\"bbox\":[-3.2027,-21.0534,55.2234,47.6536]}"
36+
"body": "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"id\":\"beaches.789\",\"geometry\":{\"type\":\"MultiPoint\",\"coordinates\":[[-3.2027,47.6536]]},\"geometry_name\":\"geom\",\"properties\":{\"id\":789,\"name\":\"Plan D'eau\",\"official_name\":\"Étel\",\"postcode\":\"56410\",\"insee\":\"56055\"},\"bbox\":[-3.2027,47.6536,-3.2027,47.6536]}],\"totalFeatures\":1,\"numberMatched\":1,\"numberReturned\":1,\"timeStamp\":\"2025-08-26T07:12:52.375Z\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"urn:ogc:def:crs:EPSG::4326\"}},\"bbox\":[-3.2027,47.6536,-3.2027,47.6536]}"
1437
}
1538
}

frontend/src/api/beachesAPI.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,34 @@ export function throwIrretrievableBeachesError(e) {
66
throw Error(`Nous n'avons pas pu récupérer les plages: ${e}`)
77
}
88

9-
export const getBeachesFromAPI = async () => {
9+
function sanitizeQuery(query: string) {
10+
return query.replace(/'/g, "''")
11+
}
12+
13+
export const getBeachesFromAPI = async (query: string | undefined) => {
1014
const geoserverURL = import.meta.env.FRONTEND_GEOSERVER_REMOTE_URL
1115

16+
if (!query) {
17+
return Promise.resolve([])
18+
}
19+
20+
const searchQueries = query
21+
.trim()
22+
.split(/[\s,.\-;:()]+/)
23+
.filter(t => t.length > 0)
24+
25+
const conditions = searchQueries.map(searchQuery => {
26+
const sanitizedQuery = sanitizeQuery(searchQuery)
27+
28+
return `(name ILIKE '%${sanitizedQuery}%' OR official_name ILIKE '%${sanitizedQuery}%' OR postcode ILIKE '%${sanitizedQuery}%')`
29+
})
30+
const cqlFilter = conditions.join(' AND ')
31+
1232
return fetch(
1333
`${geoserverURL}/geoserver/wfs?service=WFS&` +
1434
`version=1.1.0&request=GetFeature&typename=${
1535
import.meta.env.FRONTEND_GEOSERVER_NAMESPACE
16-
}:beaches&outputFormat=application/json&srsname=${WSG84_PROJECTION}`
36+
}:beaches&outputFormat=application/json&srsname=${WSG84_PROJECTION}&CQL_FILTER=${encodeURIComponent(cqlFilter)}`
1737
)
1838
.then(response => {
1939
if (response.status === OK) {

frontend/src/features/LocateOnMap/SearchLocation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function SearchLocation() {
1616
const locateOnMap = useAppSelector(state => state.map.locateOnMap)
1717
const [searchedLocation, setSearchedLocation] = useState<string | undefined>(undefined)
1818
const results = useGooglePlacesAPI(searchedLocation)
19-
const { beaches, options: beachesOptions } = useBeaches()
19+
const { beaches, options: beachesOptions } = useBeaches(searchedLocation)
2020

2121
const handleSelectLocation = async (location: { id: string; name: string } | undefined) => {
2222
if (!location || !location?.id) {

frontend/src/features/LocateOnMap/hook/useBeaches.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ type Options = {
66
value: string
77
}
88

9-
export const useBeaches = () => {
9+
export const useBeaches = (query: string | undefined) => {
1010
const [options, setOptions] = useState<Options[]>([])
1111
const [beaches, setBeaches] = useState<any[]>([])
1212

1313
useEffect(() => {
14-
getBeachesFromAPI()
14+
getBeachesFromAPI(query)
1515
.then(values => {
1616
setBeaches(values)
1717
setOptions(
@@ -33,7 +33,7 @@ export const useBeaches = () => {
3333
.catch(() => {
3434
setOptions([])
3535
})
36-
}, [])
36+
}, [query])
3737

3838
return { beaches, options }
3939
}

0 commit comments

Comments
 (0)