Untitled

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