Untitled
unknown
plain_text
a year ago
12 kB
5
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>
Editor is loading...
Leave a Comment