43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { computed, reactive, type Ref } from 'vue';
|
|
import type { SalesAdAudienceFirmRow } from '../api/sales';
|
|
|
|
/**
|
|
* Общая логика 4 экранов прогрева: список ниш для фильтра, состояние фильтров
|
|
* (ниша + период по дате запуска) и отфильтрованный список. Пагинация и
|
|
* сортировка — на стороне <v-data-table>, здесь их нет.
|
|
*/
|
|
export interface WarmingFilters {
|
|
niche: string | null;
|
|
from: string | null; // YYYY-MM-DD, включительно
|
|
to: string | null; // YYYY-MM-DD, включительно
|
|
}
|
|
|
|
export function useWarmingFirms(firms: Ref<SalesAdAudienceFirmRow[]>) {
|
|
const filters = reactive<WarmingFilters>({ niche: null, from: null, to: null });
|
|
|
|
const niches = computed(() => {
|
|
const set = new Set<string>();
|
|
for (const f of firms.value) {
|
|
if (f.rubric) set.add(f.rubric);
|
|
}
|
|
return Array.from(set).sort((a, b) => a.localeCompare(b, 'ru'));
|
|
});
|
|
|
|
function inPeriod(iso: string | null): boolean {
|
|
if (!filters.from && !filters.to) return true;
|
|
if (!iso) return false;
|
|
const day = iso.slice(0, 10);
|
|
if (filters.from && day < filters.from) return false;
|
|
if (filters.to && day > filters.to) return false;
|
|
return true;
|
|
}
|
|
|
|
const filtered = computed(() =>
|
|
firms.value.filter(
|
|
(f) => (!filters.niche || f.rubric === filters.niche) && inPeriod(f.warmup_started_at),
|
|
),
|
|
);
|
|
|
|
return { filters, niches, filtered };
|
|
}
|