Просмотр исходного кода

feat: adiciona card de aniversariante

ebagabee 4 недель назад
Родитель
Сommit
331da0be9b
2 измененных файлов с 118 добавлено и 147 удалено
  1. 88 0
      src/components/charts/AniversariantesCard.vue
  2. 30 147
      src/pages/dashboard/DashboardPage.vue

+ 88 - 0
src/components/charts/AniversariantesCard.vue

@@ -0,0 +1,88 @@
+<template>
+  <q-card flat class="dashboard-chart-card card-ring">
+    <div class="flex justify-between items-center no-wrap q-mb-sm">
+      <span class="text-subtitle2 text-weight-regular">Aniversariantes do Mês</span>
+      <q-icon name="mdi-cake-variant-outline" color="secondary" size="sm" />
+    </div>
+
+    <div class="header-row text-caption text-grey-6 q-mb-xs">
+      <div class="flex items-center" style="gap: 4px">
+        <q-icon name="mdi-calendar-outline" size="14px" color="secondary" />
+        <span>Nome</span>
+      </div>
+      <span>Ações</span>
+    </div>
+    <q-separator />
+
+    <div class="list-scroll">
+      <q-list dense>
+        <template v-for="(person, index) in people" :key="index">
+          <q-item class="q-px-none person-item">
+            <q-item-section avatar style="min-width: 36px">
+              <div class="day-badge">{{ person.day }}</div>
+            </q-item-section>
+            <q-item-section>
+              <q-item-label class="text-body2">{{ person.name }}</q-item-label>
+            </q-item-section>
+            <q-item-section side>
+              <div class="flex items-center no-wrap" style="gap: 4px">
+                <q-btn flat round dense size="sm" icon="mdi-whatsapp" color="dark" />
+                <q-btn flat round dense size="sm" icon="mdi-email-outline" color="dark" />
+              </div>
+            </q-item-section>
+          </q-item>
+          <q-separator v-if="index < people.length - 1" />
+        </template>
+      </q-list>
+    </div>
+  </q-card>
+</template>
+
+<script setup>
+defineProps({
+  people: {
+    type: Array,
+    default: () => [],
+  },
+});
+</script>
+
+<style scoped>
+.dashboard-chart-card {
+  border-radius: 12px;
+  padding: 20px 24px;
+  display: flex;
+  flex-direction: column;
+}
+
+.header-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.list-scroll {
+  flex: 1;
+  overflow-y: auto;
+  min-height: 0;
+}
+
+.person-item {
+  padding-top: 6px;
+  padding-bottom: 6px;
+}
+
+.day-badge {
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  background-color: #f97316;
+  color: #fff;
+  font-size: 12px;
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+}
+</style>

+ 30 - 147
src/pages/dashboard/DashboardPage.vue

@@ -136,92 +136,28 @@
       </div>
 
       <!-- Row 3: Bottom -->
-      <div class="row q-col-gutter-md">
-        <div class="col-12 col-md-4">
-          <q-card flat bordered style="height: 320px">
-            <q-card-section class="row justify-between items-center q-pb-xs">
-              <span class="text-subtitle2 text-weight-medium"
-                >Matrículas por Período</span
-              >
-              <q-icon name="mdi-book-open-outline" color="grey-5" />
-            </q-card-section>
-            <q-separator />
-            <q-card-section
-              style="height: calc(100% - 57px)"
-              class="q-pt-sm q-px-sm"
-            >
-              <Bar
-                :data="matriculasData"
-                :options="matriculasOptions"
-                :plugins="[ChartDataLabels]"
-              />
-            </q-card-section>
-          </q-card>
+      <div class="row q-col-gutter-md items-stretch">
+        <div class="col-12 col-md-5">
+          <DashboardChartCard title="Matrículas por Período" style="height: 100%">
+            <GroupedBarChart
+              :labels="matriculasChart.labels"
+              :datasets="matriculasChart.datasets"
+              :bar-radius="50"
+              :show-datalabels="true"
+              :max-bar-thickness="44"
+              :category-percentage="0.6"
+              :bar-percentage="0.85"
+              class="full-width full-height"
+            />
+          </DashboardChartCard>
         </div>
 
         <div class="col-12 col-md-4">
