SearchFilter.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import type { Query as PiniaOrmQuery } from 'pinia-orm'
  2. import type { ApiFilter } from '~/types/data'
  3. import ApiResource from '~/models/ApiResource'
  4. import { SEARCH_STRATEGY } from '~/types/enum/data'
  5. import AbstractFilter from '~/services/data/Filters/AbstractFilter'
  6. import RefUtils from '~/services/utils/refUtils'
  7. export default class SearchFilter extends AbstractFilter implements ApiFilter {
  8. field: string
  9. filterValue: Ref<string>
  10. mode: SEARCH_STRATEGY
  11. /**
  12. * @param field
  13. * @param value
  14. * @param mode The 'search' strategy (exact [default], partial, start, end, word_start).
  15. * This strategy is defined API-side, but PiniaOrm needs to know how to handle this.
  16. * @see https://api-platform.com/docs/core/filters/
  17. * @param reactiveFilter
  18. */
  19. constructor(
  20. field: string,
  21. value: Ref<string>,
  22. mode: SEARCH_STRATEGY = SEARCH_STRATEGY.EXACT,
  23. reactiveFilter: boolean = false,
  24. ) {
  25. super(reactiveFilter)
  26. this.field = field
  27. this.filterValue = value
  28. this.mode = mode
  29. }
  30. public applyToPiniaOrmQuery(
  31. query: PiniaOrmQuery<ApiResource>,
  32. ): PiniaOrmQuery<ApiResource> {
  33. const filterValue = RefUtils.castToRef(
  34. this.filterValue,
  35. this.reactiveFilter,
  36. )
  37. if (!filterValue.value) {
  38. return query
  39. }
  40. let wordStartRx: RegExp | null = null
  41. if (this.mode === SEARCH_STRATEGY.WORD_START) {
  42. wordStartRx = new RegExp(`^${filterValue.value}|\\s${filterValue.value}`)
  43. }
  44. return query.where(this.field, (value: string) => {
  45. if (this.mode === SEARCH_STRATEGY.EXACT) {
  46. return value === filterValue.value
  47. } else if (this.mode === SEARCH_STRATEGY.IEXACT) {
  48. return value.toLowerCase() === filterValue.value.toLowerCase()
  49. } else if (this.mode === SEARCH_STRATEGY.PARTIAL) {
  50. return value.includes(filterValue.value)
  51. } else if (this.mode === SEARCH_STRATEGY.IPARTIAL) {
  52. return value.toLowerCase().includes(filterValue.value.toLowerCase())
  53. } else if (this.mode === SEARCH_STRATEGY.START) {
  54. return value.startsWith(filterValue.value)
  55. } else if (this.mode === SEARCH_STRATEGY.END) {
  56. return value.endsWith(filterValue.value)
  57. } else if (this.mode === SEARCH_STRATEGY.WORD_START) {
  58. return wordStartRx!.test(value)
  59. } else {
  60. throw new Error('Unrecognized mode')
  61. }
  62. })
  63. }
  64. public getApiQueryPart(): string {
  65. if (!this.filterValue.value) {
  66. return ''
  67. }
  68. return `${this.field}[]=${this.filterValue.value}`
  69. }
  70. }