Преглед изворни кода

feat(DashboardStatCard): add support for multiple badges and update dashboard card to use them

alvesantos пре 4 дана
родитељ
комит
c8eb8335f2
2 измењених фајлова са 29 додато и 5 уклоњено
  1. 18 1
      src/components/charts/DashboardStatCard.vue
  2. 11 4
      src/pages/dashboard/DashboardPage.vue

+ 18 - 1
src/components/charts/DashboardStatCard.vue

@@ -12,8 +12,18 @@
     <div class="value-area">
       <span class="text-h5 value-text card-value">{{ value }}</span>
 
+      <div v-if="badges && badges.length" class="stat-badges">
+        <q-badge
+          v-for="badgeItem in badges"
+          :key="badgeItem.label"
+          :color="badgeItem.color || badgeColor"
+          :label="badgeItem.label"
+          :style="customStyle"
+          class="stat-badge"
+        />
+      </div>
       <q-badge
-        v-if="badge"
+        v-else-if="badge"
         :color="badgeColor"
         :label="badge"
         :style="customStyle"
@@ -35,6 +45,7 @@ defineProps({
   value: { type: [String, Number], required: true },
   subtitle: { type: String, default: "" },
   badge: { type: String, default: "" },
+  badges: { type: Array, default: () => [] },
   badgeColor: { type: String, default: "accent-1" },
   customStyle: { type: String, default: "padding: 4px" },
   clickable: { type: Boolean, default: false },
@@ -95,6 +106,12 @@ const emit = defineEmits(["click"]);
   line-height: 1.2;
 }
 
+.stat-badges {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 4px;
+}
+
 .stat-badge {
   font-size: 12px;
   border-radius: 8px;

+ 11 - 4
src/pages/dashboard/DashboardPage.vue

@@ -117,10 +117,10 @@
 
       <div class="stat-cards-row">
         <DashboardStatCard
-          title="Total alunos (contratos ativos)"
+          title="Total alunos"
           icon="mdi-account-multiple-outline"
           :value="totalStudents"
-          :badge="`${activeContracts} ativos`"
+          :badges="studentsStatusBadges"
           clickable
           @click="openActiveStudentsDialog"
         />
@@ -248,7 +248,7 @@ const isLoading = ref(true);
 
 // ─── Metric counters ─────────────────────────────────────────
 const totalStudents    = ref(0);
-const activeContracts  = ref(0);
+const studentsByStatus = ref({ active: 0, ex_student: 0, lead: 0, locked: 0 });
 const frozenContracts  = ref(0);
 const cancelledContracts = ref(0);
 const openTickets      = ref(0);
@@ -340,6 +340,13 @@ const receivablesPeriodLabel = computed(() => {
  * - Unit selected   → just that unit ID
  * - Nothing selected → [] (no filter = all units)
  */
+const studentsStatusBadges = computed(() => [
+  { color: "info", label: `${studentsByStatus.value.lead} Lead` },
+  { color: "positive", label: `${studentsByStatus.value.active} Ativo` },
+  { color: "grey", label: `${studentsByStatus.value.ex_student} Ex-aluno` },
+  { color: "warning", label: `${studentsByStatus.value.locked} Trancado` },
+]);
+
 const activeUnitIds = computed(() => {
   if (selectedGroup.value?.unit_ids?.length) {
     return selectedGroup.value.unit_ids;
@@ -431,7 +438,7 @@ const fetchMetrics = async () => {
   ]);
 
   totalStudents.value      = studentSummary.total;
-  activeContracts.value    = contractSummary.active ?? 0;
+  studentsByStatus.value   = studentSummary.by_status ?? studentsByStatus.value;
   frozenContracts.value    = contractSummary.frozen;
   cancelledContracts.value = contractSummary.cancelled;