|
|
@@ -12,7 +12,7 @@
|
|
|
<div
|
|
|
v-for="card in statCards"
|
|
|
:key="card.key"
|
|
|
- class="col-12 col-sm-6 col-md-4 col-lg-2"
|
|
|
+ class="col-12 col-sm-6 col-md-4 col-lg"
|
|
|
>
|
|
|
<q-card
|
|
|
flat
|
|
|
@@ -40,6 +40,7 @@
|
|
|
:api-call="activeApiCall"
|
|
|
:add-item="false"
|
|
|
sem-table-top
|
|
|
+ :show-search-field="activeCard !== 'ultimos_acessos'"
|
|
|
>
|
|
|
<template #body-cell-status="{ row }">
|
|
|
<q-td>
|
|
|
@@ -51,6 +52,22 @@
|
|
|
/>
|
|
|
</q-td>
|
|
|
</template>
|
|
|
+
|
|
|
+ <template #body-cell-user_type="{ row }">
|
|
|
+ <q-td class="text-center">
|
|
|
+ <q-badge
|
|
|
+ outline
|
|
|
+ :color="row.user_type === 'associado' ? 'violet-normal' : 'teal'"
|
|
|
+ :label="row.user_type === 'associado' ? $t('auth.type.associado') : $t('auth.type.parceiro')"
|
|
|
+ />
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #body-cell-accessed_at="{ row }">
|
|
|
+ <q-td>
|
|
|
+ {{ formatDateTime(row.accessed_at) }}
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
</DefaultTableServerSide>
|
|
|
</q-card>
|
|
|
</template>
|
|
|
@@ -66,6 +83,7 @@ import DefaultTableServerSide from "src/components/defaults/DefaultTableServerSi
|
|
|
import { getDashboardStats } from "src/api/dashboard";
|
|
|
import { getUsersPaginated } from "src/api/user";
|
|
|
import { getPartnerAgreementsPaginated, getExpiringPartnerAgreementsPaginated } from "src/api/partnerAgreement";
|
|
|
+import { getAccessLogsPaginated } from "src/api/userAccessLog";
|
|
|
import { formatDateYMDtoDMY, getStatusColor, getStatusI18nKey } from "src/helpers/utils";
|
|
|
|
|
|
const { t } = useI18n();
|
|
|
@@ -81,6 +99,7 @@ const statCards = [
|
|
|
{ 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" },
|
|
|
+ { key: "ultimos_acessos", icon: "mdi-login-variant", labelKey: "dashboard.stats.ultimos_acessos" },
|
|
|
];
|
|
|
|
|
|
// Colunas por tipo de card
|
|
|
@@ -105,10 +124,17 @@ const columnsContratosAVencer = computed(() => [
|
|
|
{ name: "status", label: t("common.terms.status"), field: "status", align: "left" },
|
|
|
]);
|
|
|
|
|
|
+const columnsAccessLogs = computed(() => [
|
|
|
+ { name: "user_name", label: t("access_log.user"), field: "user_name", align: "left", sortable: false },
|
|
|
+ { name: "user_type", label: t("access_log.user_type"), field: "user_type", align: "center", sortable: false },
|
|
|
+ { name: "accessed_at", label: t("access_log.accessed_at"), field: "accessed_at", align: "left", sortable: false },
|
|
|
+]);
|
|
|
+
|
|
|
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 === "ultimos_acessos") return columnsAccessLogs.value;
|
|
|
return columnsAssociados.value;
|
|
|
});
|
|
|
|
|
|
@@ -127,11 +153,22 @@ const activeApiCall = computed(() => {
|
|
|
return (p) => getExpiringPartnerAgreementsPaginated({ ...p });
|
|
|
case "novos_mes":
|
|
|
return (p) => getPartnerAgreementsPaginated({ ...p, createdMonth: "current" });
|
|
|
+ case "ultimos_acessos":
|
|
|
+ return (p) => getAccessLogsPaginated({ ...p, last_per_user: true });
|
|
|
default:
|
|
|
return null;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+const formatDateTime = (isoString) => {
|
|
|
+ if (!isoString) return "—";
|
|
|
+ const d = new Date(isoString);
|
|
|
+ return d.toLocaleString("pt-BR", {
|
|
|
+ day: "2-digit", month: "2-digit", year: "numeric",
|
|
|
+ hour: "2-digit", minute: "2-digit", second: "2-digit",
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
const onCardClick = (card) => {
|
|
|
activeCard.value = activeCard.value === card.key ? null : card.key;
|
|
|
};
|