|
|
@@ -3,47 +3,20 @@
|
|
|
<table class="payout-table">
|
|
|
<thead>
|
|
|
<tr>
|
|
|
- <th
|
|
|
- v-for="(column, index) in columns"
|
|
|
- :key="column.key"
|
|
|
- >
|
|
|
+ <th v-for="column in columns" :key="column.key">
|
|
|
<div class="header-wrapper">
|
|
|
<div class="header-content">
|
|
|
<q-icon
|
|
|
class="cursor-pointer sort-icon q-my-md"
|
|
|
- :name="
|
|
|
- column.direction === 'desc'
|
|
|
- ? 'south'
|
|
|
- : 'north'
|
|
|
- "
|
|
|
+ :name="column.direction === 'desc' ? 'south' : 'north'"
|
|
|
size="15px"
|
|
|
- :color="
|
|
|
- column.direction
|
|
|
- ? 'primary'
|
|
|
- : '#b0b0b0'
|
|
|
- "
|
|
|
+ :color="column.direction ? 'primary' : '#b0b0b0'"
|
|
|
@click="toggleSort(column)"
|
|
|
/>
|
|
|
|
|
|
- <q-icon
|
|
|
- class="cursor-pointer move-icon"
|
|
|
- color="#888"
|
|
|
- name="chevron_left"
|
|
|
- size="18px"
|
|
|
- @click="moveLeft(index)"
|
|
|
- />
|
|
|
-
|
|
|
<span class="header-label">
|
|
|
{{ column.label }}
|
|
|
</span>
|
|
|
-
|
|
|
- <q-icon
|
|
|
- class="cursor-pointer move-icon"
|
|
|
- color="#888"
|
|
|
- name="chevron_right"
|
|
|
- size="18px"
|
|
|
- @click="moveRight(index)"
|
|
|
- />
|
|
|
</div>
|
|
|
</div>
|
|
|
</th>
|
|
|
@@ -51,38 +24,14 @@
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
- <tr
|
|
|
- v-for="item in sortedRows"
|
|
|
- :key="item.property_id"
|
|
|
- >
|
|
|
- <td
|
|
|
- v-for="column in columns"
|
|
|
- :key="column.key"
|
|
|
- >
|
|
|
- <template
|
|
|
- v-if="
|
|
|
- column.key ===
|
|
|
- 'final_payout_amount'
|
|
|
- "
|
|
|
- >
|
|
|
- {{
|
|
|
- formatCurrency(
|
|
|
- item[column.key]
|
|
|
- )
|
|
|
- }}
|
|
|
+ <tr v-for="item in sortedRows" :key="item.property_id">
|
|
|
+ <td v-for="column in columns" :key="column.key">
|
|
|
+ <template v-if="column.key === 'final_payout_amount'">
|
|
|
+ {{ formatCurrency(item[column.key]) }}
|
|
|
</template>
|
|
|
|
|
|
- <template
|
|
|
- v-else-if="
|
|
|
- column.key ===
|
|
|
- 'reservations_count'
|
|
|
- "
|
|
|
- >
|
|
|
- {{
|
|
|
- formatInteger(
|
|
|
- resolveReservationsCount(item)
|
|
|
- )
|
|
|
- }}
|
|
|
+ <template v-else-if="column.key === 'reservations_count'">
|
|
|
+ {{ formatInteger(resolveReservationsCount(item)) }}
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
@@ -95,17 +44,11 @@
|
|
|
<td>Total</td>
|
|
|
|
|
|
<td>
|
|
|
- {{
|
|
|
- formatInteger(
|
|
|
- totalReservations
|
|
|
- )
|
|
|
- }}
|
|
|
+ {{ formatInteger(totalReservations) }}
|
|
|
</td>
|
|
|
|
|
|
<td>
|
|
|
- {{
|
|
|
- formatCurrency(totalValue)
|
|
|
- }}
|
|
|
+ {{ formatCurrency(totalValue) }}
|
|
|
</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
@@ -114,10 +57,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import {
|
|
|
- computed,
|
|
|
- ref,
|
|
|
-} from "vue";
|
|
|
+import { computed, ref } from "vue";
|
|
|
|
|
|
const props = defineProps({
|
|
|
rows: {
|
|
|
@@ -156,91 +96,48 @@ const columns = ref([
|
|
|
},
|
|
|
]);
|
|
|
|
|
|
-const toggleSort = (
|
|
|
- column
|
|
|
-) => {
|
|
|
- column.direction =
|
|
|
- column.direction === "asc"
|
|
|
- ? "desc"
|
|
|
- : "asc";
|
|
|
-};
|
|
|
-
|
|
|
-const moveLeft = (index) => {
|
|
|
- const lastIndex =
|
|
|
- columns.value.length - 1;
|
|
|
-
|
|
|
- const targetIndex =
|
|
|
- index === 0
|
|
|
- ? lastIndex
|
|
|
- : index - 1;
|
|
|
-
|
|
|
- [
|
|
|
- columns.value[targetIndex],
|
|
|
- columns.value[index],
|
|
|
- ] = [
|
|
|
- columns.value[index],
|
|
|
- columns.value[targetIndex],
|
|
|
- ];
|
|
|
-};
|
|
|
+const toggleSort = (column) => {
|
|
|
+ columns.value.forEach((item) => {
|
|
|
+ if (item !== column) {
|
|
|
+ item.direction = null;
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
-const moveRight = (index) => {
|
|
|
- const lastIndex =
|
|
|
- columns.value.length - 1;
|
|
|
-
|
|
|
- const targetIndex =
|
|
|
- index === lastIndex
|
|
|
- ? 0
|
|
|
- : index + 1;
|
|
|
-
|
|
|
- [
|
|
|
- columns.value[targetIndex],
|
|
|
- columns.value[index],
|
|
|
- ] = [
|
|
|
- columns.value[index],
|
|
|
- columns.value[targetIndex],
|
|
|
- ];
|
|
|
+ column.direction = column.direction === "asc" ? "desc" : "asc";
|
|
|
};
|
|
|
|
|
|
const sortedRows = computed(() => {
|
|
|
- const activeSorts =
|
|
|
- columns.value.filter(
|
|
|
- (column) => column.direction
|
|
|
- );
|
|
|
+ const activeSorts = columns.value.filter((column) => column.direction);
|
|
|
|
|
|
if (!activeSorts.length) {
|
|
|
return [...props.rows];
|
|
|
}
|
|
|
|
|
|
- return [...props.rows].sort(
|
|
|
- (a, b) => {
|
|
|
- for (const sort of activeSorts) {
|
|
|
- const direction =
|
|
|
- sort.direction === "asc"
|
|
|
- ? 1
|
|
|
- : -1;
|
|
|
-
|
|
|
- const valueA =
|
|
|
- sort.key === "reservations_count"
|
|
|
- ? resolveReservationsCount(a)
|
|
|
- : a[sort.key];
|
|
|
-
|
|
|
- const valueB =
|
|
|
- sort.key === "reservations_count"
|
|
|
- ? resolveReservationsCount(b)
|
|
|
- : b[sort.key];
|
|
|
-
|
|
|
- if (valueA > valueB) {
|
|
|
- return direction;
|
|
|
- }
|
|
|
-
|
|
|
- if (valueA < valueB) {
|
|
|
- return -direction;
|
|
|
- }
|
|
|
+ return [...props.rows].sort((a, b) => {
|
|
|
+ for (const sort of activeSorts) {
|
|
|
+ const direction = sort.direction === "asc" ? 1 : -1;
|
|
|
+
|
|
|
+ const valueA =
|
|
|
+ sort.key === "reservations_count"
|
|
|
+ ? resolveReservationsCount(a)
|
|
|
+ : a[sort.key];
|
|
|
+
|
|
|
+ const valueB =
|
|
|
+ sort.key === "reservations_count"
|
|
|
+ ? resolveReservationsCount(b)
|
|
|
+ : b[sort.key];
|
|
|
+
|
|
|
+ if (valueA > valueB) {
|
|
|
+ return direction;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ if (valueA < valueB) {
|
|
|
+ return -direction;
|
|
|
+ }
|
|
|
}
|
|
|
- );
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
const resolveReservationsCount = (item) =>
|
|
|
@@ -248,28 +145,19 @@ const resolveReservationsCount = (item) =>
|
|
|
item.checkout_reservations_count ??
|
|
|
item.distinct_reservations_count ??
|
|
|
item.reservations_count ??
|
|
|
- 0
|
|
|
+ 0,
|
|
|
);
|
|
|
|
|
|
-const formatCurrency = (
|
|
|
- value
|
|
|
-) => {
|
|
|
- return new Intl.NumberFormat(
|
|
|
- "pt-BR",
|
|
|
- {
|
|
|
- style: "currency",
|
|
|
- currency: "BRL",
|
|
|
- minimumFractionDigits: 2,
|
|
|
- }
|
|
|
- ).format(Number(value ?? 0));
|
|
|
+const formatCurrency = (value) => {
|
|
|
+ return new Intl.NumberFormat("pt-BR", {
|
|
|
+ style: "currency",
|
|
|
+ currency: "BRL",
|
|
|
+ minimumFractionDigits: 2,
|
|
|
+ }).format(Number(value ?? 0));
|
|
|
};
|
|
|
|
|
|
-const formatInteger = (
|
|
|
- value
|
|
|
-) => {
|
|
|
- return Number(
|
|
|
- value ?? 0
|
|
|
- ).toLocaleString("pt-BR");
|
|
|
+const formatInteger = (value) => {
|
|
|
+ return Number(value ?? 0).toLocaleString("pt-BR");
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
@@ -327,12 +215,6 @@ const formatInteger = (
|
|
|
transition: 0.2s ease;
|
|
|
}
|
|
|
|
|
|
-.move-icon {
|
|
|
- opacity: 0.7;
|
|
|
- transition: 0.2s ease;
|
|
|
-}
|
|
|
-
|
|
|
-.move-icon:hover,
|
|
|
.sort-icon:hover {
|
|
|
opacity: 1;
|
|
|
transform: scale(1.08);
|