Untitled
<template> <Filters v-model="selectedFilter" @buttonClicked="applyFilters" @sendOrder="formatBodyOrder" /> <v-data-table :headers="headers" :items="response" item-value="id" item-selected="isSelected" class="elevation-1" :model-value="selectedItems" show-select :footer-props="{ itemsPerPageText: 'Itens por página', pageText: (pageStart, pageStop, totalItems) => `${pageStart}-${pageStop} de ${totalItems}` }" > <!-- Corpo da tabela --> <template v-slot:body="{ items }"> <template v-for="(item, index) in items" :key="item.id"> <!-- Linha principal --> <tr> <td> <v-btn icon small @click="onActionClick(index)"> <v-icon> {{ expandedRows.includes(index) ? "mdi-chevron-up" : "mdi-chevron-down" }} </v-icon> </v-btn> </td> <td> <v-checkbox :value="item.id" color="primary" hide-details v-model="selectedItems" @change="onParentCheckboxChange(item)" ></v-checkbox> </td> <td v-for="header in headers.slice(2)" :key="header.value"> {{ item[header.value] }} </td> </tr> <!-- Linha expandida --> <tr v-if="expandedRows.includes(index)" class="details-row"> <td :colspan="headers.length + 1"> <v-data-table :headers="detailHeaders" :items="item.stretchsFull" dense hide-default-footer :model-value="selectedItemsFilho" show-select > <!-- Corpo da tabela detalhada --> <template v-slot:body="{ items: detailItems }"> <tr v-for="stretchFull in detailItems" :key="stretchFull.id"> <td> <v-checkbox :value="stretchFull.id" color="primary" hide-details v-model="selectedItemsFilho" @change="onChildCheckboxChange(item)" ></v-checkbox> </td> <td v-for="header in detailHeaders" :key="header.value"> <template v-if="header.value === 'dia_vencimento'"> <v-text-field v-model="stretchFull[header.value]" solo dense hide-details ></v-text-field> </template> <template v-else> {{ stretchFull[header.value] }} </template> </td> </tr> </template> </v-data-table> </td> </tr> </template> </template> <!-- Nenhum dado --> <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, onMounted } from "vue"; import useOrders from "../../../../composables/orders"; import useRates from "../../../../composables/rates"; 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 { upgradeRates, downgradeRates, getUpgradeRates, getDowngradeRates } = useRates(); const { getClientsContractsRefactor, subTotalStretchProvidences, subTotalStreches, subTotalStretchesMinutes, qualificationToShow } = useOrders(); const selectedFilter = ref({ currentDateRange: '', selectedProgramObj: '', selectedClientObj: '', currentDate: new Date(), }); const response = ref([]); const selectedItems = ref([]); // Modelo de seleção para a tabela principal const selectedItemsFilho = ref([]); // Modelo de seleção para a tabela detalhada const expandedRows = ref([]); onMounted(async() => { await getUpgradeRates(); await getDowngradeRates(); }); const onActionClick = (item) => { if (expandedRows.value.includes(item)) { const index = expandedRows.value.indexOf(item); if (index > -1) { expandedRows.value.splice(index, 1); } } else { expandedRows.value.push(item); } }; 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); response.value.forEach((booking, index) => { treatMainTable(booking); treatDetailTable(booking); }); } }; const formatCurrency = (value) => { return parseFloat(value).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', minimumFractionDigits: 2 }); }; const 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 treatStretch = (booking, stretch, upgradeRates, downgradeRates, diaVencimento, quotaID, clientFullName, stretchIndex) => { const valorProvidencias = parseFloat(subTotalStretchProvidences(booking, stretch)); const valorTempoVoo = parseFloat(subTotalStrech(booking, stretch, upgradeRates.value, downgradeRates.value)); return { ...stretch, valor_providencias: formatCurrency(valorProvidencias), valor_tempo_voo: `${formatCurrency(valorTempoVoo)} / ${subTotalStretchMinutes(stretch)}`, dia_vencimento: diaVencimento, cota_id: quotaID, clientFullname: clientFullName, stretchIndex: stretchIndex + 1, qualification: qualificationToShow(stretch.qualification), selected: false }; }; const treatDetailTable = (booking) => { const diaVencimento = extractDiaVencimento(booking.client.clients_share_contracts); const quotaID = extractCotaID(booking.client.clients_share_contracts, booking); const clientFullName = booking.clientFullname; booking.stretchsFull = booking.stretchsFull.map((stretch, stretchIndex) => treatStretch(booking, stretch, upgradeRates, downgradeRates, diaVencimento, quotaID, clientFullName, stretchIndex) ); }; const treatMainTable = (booking) => { const valorProvidencias = booking.stretchsFull.reduce( (total, stretch) => total + parseFloat(subTotalStretchProvidences(booking, stretch)), 0 ); const valorTempoVoo = parseFloat(subTotalStreches(booking, upgradeRates.value, downgradeRates.value)); booking.stretchFirstDate = moment(booking.stretchsFull[0].originFull.date, 'YYYY-MM-DD').format('DD/MM/YYYY'); booking.stretchFirstHour = moment(booking.stretchsFull[0].originFull.hour, 'HH:mm:ss').format('HH:mm'); booking.valor_providencias = formatCurrency(valorProvidencias); booking.valor_tempo_voo = `${formatCurrency(valorTempoVoo)} / ${subTotalStretchesMinutes(booking)}`; booking.selected = false; }; const headers = [ { title: '', align: 'center', value: 'expand' }, { title: '', align: 'center', value: 'data-table-select' }, { 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: 'stretchFirstDate' }, { title: 'Hora', align: 'start', value: 'stretchFirstHour' }, { title: 'Valor/Tempo de Voo (min)', align: 'start', value: 'valor_tempo_voo' }, { title: 'Valor Providências', align: 'start', value: 'valor_providencias' }, ]; const detailHeaders = [ { title: '', align: 'center', value: 'data-table-select' }, { title: 'Trecho', align: 'start', value: 'stretchIndex' }, { title: 'Qualificação', align: 'start', value: 'qualification' }, { title: 'Cliente', align: 'start', value: 'clientFullname' }, { title: 'Dia de Vencimento', align: 'start', value: 'dia_vencimento' }, { title: 'Valor/Tempo de Voo (min)', align: 'start', value: 'valor_tempo_voo' }, { title: 'Valor Providências', align: 'start', value: 'valor_providencias' }, ]; return { selectedFilter, applyFilters, response, headers, detailHeaders, selectedItems, selectedItemsFilho, expandedRows, upgradeRates, downgradeRates }; }, components: { Filters } }; </script>
Leave a Comment