import { type Ref, defineComponent, inject, onMounted, ref, watch, watchEffect } from 'vue'; import { useI18n } from 'vue-i18n'; import { useIntersectionObserver } from '@vueuse/core'; import { useAlertService } from '@/shared/alert/alert.service'; import { useDateFormat } from '@/shared/composables'; import useDataUtils from '@/shared/data/data-utils.service'; import { type IDisponibilita } from '@/shared/model/disponibilita.model'; import DisponibilitaService from './disponibilita.service'; export default defineComponent({ name: 'Disponibilita', setup() { const { t: t$ } = useI18n(); const dateFormat = useDateFormat(); const dataUtils = useDataUtils(); const disponibilitaService = inject('disponibilitaService', () => new DisponibilitaService()); const alertService = inject('alertService', () => useAlertService(), true); const itemsPerPage = ref(20); const queryCount: Ref = ref(null); const page: Ref = ref(1); const propOrder = ref('id'); const reverse = ref(false); const totalItems = ref(0); const links: Ref = ref({}); const disponibilitas: Ref = ref([]); const isFetching = ref(false); const clear = () => { page.value = 1; links.value = {}; disponibilitas.value = []; }; const sort = (): Array => { const result = [`${propOrder.value},${reverse.value ? 'desc' : 'asc'}`]; if (propOrder.value !== 'id') { result.push('id'); } return result; }; const retrieveDisponibilitas = async () => { isFetching.value = true; try { const paginationQuery = { page: page.value - 1, size: itemsPerPage.value, sort: sort(), }; const res = await disponibilitaService().retrieve(paginationQuery); totalItems.value = Number(res.headers['x-total-count']); queryCount.value = totalItems.value; links.value = dataUtils.parseLinks(res.headers?.link); disponibilitas.value.push(...(res.data ?? [])); } catch (err) { alertService.showHttpError(err.response); } finally { isFetching.value = false; } }; const handleSyncList = () => { clear(); }; onMounted(async () => { await retrieveDisponibilitas(); }); const removeId: Ref = ref(null); const removeEntity = ref(null); const prepareRemove = (instance: IDisponibilita) => { removeId.value = instance.id; removeEntity.value.show(); }; const closeDialog = () => { removeEntity.value.hide(); }; const removeDisponibilita = async () => { try { await disponibilitaService().delete(removeId.value); const message = t$('smartbookingApp.disponibilita.deleted', { param: removeId.value }).toString(); alertService.showInfo(message, { variant: 'danger' }); removeId.value = null; clear(); closeDialog(); } catch (error) { alertService.showHttpError(error.response); } }; const changeOrder = (newOrder: string) => { if (propOrder.value === newOrder) { reverse.value = !reverse.value; } else { reverse.value = false; } propOrder.value = newOrder; }; // Whenever order changes, reset the pagination watch([propOrder, reverse], () => { clear(); }); // Whenever the data resets or page changes, switch to the new page. watch([disponibilitas, page], async ([data, page], [_prevData, prevPage]) => { if (data.length === 0 || page !== prevPage) { await retrieveDisponibilitas(); } }); const infiniteScrollEl = ref(null); const intersectionObserver = useIntersectionObserver( infiniteScrollEl, intersection => { if (intersection[0].isIntersecting && !isFetching.value) { page.value++; } }, { threshold: 0.5, immediate: false, }, ); watchEffect(() => { if (links.value.next) { intersectionObserver.resume(); } else if (intersectionObserver.isActive) { intersectionObserver.pause(); } }); return { disponibilitas, handleSyncList, isFetching, retrieveDisponibilitas, clear, ...dateFormat, removeId, removeEntity, prepareRemove, closeDialog, removeDisponibilita, itemsPerPage, queryCount, page, propOrder, reverse, totalItems, changeOrder, infiniteScrollEl, t$, ...dataUtils, }; }, });