import type { Query as PiniaOrmQuery } from 'pinia-orm' import type { Ref } from 'vue' import type { ApiFilter } from '~/types/data' import type ApiResource from '~/models/ApiResource' import { TIME_STRATEGY } from '~/types/enum/data' import AbstractFilter from '~/services/data/Filters/AbstractFilter' import RefUtils from '~/services/utils/refUtils' import DateUtils from '~/services/utils/dateUtils' export default class TimeFilter extends AbstractFilter implements ApiFilter { field: string filterValue: Ref mode: TIME_STRATEGY /** * @param field * @param value * @param mode The 'time' strategy (after, before, strictly_after, strictly_before). * 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 */ constructor( field: string, value: Ref, mode: TIME_STRATEGY, reactiveFilter: boolean = false, ) { super(reactiveFilter) this.field = field this.filterValue = value this.mode = mode } protected search(value: string, filterValue: Ref): boolean { if (filterValue.value === null) { return false } switch (this.mode) { case TIME_STRATEGY.BEFORE: return DateUtils.isBefore(value, filterValue.value, false) case TIME_STRATEGY.AFTER: return DateUtils.isBefore(filterValue.value, value, false) case TIME_STRATEGY.STRICTLY_BEFORE: return DateUtils.isBefore(value, filterValue.value) case TIME_STRATEGY.STRICTLY_AFTER: return DateUtils.isBefore(filterValue.value, value) default: throw new Error('Unrecognized mode') } } public applyToPiniaOrmQuery( query: PiniaOrmQuery, ): PiniaOrmQuery { const filterValue = RefUtils.castToRef( this.filterValue, this.reactiveFilter, ) if (!filterValue.value) { return query } return query.where(this.field, (value: string) => this.search(value, filterValue), ) } public getApiQueryPart(): string { if (!this.filterValue.value) { return '' } return `${this.field}[${this.mode}]=${this.filterValue.value}` } }