Explorar el Código

feat: adiciona dashboardStatCard

ebagabee hace 1 mes
padre
commit
113a547b73
Se han modificado 2 ficheros con 90 adiciones y 74 borrados
  1. 47 0
      src/components/charts/DashboardStatCard.vue
  2. 43 74
      src/pages/dashboard/DashboardPage.vue

+ 47 - 0
src/components/charts/DashboardStatCard.vue

@@ -0,0 +1,47 @@
+<template>
+  <q-card class="stat-card q-pa-lg">
+    <div class="column full-width" style="gap: 8px">
+      <div class="flex justify-between items-start no-wrap">
+        <span class="text-body2 text-grey-6">{{ title }}</span>
+        <q-icon :name="icon" size="22px" color="grey-5" />
+      </div>
+
+      <span class="text-h4 text-primary" style="font-weight: 600; line-height: 1.2">
+        {{ value }}
+      </span>
+
+      <q-badge
+        v-if="badge"
+        color="secondary"
+        :label="badge"
+        class="stat-badge"
+      />
+      <span v-else class="text-caption text-grey-6">{{ subtitle }}</span>
+    </div>
+  </q-card>
+</template>
+
+<script setup>
+defineProps({
+  title: { type: String, required: true },
+  icon: { type: String, default: "mdi-information-outline" },
+  value: { type: [String, Number], required: true },
+  subtitle: { type: String, default: "" },
+  badge: { type: String, default: "" },
+});
+</script>
+
+<style scoped>
+.stat-card {
+  flex: 1 1 200px;
+  border-radius: 8px;
+  box-shadow: 0 0 0 1px #c0c0c0c0 !important;
+}
+
+.stat-badge {
+  font-size: 0.75rem;
+  padding: 4px 8px;
+  border-radius: 4px;
+  width: fit-content;
+}
+</style>

+ 43 - 74
src/pages/dashboard/DashboardPage.vue

@@ -161,71 +161,31 @@
     </div>
 
     <div v-if="!isLoading" class="column gap q-pa-sm">
-      <div class="flex full-width gap">
-        <div class="flex flex-grow gap">
-          <CardIconMiniChart
-            class="flex-grow"
-            :title="t('dashboard.cards.total_earnings')"
-            :icon="'mdi-currency-usd'"
-            :number-porcent="paymentsChart.percentage_change"
-            :number-card="
-              t('dashboard.currency_format', {
-                value: paymentsChart.current_total,
-              })
-            "
-          >
-            <template #chart>
-              <MiniLineChart
-                :data="paymentsChart.trend_data"
-                fill-color="rgba(0, 0, 0, 0)"
-              />
-            </template>
-          </CardIconMiniChart>
-          <CardIconMiniChart
-            class="flex-grow"
-            :title="t('orders.plural')"
-            :icon="'mdi-package-variant'"
-            :number-porcent="ordersChart.percentage_change"
-            :number-card="ordersChart.current_total"
-          >
-            <template #chart>
-              <MiniBarChart
-                :data="ordersChart.trend_data"
-                fill-color="rgba(0, 0, 0, 0)"
-              />
-            </template>
-          </CardIconMiniChart>
-        </div>
-        <div class="flex flex-grow gap">
-          <CardIconMiniChart
-            class="flex-grow"
-            :title="t('dashboard.cards.tickets_sold')"
-            :icon="'mdi-ticket-outline'"
-            :number-porcent="ticketsSoldChart.percentage_change"
-            :number-card="ticketsSoldChart.current_total"
-          >
-            <template #chart>
-              <MiniLineChart
-                :data="ticketsSoldChart.trend_data"
-                fill-color="rgba(0, 0, 0, 0)"
-              />
-            </template>
-          </CardIconMiniChart>
-          <CardIconMiniChart
-            class="flex-grow"
-            :title="t('dashboard.cards.registrations')"
-            :icon="'mdi-account-group-outline'"
-            :number-porcent="participantsChart.percentage_change"
-            :number-card="participantsChart.current_total"
-          >
-            <template #chart>
-              <MiniBarChart
-                :data="participantsChart.trend_data"
-                fill-color="rgba(0, 0, 0, 0)"
-              />
-            </template>
-          </CardIconMiniChart>
-        </div>
+      <div class="stat-cards-row">
+        <DashboardStatCard
+          title="Total alunos (contratos ativos)"
+          icon="mdi-account-multiple"
+          value="4.527"
+          badge="3.200 ativos"
+        />
+        <DashboardStatCard
+          title="Contratos Congelados"
+          icon="mdi-snowflake"
+          value="57"
+          subtitle="É hora de incentivar nossos alunos"
+        />
+        <DashboardStatCard
+          title="Contratos Cancelados"
+          icon="mdi-cancel"
+          value="57"
+          subtitle="É hora de incentivar nossos alunos"
+        />
+        <DashboardStatCard
+          title="Receita Geral"
+          icon="mdi-currency-usd"
+          value="R$ 51.548,80"
+          subtitle="0 pagamentos pendentes"
+        />
       </div>
 
       <div class="flex full-width gap">
@@ -312,16 +272,8 @@
 import { onMounted, ref, watch, defineAsyncComponent } from "vue";
 import { useI18n } from "vue-i18n";
 import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
+import DashboardStatCard from "src/components/charts/DashboardStatCard.vue";
 
-const MiniLineChart = defineAsyncComponent(
-  () => import("src/components/charts/mini/MiniLineChart.vue"),
-);
-const MiniBarChart = defineAsyncComponent(
-  () => import("src/components/charts/mini/MiniBarChart.vue"),
-);
-const CardIconMiniChart = defineAsyncComponent(
-  () => import("src/components/charts/CardIconMiniChart.vue"),
-);
 const CardIconChart = defineAsyncComponent(
   () => import("src/components/charts/CardIconChart.vue"),
 );
@@ -530,6 +482,23 @@ onMounted(async () => {
   flex-shrink: 0;
 }
 
+.stat-cards-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px;
+}
+
+.stat-cards-row > * {
+  flex: 1 1 200px;
+  min-width: 180px;
+}
+
+@media (max-width: 599px) {
+  .stat-cards-row > * {
+    flex: 1 1 100%;
+  }
+}
+
 .filter-row {
   display: flex;
   flex-wrap: wrap;