|
|
@@ -3,38 +3,70 @@ import type { ApiFilter } from '~/types/data'
|
|
|
import ApiResource from '~/models/ApiResource'
|
|
|
import { SEARCH_STRATEGY } from '~/types/enum/data'
|
|
|
|
|
|
-/**
|
|
|
- *
|
|
|
- */
|
|
|
export default class Search implements ApiFilter {
|
|
|
field: string
|
|
|
- value: Ref<string | number>
|
|
|
- private mode: string
|
|
|
+ filterValue: Ref<string>
|
|
|
+ mode: SEARCH_STRATEGY
|
|
|
+ reactiveFilter: boolean
|
|
|
|
|
|
/**
|
|
|
* @param field
|
|
|
* @param value
|
|
|
- * @param mode The search strategy (exact [default], partial, start, end, word_start).
|
|
|
+ * @param mode The 'search' strategy (exact [default], partial, start, end, word_start).
|
|
|
* This strategy is defined API-side, but PiniaOrm needs to know how to handle this.
|
|
|
* @see https://api-platform.com/docs/core/filters/
|
|
|
+ * @param reactiveFilter Est-ce qu'on doit conserver la réactivité du filtre ? Concrètement, dans le cas d'une
|
|
|
+ * recherche textuelle, si le filtre est réactif, le résultat de la query Pinia-ORM sera
|
|
|
+ * filtré à chaque fois que le filtre est modifié (même sans refresh ou nouvel appel à
|
|
|
+ * fetchCollection). Si reactiveFilter est false (comportement par défaut), le résultat
|
|
|
+ * de la query ne sera mis à jour qu'en cas de nouvel appel à fetchCollection (ou à refresh()).
|
|
|
*/
|
|
|
constructor(
|
|
|
field: string,
|
|
|
- value: Ref<string | number>,
|
|
|
+ value: Ref<string>,
|
|
|
mode: SEARCH_STRATEGY = SEARCH_STRATEGY.EXACT,
|
|
|
+ reactiveFilter: boolean = false,
|
|
|
) {
|
|
|
this.field = field
|
|
|
- this.value = value
|
|
|
+ this.filterValue = value
|
|
|
this.mode = mode
|
|
|
+ this.reactiveFilter = reactiveFilter
|
|
|
}
|
|
|
|
|
|
public applyToPiniaOrmQuery(
|
|
|
query: PiniaOrmQuery<ApiResource>,
|
|
|
): PiniaOrmQuery<ApiResource> {
|
|
|
- return query.where(this.field, this.value.value)
|
|
|
+ const filterValue = this.reactiveFilter
|
|
|
+ ? this.filterValue
|
|
|
+ : ref(this.filterValue.value)
|
|
|
+
|
|
|
+ let wordStartRx: RegExp | null = null
|
|
|
+ if (this.mode === SEARCH_STRATEGY.WORD_START) {
|
|
|
+ wordStartRx = new RegExp(`^${filterValue.value}|\\s${filterValue.value}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ return query.where(this.field, (value: string) => {
|
|
|
+ if (this.mode === SEARCH_STRATEGY.EXACT) {
|
|
|
+ return value === filterValue.value
|
|
|
+ } else if (this.mode === SEARCH_STRATEGY.IEXACT) {
|
|
|
+ return value.toLowerCase() === filterValue.value.toLowerCase()
|
|
|
+ } else if (this.mode === SEARCH_STRATEGY.PARTIAL) {
|
|
|
+ return value.includes(filterValue.value)
|
|
|
+ } else if (this.mode === SEARCH_STRATEGY.IPARTIAL) {
|
|
|
+ return value.toLowerCase().includes(filterValue.value.toLowerCase())
|
|
|
+ } else if (this.mode === SEARCH_STRATEGY.START) {
|
|
|
+ return value.startsWith(filterValue.value)
|
|
|
+ } else if (this.mode === SEARCH_STRATEGY.END) {
|
|
|
+ return value.endsWith(filterValue.value)
|
|
|
+ } else if (this.mode === SEARCH_STRATEGY.WORD_START) {
|
|
|
+ return wordStartRx!.test(value)
|
|
|
+ } else {
|
|
|
+ throw new Error('Unrecognized mode')
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
public getApiQueryPart(): string {
|
|
|
- return `${this.field}[]=${this.value.value}`
|
|
|
+ return `${this.field}[]=${this.filterValue.value}`
|
|
|
}
|
|
|
}
|