Untitled
<template> <Filters v-model="selectedFilter" @buttonClicked="applyFilters" @sendOrder="formatBodyOrder" /> <v-data-table :headers="headers" :items="response" v-model="selectedItems" item-value="id" item-selected="isSelected" class="elevation-1" :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 v-model="selected" :value="item" color="primary" hide-details @click="checkItem(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" v-model="selectedItemsFilho" dense hide-default-footer > <!-- Corpo da tabela detalhada --> <template v-slot:body="{ items: detailItems }"> <tr v-for="stretchFull in detailItems" :key="stretchFull.id"> <td> <v-checkbox v-model="selected" :value="item" color="primary" hide-details ></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, subTotalStrech, subTotalStretchMinutes, qualificationToShow } = useOrders() const selectedFilter = ref({ currentDateRange: '', selectedProgramObj: '', selectedClientObj: '', currentDate: new Date(), }) const response = ref([]); const selectedItems = ref([]) const selectedItemsFilho = ref([]) 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); } } 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); console.log('response.value', response.value) 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 extractDiaVencimento = (clientsShareContracts) => { for (const shareContract of clientsShareContracts) { if (shareContract.status === 'ativo') { for (const contractQuota of Object.values(shareContract.contract_quotas)) { return contractQuota.taxa_variavel.data_vencimento; } } } return 0; }; const checkItem = (item) => { console.log('item', item) console.log('selectedItems.value', selectedItems.value) } const treatStretch = (booking, stretch, upgradeRates, downgradeRates, diaVencimento, 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, clientFullname: clientFullName, stretchIndex: stretchIndex + 1, qualification: qualificationToShow(stretch.qualification), selected: false }; }; const treatDetailTable = (booking) => { const diaVencimento = extractDiaVencimento(booking.client.clients_share_contracts); const clientFullName = booking.clientFullname; booking.stretchsFull = booking.stretchsFull.map((stretch, stretchIndex) => treatStretch(booking, stretch, upgradeRates, downgradeRates, diaVencimento, 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 formatBodyOrder = async() => { if(selectedItems.value.length === 0){ Toast.fire({ icon: 'info', title: `Selecione ao menos uma linha.` }) return; } } 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' }, // parseFloat(subTotalStretchProvidences(null, stretch)).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', minimumFractionDigits: 2 }) ] return { selectedFilter, applyFilters, response, headers, detailHeaders, formatBodyOrder, selectedItems, selectedItemsFilho, onActionClick, expandedRows, upgradeRates, downgradeRates, checkItem } }, components: { Filters }, } </script>
Leave a Comment