|
|
@@ -33,32 +33,26 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div v-if="activeCard">
|
|
|
- <q-card flat class="bg-white q-pa-md" style="border-radius: 12px">
|
|
|
- <div v-if="tableLoading" class="flex flex-center q-pa-xl">
|
|
|
- <q-spinner color="violet-normal" size="40px" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <DefaultTable
|
|
|
- v-else
|
|
|
- v-model:rows="tableRows"
|
|
|
- :columns="tableColumns"
|
|
|
- no-api-call
|
|
|
- :rows-per-page="10"
|
|
|
- :show-search-field="false"
|
|
|
- >
|
|
|
- <template #body-cell-status="{ row }">
|
|
|
- <q-td>
|
|
|
- <q-badge
|
|
|
- :color="getStatusColor(row.status)"
|
|
|
- :label="$t(getStatusI18nKey(row.status))"
|
|
|
- class="text-capitalize"
|
|
|
- />
|
|
|
- </q-td>
|
|
|
- </template>
|
|
|
- </DefaultTable>
|
|
|
- </q-card>
|
|
|
- </div>
|
|
|
+ <q-card v-if="activeCard" flat class="bg-white" style="border-radius: 12px">
|
|
|
+ <DefaultTableServerSide
|
|
|
+ :key="activeCard"
|
|
|
+ :columns="tableColumns"
|
|
|
+ :api-call="activeApiCall"
|
|
|
+ :add-item="false"
|
|
|
+ sem-table-top
|
|
|
+ >
|
|
|
+ <template #body-cell-status="{ row }">
|
|
|
+ <q-td>
|
|
|
+ <q-badge
|
|
|
+ :color="getStatusColor(row.status)"
|
|
|
+ :label="$t(getStatusI18nKey(row.status))"
|
|
|
+ class="text-capitalize"
|
|
|
+ outline
|
|
|
+ />
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
+ </DefaultTableServerSide>
|
|
|
+ </q-card>
|
|
|
</template>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -68,128 +62,78 @@
|
|
|
import { ref, computed, onMounted } from "vue";
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
|
|
|
-import DefaultTable from "src/components/defaults/DefaultTable.vue";
|
|
|
+import DefaultTableServerSide from "src/components/defaults/DefaultTableServerSide.vue";
|
|
|
import { getDashboardStats } from "src/api/dashboard";
|
|
|
-import { getUsers } from "src/api/user";
|
|
|
-import { getPartnerAgreements } from "src/api/partnerAgreement";
|
|
|
+import { getUsersPaginated } from "src/api/user";
|
|
|
+import { getPartnerAgreementsPaginated } from "src/api/partnerAgreement";
|
|
|
import { formatDateYMDtoDMY, getStatusColor, getStatusI18nKey } from "src/helpers/utils";
|
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
|
const statsLoading = ref(true);
|
|
|
-const tableLoading = ref(false);
|
|
|
const stats = ref({});
|
|
|
const activeCard = ref(null);
|
|
|
-const tableRows = ref([]);
|
|
|
-
|
|
|
-const usersCache = ref(null);
|
|
|
-const partnersCache = ref(null);
|
|
|
|
|
|
const statCards = [
|
|
|
- { key: "total_associados", icon: "mdi-account-group", labelKey: "dashboard.stats.total_associados" },
|
|
|
- { key: "associados_ativos", icon: "mdi-trending-up", labelKey: "dashboard.stats.associados_ativos" },
|
|
|
- { key: "parceiros", icon: "mdi-handshake", labelKey: "dashboard.stats.parceiros" },
|
|
|
- { key: "contratos_a_vencer", icon: "mdi-file-clock", labelKey: "dashboard.stats.contratos_a_vencer" },
|
|
|
- { key: "novos_mes", icon: "mdi-account-plus", labelKey: "dashboard.stats.novos_mes" },
|
|
|
+ { key: "total_associados", icon: "mdi-account-group", labelKey: "dashboard.stats.total_associados" },
|
|
|
+ { key: "associados_ativos", icon: "mdi-trending-up", labelKey: "dashboard.stats.associados_ativos" },
|
|
|
+ { key: "parceiros", icon: "mdi-handshake", labelKey: "dashboard.stats.parceiros" },
|
|
|
+ { key: "contratos_a_vencer", icon: "mdi-file-clock", labelKey: "dashboard.stats.contratos_a_vencer" },
|
|
|
+ { key: "novos_mes", icon: "mdi-account-plus", labelKey: "dashboard.stats.novos_mes" },
|
|
|
{ key: "associados_pendentes", icon: "mdi-account-alert", labelKey: "dashboard.stats.associados_pendentes" },
|
|
|
];
|
|
|
|
|
|
+// Colunas por tipo de card
|
|
|
const columnsAssociados = computed(() => [
|
|
|
- { name: "name", label: t("common.terms.name"), field: "name", align: "left", sortable: true },
|
|
|
- { name: "email", label: t("common.terms.email"), field: "email", align: "left", sortable: true },
|
|
|
- { name: "created_at", label: t("dashboard.stats.association_date"), field: (row) => formatDateYMDtoDMY(row.created_at), align: "left", sortable: true },
|
|
|
- { name: "status", label: t("common.terms.status"), field: "status", align: "left" },
|
|
|
+ { name: "name", label: t("common.terms.name"), field: "name", align: "left", sortable: true },
|
|
|
+ { name: "email", label: t("common.terms.email"), field: "email", align: "left", sortable: true },
|
|
|
+ { name: "created_at", label: t("dashboard.stats.association_date"), field: (row) => formatDateYMDtoDMY(row.created_at), align: "left", sortable: true },
|
|
|
+ { name: "status", label: t("common.terms.status"), field: "status", align: "left" },
|
|
|
]);
|
|
|
|
|
|
const columnsParceiros = computed(() => [
|
|
|
- { name: "company_name", label: t("common.terms.name"), field: "company_name", align: "left", sortable: true },
|
|
|
+ { name: "company_name", label: t("common.terms.name"), field: "company_name", align: "left", sortable: true },
|
|
|
{ name: "responsible", label: t("parceiro.responsible"), field: "responsible", align: "left", sortable: true },
|
|
|
{ name: "created_at", label: t("dashboard.stats.registration_date"), field: (row) => formatDateYMDtoDMY(row.created_at), align: "left", sortable: true },
|
|
|
{ name: "status", label: t("common.terms.status"), field: "status", align: "left" },
|
|
|
]);
|
|
|
|
|
|
const columnsContratosAVencer = computed(() => [
|
|
|
- { name: "company_name", label: t("common.terms.name"), field: "company_name", align: "left", sortable: true },
|
|
|
- { name: "responsible", label: t("parceiro.responsible"), field: "responsible", align: "left", sortable: true },
|
|
|
- { name: "contract_end", label: t("parceiro.contract_end"), field: (row) => formatDateYMDtoDMY(row.contract_end), align: "left", sortable: true },
|
|
|
- { name: "status", label: t("common.terms.status"), field: "status", align: "left" },
|
|
|
+ { name: "company_name", label: t("common.terms.name"), field: "company_name", align: "left", sortable: true },
|
|
|
+ { name: "responsible", label: t("parceiro.responsible"), field: "responsible", align: "left", sortable: true },
|
|
|
+ { name: "contract_end", label: t("parceiro.contract_end"), field: (row) => formatDateYMDtoDMY(row.contract_end), align: "left", sortable: true },
|
|
|
+ { name: "status", label: t("common.terms.status"), field: "status", align: "left" },
|
|
|
]);
|
|
|
|
|
|
const tableColumns = computed(() => {
|
|
|
if (!activeCard.value) return [];
|
|
|
if (activeCard.value === "contratos_a_vencer") return columnsContratosAVencer.value;
|
|
|
- if (activeCard.value === "parceiros" || activeCard.value === "novos_mes") {
|
|
|
- return columnsParceiros.value;
|
|
|
- }
|
|
|
+ if (activeCard.value === "parceiros" || activeCard.value === "novos_mes") return columnsParceiros.value;
|
|
|
return columnsAssociados.value;
|
|
|
});
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-const loadUsers = async () => {
|
|
|
- if (usersCache.value) return usersCache.value;
|
|
|
- const users = await getUsers();
|
|
|
- usersCache.value = users;
|
|
|
- return users;
|
|
|
-};
|
|
|
-
|
|
|
-const loadPartners = async () => {
|
|
|
- if (partnersCache.value) return partnersCache.value;
|
|
|
- const partners = await getPartnerAgreements();
|
|
|
- partnersCache.value = partners;
|
|
|
- return partners;
|
|
|
-};
|
|
|
-
|
|
|
-const isCurrentMonth = (dateStr) => {
|
|
|
- if (!dateStr) return false;
|
|
|
- const now = new Date();
|
|
|
- const [datePart] = dateStr.split(" ");
|
|
|
- const [year, month] = datePart.split("-");
|
|
|
- return parseInt(year) === now.getFullYear() && parseInt(month) === now.getMonth() + 1;
|
|
|
-};
|
|
|
-
|
|
|
-const getStatusValue = (status) => typeof status === "object" ? status?.value : status;
|
|
|
-
|
|
|
-const onCardClick = async (card) => {
|
|
|
- if (activeCard.value === card.key) return;
|
|
|
-
|
|
|
- activeCard.value = card.key;
|
|
|
- tableLoading.value = true;
|
|
|
- tableRows.value = [];
|
|
|
-
|
|
|
- try {
|
|
|
- if (card.key === "contratos_a_vencer") {
|
|
|
- const partners = await loadPartners();
|
|
|
- const today = new Date();
|
|
|
- today.setHours(0, 0, 0, 0);
|
|
|
- const in30Days = new Date(today);
|
|
|
- in30Days.setDate(in30Days.getDate() + 30);
|
|
|
- tableRows.value = partners.filter((p) => {
|
|
|
- if (!p.contract_end) return false;
|
|
|
- const end = new Date(p.contract_end + "T00:00:00");
|
|
|
- return end >= today && end <= in30Days;
|
|
|
- });
|
|
|
- } else if (card.key === "parceiros") {
|
|
|
- const partners = await loadPartners();
|
|
|
- tableRows.value = partners;
|
|
|
- } else if (card.key === "novos_mes") {
|
|
|
- const partners = await loadPartners();
|
|
|
- tableRows.value = partners.filter((p) => isCurrentMonth(p.created_at));
|
|
|
- } else {
|
|
|
- const users = await loadUsers();
|
|
|
- const associados = users.filter((u) => getStatusValue(u.type) === "associado");
|
|
|
-
|
|
|
- if (card.key === "total_associados") {
|
|
|
- tableRows.value = associados;
|
|
|
- } else if (card.key === "associados_ativos") {
|
|
|
- tableRows.value = associados.filter((u) => getStatusValue(u.status) === "active");
|
|
|
- } else if (card.key === "associados_pendentes") {
|
|
|
- tableRows.value = associados.filter((u) => getStatusValue(u.status) === "pending");
|
|
|
- }
|
|
|
- }
|
|
|
- } finally {
|
|
|
- tableLoading.value = false;
|
|
|
+// Função de API correspondente a cada card — nova referência a cada computed
|
|
|
+const activeApiCall = computed(() => {
|
|
|
+ switch (activeCard.value) {
|
|
|
+ case "total_associados":
|
|
|
+ return (p) => getUsersPaginated({ ...p, type: "associado" });
|
|
|
+ case "associados_ativos":
|
|
|
+ return (p) => getUsersPaginated({ ...p, type: "associado", status: "active" });
|
|
|
+ case "associados_pendentes":
|
|
|
+ return (p) => getUsersPaginated({ ...p, type: "associado", status: "pending" });
|
|
|
+ case "parceiros":
|
|
|
+ return (p) => getPartnerAgreementsPaginated({ ...p });
|
|
|
+ case "contratos_a_vencer":
|
|
|
+ return (p) => getPartnerAgreementsPaginated({ ...p, expiresInDays: 30 });
|
|
|
+ case "novos_mes":
|
|
|
+ return (p) => getPartnerAgreementsPaginated({ ...p, createdMonth: "current" });
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
}
|
|
|
+});
|
|
|
+
|
|
|
+const onCardClick = (card) => {
|
|
|
+ activeCard.value = activeCard.value === card.key ? null : card.key;
|
|
|
};
|
|
|
|
|
|
onMounted(async () => {
|