-          <q-card flat bordered style="height: 320px">
-            <q-card-section class="row justify-between items-center q-pb-xs">
-              <span class="text-subtitle2 text-weight-medium"
-                >Aniversariantes do Mês</span
-              >
-              <q-icon name="mdi-gift-outline" color="grey-5" />
-            </q-card-section>
-            <q-separator />
-            <div class="row justify-between items-center q-px-md q-py-xs">
-              <span class="text-caption text-grey-6">Nome</span>
-              <span class="text-caption text-grey-6">Ações</span>
-            </div>
-            <q-separator />
-            <div style="height: calc(100% - 105px); overflow-y: auto">
-              <q-list separator>
-                <q-item
-                  v-for="(pessoa, i) in aniversariantes"
-                  :key="i"
-                  dense
-                  class="q-py-sm"
-                >
-                  <q-item-section avatar>
-                    <q-avatar
-                      :color="pessoa.color"
-                      text-color="white"
-                      size="34px"
-                      class="text-caption text-bold"
-                    >
-                      {{ pessoa.nome[0] }}
-                    </q-avatar>
-                  </q-item-section>
-                  <q-item-section>
-                    <q-item-label>{{ pessoa.nome }}</q-item-label>
-                  </q-item-section>
-                  <q-item-section side>
-                    <div class="row">
-                      <q-btn
-                        flat
-                        dense
-                        round
-                        icon="mdi-whatsapp"
-                        color="green"
-                        size="sm"
-                      />
-                      <q-btn
-                        flat
-                        dense
-                        round
-                        icon="mdi-email-outline"
-                        color="grey-6"
-                        size="sm"
-                      />
-                    </div>
-                  </q-item-section>
-                </q-item>
-              </q-list>
-            </div>
-          </q-card>
+          <AniversariantesCard :people="aniversariantes" style="height: 100%" />
         </div>
 
-        <div class="col-12 col-md-4">
-          <q-card flat bordered style="height: 320px">
+        <div class="col-12 col-md-3">
+          <q-card flat bordered class="full-height">
             <q-card-section class="row justify-between items-center q-pb-xs">
               <span class="text-subtitle2 text-weight-medium"
                 >Feriados do mês</span
@@ -266,32 +202,15 @@
 
 <script setup>
 import { ref } from "vue";
-import { Bar, Doughnut } from "vue-chartjs";
-import {
-  Chart as ChartJS,
-  Title,
-  Tooltip,
-  Legend,
-  BarElement,
-  CategoryScale,
-  LinearScale,
-  ArcElement,
-} from "chart.js";
-import ChartDataLabels from "chartjs-plugin-datalabels";
+import { Doughnut } from "vue-chartjs";
+import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
 import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
 import DashboardStatCard from "src/components/charts/DashboardStatCard.vue";
 import DashboardChartCard from "src/components/charts/DashboardChartCard.vue";
 import GroupedBarChart from "src/components/charts/normal/GroupedBarChart.vue";
+import AniversariantesCard from "src/components/charts/AniversariantesCard.vue";
 
-ChartJS.register(
-  Title,
-  Tooltip,
-  Legend,
-  BarElement,
-  CategoryScale,
-  LinearScale,
-  ArcElement,
-);
+ChartJS.register(ArcElement, Tooltip, Legend);
 
 const faturamentoChart = {
   labels: [
@@ -393,60 +312,24 @@ const gaugeNeedlePlugin = {
   },
 };
 
-const matriculasData = ref({
+const matriculasChart = {
   labels: ["JAN", "FEV", "MAR", "ABR", "MAI", "JUN"],
   datasets: [
     {
       label: "Matrículas",
       data: [120, 200, 150, 80, 70, 110],
-      backgroundColor: [
-        "#2196F3",
-        "#F44336",
-        "#9C27B0",
-        "#FFC107",
-        "#212121",
-        "#009688",
-      ],
-      borderColor: [
-        "#2196F3",
-        "#F44336",
-        "#9C27B0",
-        "#FFC107",
-        "#212121",
-        "#009688",
-      ],
-      borderWidth: 1,
-      borderRadius: 2,
+      color: ["#3B82F6", "#EF4444", "#A855F7", "#374151", "#EAB308", "#06B6D4"],
     },
   ],
-});
-
-const matriculasOptions = ref({
-  responsive: true,
-  maintainAspectRatio: false,
-  plugins: {
-    legend: { display: false },
-    datalabels: {
-      anchor: "end",
-      align: "top",
-      color: "#666",
-      font: { size: 11, weight: "bold" },
-      formatter: (v) => v,
-    },
-  },
-  scales: {
-    x: { ticks: { font: { size: 11 } }, grid: { display: false } },
-    y: { display: false, suggestedMin: 0, suggestedMax: 230 },
-  },
-});
+};
 
 const aniversariantes = ref([
-  { nome: "Heloisa Faria", color: "orange" },
-  { nome: "Juliana Costa", color: "green" },
-  { nome: "Juliana Costa", color: "green" },
-  { nome: "Fernando Almeida", color: "blue" },
-  { nome: "Lucas Pereira", color: "purple" },
-  { nome: "Sofia Martins", color: "teal" },
+  { day: 10, name: "Heloisa Faria" },
+  { day: 11, name: "Juliana Costa" },
+  { day: 16, name: "Juliana Costa" },
+  { day: 23, name: "Fernando Almeida" },
+  { day: 29, name: "Lucas Pereira" },
+  { day: 34, name: "Sofia Martins" },
 ]);
 
 const feriados = ref([