Untitled
unknown
plain_text
2 months ago
4.7 kB
3
Indexable
<template> <Filters v-model="selectedFilter" @buttonClicked="applyFilters" @sendOrder="formatBodyOrder" /> <v-data-table :headers="headers" :items="response" v-model="selectedItems" show-select :items-per-page="25" :footer-props="{ itemsPerPageText: 'Itens por página', pageText: (pageStart, pageStop, totalItems) => `${pageStart}-${pageStop} de ${totalItems}` }" > <template v-slot:body="{ items }"> <tr v-for="(item, index) in items" :key="item.id"> <td v-for="header in headers" :key="header.value"> {{ item[header.value] }} </td> <!-- Botão para expandir --> <td> <v-btn icon small @click="onActionClick(index)"> <v-icon>{{ expandedRows.includes(index) ? 'mdi-chevron-up' : 'mdi-chevron-down' }}</v-icon> </v-btn> </td> </tr> <!-- Linha de Detalhes --> <tr v-if="expandedRows.includes(index)" class="details-row"> <td :colspan="headers.length + 1"> <v-data-table :headers="detailHeaders" :items="item.details" dense hide-default-footer > <template v-slot:items="props"> <tr> <td>{{ props.item.id }}</td> <td>{{ props.item.qualification }}</td> </tr> </template> </v-data-table> </td> </tr> </template> <template v-slot:no-data> <v-alert type="info">Nenhum registro encontrado.</v-alert> </template> </v-data-table> </template> <script> import Filters from './Filters.vue'; import { ref, inject } from "vue"; import useOrders from "../../../../composables/orders"; export default { setup() { const swal = inject('$swal'); const Toast = swal.mixin({ toast: true, position: 'top-end', showConfirmButton: false, timer: 2000, timerProgressBar: true, didOpen: (toast) => { toast.addEventListener('mouseenter', swal.stopTimer); toast.addEventListener('mouseleave', swal.resumeTimer); } }); const { getClientsContractsRefactor, processOrders } = useOrders(); const selectedFilter = ref({ currentDateRange: '', selectedProgramObj: '', selectedClientObj: '', currentDate: new Date(), }); const response = ref([]); const selectedItems = ref([]); const expandedRows = ref([]); const onActionClick = (index) => { const idx = expandedRows.value.indexOf(index); if (idx === -1) { expandedRows.value.push(index); // Expande a linha } else { expandedRows.value.splice(idx, 1); // Fecha a linha } }; function validarFiltros() { for (let key of Object.keys(selectedFilter.value)) { const value = selectedFilter.value[key]; if (value === null || value === '') { Toast.fire({ icon: 'info', title: `Preencha todos os campos obrigatórios.` }); return false; } } return true; } const applyFilters = async() => { if (validarFiltros()) { const dates = [selectedFilter.value.currentDateRange.start, selectedFilter.value.currentDateRange.end].map(date => moment(date).format('YYYY-MM-DD')); response.value = await getClientsContractsRefactor('variavel', selectedFilter.value.selectedClientObj, dates, selectedFilter.value.selectedProgramObj); } }; const formatBodyOrder = async() => { if (selectedItems.value.length === 0) { Toast.fire({ icon: 'info', title: `Selecione ao menos uma linha.` }); return; } }; const headers = [ { title: '', align: 'start', value: 'expand' }, { title: 'Nº da Reserva', align: 'start', value: 'id' }, { title: 'Status', align: 'start', value: 'status' }, { title: 'Cliente', align: 'start', value: 'clientFullname' }, { title: 'Data', align: 'start', value: 'date' }, { title: 'Hora', align: 'start', value: 'hour' }, ]; const detailHeaders = [ { title: 'Trecho', align: 'start', value: 'id' }, { title: 'Qualificação', align: 'start', value: 'qualification' }, ]; return { selectedFilter, applyFilters, response, headers, detailHeaders, formatBodyOrder, selectedItems, onActionClick, expandedRows }; }, components: { Filters }, }; </script>
Editor is loading...
Leave a Comment