Untitled

 avatar
unknown
plain_text
a month ago
12 kB
2
Indexable
<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