Parcourir la source

♻️ refactor(charts): remover componentes de gráficos não utilizados na plataforma

Fase: dev | Origin: melhoria-interna
Gustavo Zanatta il y a 1 semaine
Parent
commit
8f03f63d4a

+ 0 - 81
src/components/charts/CardIconChart.vue

@@ -1,81 +0,0 @@
-<template>
-  <q-card
-    flat
-    class="full-height q-pa-lg chart-card card-ring"
-    :style="{
-      minHeight: $q.screen.lt.sm ? '400px' : '600px',
-      minWidth: $q.screen.lt.sm ? '200px' : '300px',
-    }"
-  >
-    <div class="column no-wrap full-width">
-      <div class="flex justify-between items-center no-wrap">
-        <span class="text-h5">{{ title }}</span>
-        <div class="flex no-wrap flex-center">
-          <div class="round">
-            <q-icon :name="icon" size="24px" :color="color" />
-          </div>
-          <!-- <q-icon
-            v-if="downloadImage !== null"
-            name="mdi-dots-vertical"
-            size="sm"
-            style="width: 12px;margin-right: -12px"
-            @click="downloadImage"
-          /> -->
-        </div>
-      </div>
-    </div>
-    <div class="flex flex-grow flex-center" style="height: calc(100% - 30px)">
-      <template v-if="hasChartSlot">
-        <slot name="chart"></slot>
-      </template>
-      <template v-else>
-        <div v-if="!loading" class="q-my-md row justify-center full-width">
-          <div class="q-pa-md body2">
-            {{ $t("http.errors.no_records_found") }}
-          </div>
-        </div>
-      </template>
-    </div>
-  </q-card>
-</template>
-
-<script setup>
-import { useSlots } from "vue";
-
-const hasChartSlot = useSlots("chart");
-
-const { color, title, icon } = defineProps({
-  color: {
-    type: String,
-    default: "primary",
-  },
-  title: {
-    type: String,
-    default: "Usuários",
-  },
-  icon: {
-    type: String,
-    default: "mdi-account",
-  },
-});
-</script>
-<style lang="scss" scoped>
-@use "sass:map";
-@use "src/css/quasar.variables.scss";
-
-body.body--light {
-  .background {
-    background: rgba(map.get($colors, "primary"), 0.2) !important;
-  }
-}
-
-body.body--dark {
-  .background {
-    background: rgba(map.get($colors-dark, "primary"), 0.2) !important;
-  }
-}
-
-.chart-card {
-  border-radius: 8px;
-}
-</style>

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

@@ -1,88 +0,0 @@
-<template>
-  <q-card class="q-pa-lg mini-card card-ring">
-    <div class="column no-wrap full-width">
-      <div class="flex justify-between items-center no-wrap">
-        <span class="text-h5">{{ title }}</span>
-        <div class="round">
-          <q-icon :name="icon" size="24px" :color="color" />
-        </div>
-      </div>
-      <div class="flex no-wrap full-width justify-between q-pa-sm">
-        <div class="column flex-center">
-          <span :class="numberCard.length >= 7 ? 'text-h4' : 'text-h3'">
-            {{ numberCard }}
-          </span>
-          <div
-            v-if="numberPorcent !== null"
-            class="flex no-wrap text-subtitle2"
-            :class="numberPorcent > 0 ? 'text-positive' : 'text-negative'"
-          >
-            <q-icon
-              :name="numberPorcent > 0 ? 'mdi-arrow-up' : 'mdi-arrow-down'"
-              size="18px"
-              class="q-mr-xs"
-            />
-            {{ numberPorcent + "%" }}
-          </div>
-        </div>
-        <div class="flex justify-end" style="max-width: 120px; height: 80px">
-          <slot name="chart" :color="color" :chart-data="chartData" />
-        </div>
-      </div>
-    </div>
-  </q-card>
-</template>
-
-<script setup>
-const { color, title, icon, chartData, numberCard, numberPorcent } =
-  defineProps({
-    color: {
-      type: String,
-      default: "primary",
-    },
-    title: {
-      type: String,
-      default: "Usuários",
-    },
-    icon: {
-      type: String,
-      default: "mdi-account",
-    },
-    chartData: {
-      type: Array,
-      default: () =>
-        Array.from({ length: 7 }, () => Math.floor(Math.random() * 100)),
-    },
-    numberCard: {
-      type: String,
-      default: () => Math.floor(Math.random() * 100),
-    },
-    numberPorcent: {
-      type: Number,
-      default: null,
-    },
-  });
-</script>
-<style lang="scss" scoped>
-@use "sass:map";
-@use "src/css/quasar.variables.scss";
-
-body.body--light {
-  .background {
-    background: rgba(map.get($colors, "primary"), 0.2) !important;
-  }
-}
-
-body.body--dark {
-  .background {
-    background: rgba(map.get($colors-dark, "primary"), 0.2) !important;
-  }
-}
-
-.mini-card {
-  height: 100%;
-  min-width: 305px;
-  border-radius: 8px;
-  box-shadow: 0 0 0 1px #c0c0c0c0 !important;
-}
-</style>

+ 0 - 285
src/components/charts/custom/NPSChart.vue

@@ -1,285 +0,0 @@
-<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
-<template>
-  <q-card v-bind="$attrs" class="q-px-md">
-    <q-card-section class="row justify-between">
-      <div>
-        <div class="text-h6">{{ props.title }}</div>
-        <span>{{ props.subTitle }}</span>
-      </div>
-      <q-btn
-        icon="mdi-tray-arrow-down"
-        dense
-        flat
-        class="q-my-auto"
-        @click="downloadImage"
-      />
-    </q-card-section>
-    <q-separator dark inset />
-    <div class="graph-container">
-      <div class="column">
-        <div class="col-4 row">
-          <div
-            class="bg-nps-green"
-            style="width: 1rem; min-height: max-content"
-          />
-          <div class="column q-pa-md">
-            <span class="text-bold text-h6 text-nps-green">
-              {{ $t("charts.nps.promotion_zone") }}
-            </span>
-            <span>{{ $t("charts.nps.promotion_zone_range") }}</span>
-          </div>
-        </div>
-        <div class="col-4 row">
-          <div
-            class="bg-nps-green-light"
-            style="width: 1rem; min-height: max-content"
-          />
-          <div class="column q-pa-md">
-            <span class="text-bold text-h6 text-nps-green-light">
-              {{ $t("charts.nps.quality_zone") }}
-            </span>
-            <span>{{ $t("charts.nps.quality_zone_range") }}</span>
-          </div>
-        </div>
-        <div class="col-4 row">
-          <div
-            class="bg-nps-yellow"
-            style="width: 1rem; min-height: max-content"
-          />
-          <div class="column q-pa-md">
-            <span class="text-bold text-h6 text-nps-yellow">
-              {{ $t("charts.nps.refinement_zone") }}
-            </span>
-            <span>{{ $t("charts.nps.refinement_zone_range") }}</span>
-          </div>
-        </div>
-        <div class="col-4 row">
-          <div
-            class="bg-nps-red"
-            style="width: 1rem; min-height: max-content"
-          />
-          <div class="column q-pa-md">
-            <span class="text-bold text-h6 text-nps-red">
-              {{ $t("charts.nps.critical_zone") }}</span
-            >
-            <span>{{ $t("charts.nps.critical_zone_range") }}</span>
-          </div>
-        </div>
-      </div>
-
-      <div style="display: flex; flex-direction: column; align-items: center">
-        <div style="max-height: 500px">
-          <Doughnut
-            ref="chart_ref"
-            :options="chartOptions"
-            :data="chartData"
-            :plugins="[ChartDataLabels, gaugeNeedle]"
-          />
-        </div>
-        <span>{{ titulo }}</span>
-      </div>
-
-      <div class="column q-col-gutter-md">
-        <div class="column">
-          <span>
-            {{ $t("charts.nps.promoters") }} -
-            {{ ((data.promotores / data.total) * 100).toFixed(0) }} %
-          </span>
-          <q-linear-progress
-            :value="data.promotores / data.total"
-            rounded
-            size="20px"
-            color="nps-green"
-            style="min-width: 200px"
-          />
-        </div>
-        <div class="column">
-          <span
-            >{{ $t("charts.nps.passives") }} -
-            {{ ((data.neutros / data.total) * 100).toFixed(0) }} %</span
-          >
-          <q-linear-progress
-            :value="data.neutros / data.total"
-            rounded
-            size="20px"
-            color="nps-yellow"
-            style="min-width: 200px"
-          />
-        </div>
-        <div class="column">
-          <span
-            >{{ $t("charts.nps.detractors") }} -
-            {{ ((data.detratores / data.total) * 100).toFixed(0) }} %</span
-          >
-          <q-linear-progress
-            :value="data.detratores / data.total"
-            rounded
-            size="20px"
-            color="nps-red"
-            style="min-width: 200px"
-          />
-        </div>
-      </div>
-    </div>
-  </q-card>
-</template>
-
-<script setup>
-import { ref } from "vue";
-import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
-import { Doughnut } from "vue-chartjs";
-import ChartDataLabels from "chartjs-plugin-datalabels";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-
-const props = defineProps({
-  title: {
-    type: String,
-    required: true,
-  },
-  value: {
-    type: Number,
-    required: true,
-  },
-  subTitle: {
-    type: String,
-    default: null,
-  },
-  data: {
-    type: Object,
-    required: true,
-  },
-});
-
-const chart_ref = ref(null);
-const titulo = ref(`Valor: ${props.data?.nps}`);
-
-const gaugeNeedle = {
-  id: "gaugeNeedle",
-  afterDatasetsDraw(chart) {
-    const { ctx, data } = chart;
-    ctx.save();
-
-    const needleValue = data.datasets[0].needleValue;
-    const xCenter = chart.getDatasetMeta(0).data[0].x;
-    const yCenter = chart.getDatasetMeta(0).data[0].y;
-    const outerRadius = chart.getDatasetMeta(0).data[0].outerRadius - 40;
-    const angle = Math.PI;
-
-    let circumference =
-      (chart.getDatasetMeta(0).data[0].circumference /
-        Math.PI /
-        data.datasets[0].data[0]) *
-      needleValue;
-
-    const needleAngleValue = circumference + 1.5;
-
-    ctx.translate(xCenter, yCenter);
-    ctx.rotate(angle * needleAngleValue);
-
-    // Draw the needle
-    ctx.beginPath();
-    ctx.strokeStyle = "grey";
-    ctx.fillStyle = "grey";
-    ctx.moveTo(0 - 4, 0);
-    ctx.lineTo(0, -outerRadius);
-    ctx.lineTo(0 + 4, 0);
-    ctx.stroke();
-    ctx.fill();
-
-    ctx.beginPath();
-    ctx.arc(0, 0, 8, 0, 2 * Math.PI);
-    ctx.fillStyle = "grey";
-    ctx.fill();
-
-    ctx.restore();
-  },
-};
-
-ChartJS.register(ArcElement, Tooltip, Legend);
-
-const chartData = ref({
-  datasets: [
-    {
-      backgroundColor: ["#d43333", "#ffbe00", "#40c56c", "#0d733e"],
-      data: [100, 50, 25, 25],
-      needleValue: Number(props.data?.nps) + 100,
-      borderColor: "transparent",
-    },
-  ],
-});
-
-const chartOptions = ref({
-  rotation: 270,
-  circumference: 180,
-  cutout: "50%",
-  plugins: {
-    tooltip: {
-      enabled: false,
-    },
-    datalabels: {
-      color: "white",
-      font: {
-        size: 14,
-        weight: "bold",
-      },
-      formatter: (value, ctx) => {
-        let valor = "";
-        switch (ctx.dataIndex) {
-          case 0:
-            valor = "-100 a 0";
-            break;
-          case 1:
-            valor = "0 a 50";
-            break;
-          case 2:
-            valor = "50 a 75";
-            break;
-          case 3:
-            valor = "75 a 100";
-            break;
-          default:
-            valor = "";
-            break;
-        }
-        return valor;
-      },
-    },
-  },
-});
-
-addEventListener("resize", () => {
-  if (chart_ref.value) {
-    chart_ref.value.chart.update();
-  }
-});
-
-const downloadImage = () => {
-  const image = chart_ref.value.chart?.toBase64Image("image/jpeg", 1);
-  base64ToJPEG(image, props.title);
-};
-</script>
-
-<style scoped>
-.graph-container {
-  display: grid;
-  grid-template-columns: 1fr 1fr 1fr;
-  align-items: center;
-  justify-content: space-around;
-  gap: 1rem;
-  width: 100%;
-  max-width: 100vw;
-  padding: 1rem;
-}
-
-@media screen and (max-width: 1024px) {
-  .graph-container {
-    grid-template-columns: 1fr 1fr;
-  }
-}
-
-@media screen and (max-width: 768px) {
-  .graph-container {
-    grid-template-columns: 1fr;
-  }
-}
-</style>

+ 0 - 201
src/components/charts/custom/SpeedometerChart.vue

@@ -1,201 +0,0 @@
-<template>
-  <q-card v-bind="$attrs" class="q-px-md full-height column justify-between">
-    <q-card-section class="q-pa-none">
-      <div class="row justify-between no-wrap items-start q-py-md q-px-sm">
-        <div>
-          <div class="text-bold text-description q-mb-sm">
-            {{ String(props.title).toLocaleUpperCase() }}
-          </div>
-          <span>{{ props.subTitle }}</span>
-        </div>
-        <q-btn
-          icon="mdi-tray-arrow-down"
-          class="q-ml-md"
-          dense
-          flat
-          @click="downloadImage"
-        />
-      </div>
-      <q-separator dark />
-    </q-card-section>
-    <div class="graph-container">
-      <Doughnut
-        ref="chart_ref"
-        :options="chartOptions"
-        :data="chartData"
-        :plugins="[ChartDataLabels, gaugeNeedle]"
-      />
-    </div>
-  </q-card>
-</template>
-
-<script setup>
-import { ref } from "vue";
-import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
-import { Doughnut } from "vue-chartjs";
-import ChartDataLabels from "chartjs-plugin-datalabels";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-
-const props = defineProps({
-  title: {
-    type: String,
-    required: true,
-  },
-  valorAgulha: {
-    type: Number,
-    required: true,
-  },
-  subTitle: {
-    type: String,
-    default: null,
-  },
-});
-
-const chart_ref = ref(null);
-const titulo = ref(`Valor: ${props.valorAgulha}`);
-
-const gaugeNeedle = {
-  id: "gaugeNeedle",
-  afterDatasetsDraw(chart) {
-    const { ctx, data } = chart;
-    ctx.save();
-
-    const needleValue = data.datasets[0].needleValue;
-    const xCenter = chart.getDatasetMeta(0).data[0].x;
-    const yCenter = chart.getDatasetMeta(0).data[0].y;
-    const outerRadius = chart.getDatasetMeta(0).data[0].outerRadius - 40;
-    const angle = Math.PI;
-
-    let circumference =
-      (chart.getDatasetMeta(0).data[0].circumference /
-        Math.PI /
-        data.datasets[0].data[0]) *
-      needleValue;
-
-    const needleAngleValue = circumference + 1.5;
-
-    ctx.translate(xCenter, yCenter);
-    ctx.rotate(angle * needleAngleValue);
-
-    // Draw the needle
-    ctx.beginPath();
-    ctx.strokeStyle = "grey";
-    ctx.fillStyle = "grey";
-    ctx.moveTo(0 - 4, 0);
-    ctx.lineTo(0, -outerRadius);
-    ctx.lineTo(0 + 4, 0);
-    ctx.stroke();
-    ctx.fill();
-
-    ctx.beginPath();
-    ctx.arc(0, 0, 8, 0, 2 * Math.PI);
-    ctx.fillStyle = "grey";
-    ctx.fill();
-
-    ctx.restore();
-  },
-};
-
-ChartJS.register(ArcElement, Tooltip, Legend);
-
-const chartData = ref({
-  datasets: [
-    {
-      backgroundColor: [
-        "#00a550",
-        "#4dbb7e",
-        "#9ad2ad",
-        "#cce156",
-        "#fff100",
-        "#ffbe00",
-        "#ff8c00",
-        "#FC3D23",
-        "#D01616",
-        "#8A0000",
-      ],
-      data: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
-      needleValue: props.valorAgulha,
-      borderColor: "transparent",
-    },
-  ],
-});
-
-const chartOptions = ref({
-  rotation: 270,
-  circumference: 180,
-  cutout: "50%",
-  plugins: {
-    tooltip: {
-      enabled: false,
-    },
-    title: {
-      display: true,
-      text: titulo.value,
-      color: "#ffffff",
-      position: "bottom",
-    },
-    datalabels: {
-      color: "black",
-      font: {
-        size: 14,
-        weight: "bold",
-      },
-      formatter: (value, ctx) => {
-        const valor = ctx.dataIndex;
-        return valor;
-      },
-    },
-  },
-});
-
-addEventListener("resize", () => {
-  if (chart_ref.value) {
-    chart_ref.value.chart.update();
-  }
-});
-
-const downloadImage = () => {
-  const image = chart_ref.value.chart?.toBase64Image("image/jpeg", 1);
-  base64ToJPEG(image, props.title);
-};
-</script>
-
-<style scoped>
-.graph-container {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 100%;
-  max-height: 300px;
-}
-
-@media screen and (max-width: 1600px) {
-  .graph-container {
-    max-height: 250px;
-  }
-}
-
-@media screen and (max-width: 1360px) {
-  .graph-container {
-    max-height: 200px;
-  }
-}
-
-@media screen and (max-width: 1130px) {
-  .graph-container {
-    max-height: 175px;
-  }
-}
-
-@media screen and (max-width: 888px) {
-  .graph-container {
-    max-height: 250px;
-  }
-}
-
-@media screen and (max-width: 650px) {
-  .graph-container {
-    max-height: 300px;
-  }
-}
-</style>

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 41
src/components/charts/maps/Brasil/DadosBrasil.js


+ 0 - 228
src/components/charts/maps/Brasil/MapaBrasil.vue

@@ -1,228 +0,0 @@
-<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
-<template>
-  <div>
-    <q-card style="height: 100%">
-      <q-card-section class="row justify-between">
-        <div class="column">
-          <span class="text-bold text-description q-mb-sm">
-            {{ props.title }}
-          </span>
-          <span>{{ props.subtitle }}</span>
-        </div>
-        <q-btn
-          icon="mdi-tray-arrow-down"
-          dense
-          flat
-          class="q-my-auto"
-          @click="downloadImage"
-        />
-      </q-card-section>
-
-      <q-separator inset />
-      <q-card-section>
-        <div style="display: flex; flex-direction: column">
-          <div @mouseover="hideInfoBox">
-            <svg
-              ref="ref_mapa"
-              xmlns="http://www.w3.org/2000/svg"
-              class="mapa-svg-estados"
-              viewBox="120 50 500 500"
-              @click="mapclick"
-            >
-              <g id="mapa-svg-area">
-                <MapaEstado
-                  v-for="item in items"
-                  ref="child"
-                  :key="item.uf"
-                  :item="item"
-                  :show-circle-info="showCircleInfo"
-                  :class="item.classObject"
-                  :style="item.color ? `fill: ${item.color}` : ''"
-                  @state-selected-event="onStateSelectedEvent"
-                  @state-mouse-over-event="onStateMouseOverEvent"
-                />
-              </g>
-            </svg>
-          </div>
-          <div class="bg-background--2 q-pa-md" style="border-radius: 0.5rem">
-            <div
-              v-if="selected"
-              style="display: flex; flex-direction: column; gap: 0.5rem"
-            >
-              <span>
-                <b> Estado:</b> {{ dadosEstado.name }} -
-                {{ dadosEstado.uf.toUpperCase() }}
-              </span>
-              <span><b>Participantes:</b> {{ dadosEstado.pessoas || 0 }}</span>
-            </div>
-            <div
-              v-else
-              style="display: flex; flex-direction: column; gap: 0.5rem"
-            >
-              <span>
-                <b>Selecione um estado</b>
-              </span>
-            </div>
-          </div>
-        </div>
-      </q-card-section>
-    </q-card>
-  </div>
-</template>
-
-<script setup>
-import { computed, onMounted, ref } from "vue";
-import MapaEstado from "../MapaEstado.vue";
-import { DadosBrasil } from "./DadosBrasil";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-
-const selected = ref(null);
-const showCircleInfo = ref(false);
-const infoBoxActive = ref(false);
-const infoBoxPosX = ref(0);
-const infoBoxPosY = ref(0);
-const infoBoxData = ref("");
-const child = ref(null);
-const items = ref(DadosBrasil);
-const ref_mapa = ref(null);
-
-const props = defineProps({
-  data: {
-    type: Array,
-    required: true,
-  },
-  title: {
-    type: String,
-    required: false,
-    default: "PARTICIPANTES POR ESTADO - BRASIL",
-  },
-  subtitle: {
-    type: String,
-    required: false,
-    default: "Número de participantes do evento por estado brasileiro",
-  },
-});
-
-const mapclick = (event) => {
-  // console.log("mapa-brasil: mapclick");
-  if (event.target.tagName == "svg") {
-    resetSelectionAction();
-    infoBoxActive.value = false;
-  }
-};
-const onStateSelectedEvent = (args) => {
-  // console.log("mapa-brasil: onStateSelectedEvent: ", args);
-  selected.value = args.src.item.uf;
-  resetSelectionAction();
-  args.enable();
-};
-const onStateMouseOverEvent = (args) => {
-  // console.log("mapa-brasil: onStateMouseOverEvent: ", args);
-  setInfoBoxPosition({ x: args.event.pageX, y: args.event.pageY });
-  setInfoBoxData([
-    args.src.item.name,
-    args.src.item.regional,
-    args.src.item.altText,
-  ]);
-  infoBoxActive.value = true;
-};
-const resetSelectionAction = () => {
-  // console.log("mapa-brasil: resetSelectionAction", child.value);
-  for (let index = 0; index < child.value.length; index++) {
-    child.value[index].resetAction();
-  }
-};
-const setInfoBoxPosition = (args) => {
-  infoBoxPosX.value = args.x + 30;
-  infoBoxPosY.value = args.y;
-};
-const setInfoBoxData = (args) => {
-  infoBoxData.value = args.filter(function (a) {
-    return a !== "" ? a : null;
-  });
-};
-const hideInfoBox = (args) => {
-  if (
-    ["DIV", "SVG"].indexOf(args.target.tagName.toString().toUpperCase()) > -1
-  ) {
-    infoBoxActive.value = false;
-  }
-};
-
-onMounted(() => {
-  const dataOrganizada = [...props.data].sort(
-    (a, b) => a?.total_pessoas_por_estado - b?.total_pessoas_por_estado
-  );
-  const maiorNumero =
-    dataOrganizada[dataOrganizada.length - 1]?.total_pessoas_por_estado;
-  const faixa = maiorNumero / 5;
-  const colors = ["#f6a0a1", "#f27e7f", "#ee585a", "#EB3537", "#c31315"];
-  items.value.forEach((item) => {
-    const estado = dataOrganizada.find((e) => e.estado === item.uf);
-    if (estado) {
-      const indexFaixa = Math.ceil(estado?.total_pessoas_por_estado / faixa);
-      item.color = colors[indexFaixa - 1];
-      item.pessoas = estado.total_pessoas_por_estado;
-    } else {
-      item.color = "#494949";
-      item.pessoas = 0;
-    }
-  });
-});
-
-const dadosEstado = computed(() => {
-  const estado = items.value.find((item) => item.uf === selected.value);
-  return estado;
-});
-
-const downloadImage = () => {
-  const svgString = new XMLSerializer().serializeToString(ref_mapa.value);
-  const base64String = btoa(svgString);
-  base64ToJPEG(base64String, props.title);
-};
-</script>
-
-<style lang="scss">
-svg text {
-  fill: var(--default-stroke);
-  font-family: monospace;
-}
-
-.mapa-svg-estados {
-  fill: var(--default-fill);
-  -webkit-transition: 0.8s ease;
-  -moz-transition: 0.8s ease;
-  -ms-transition: 0.8s ease;
-  -o-transition: 0.8s ease;
-  transition: 0.8s ease;
-  stroke-dasharray: 180%;
-  stroke-dashoffset: -120%;
-  stroke-width: 1px;
-  stroke: var(--default-stroke);
-  text {
-    fill: var(--default-stroke);
-    stroke: none !important;
-  }
-}
-
-.mapa-svg-estados:hover {
-  cursor: pointer;
-  fill: #8d1012 !important;
-}
-
-.mapa-svg-estados-active {
-  cursor: pointer;
-  stroke: #ffffff;
-  fill: #ffc712 !important;
-  stroke-dashoffset: 0%;
-  transition: 0.8s ease;
-  -webkit-transition: 0.8s ease;
-  -moz-transition: 0.8s ease;
-  -ms-transition: 0.8s ease;
-  -o-transition: 0.8s ease;
-  text {
-    fill: #ffffff;
-    stroke: none !important;
-  }
-}
-</style>

+ 0 - 110
src/components/charts/maps/MapaEstado.vue

@@ -1,110 +0,0 @@
-<template>
-  <g
-    ref="chart_ref"
-    :class="[classObject]"
-    :data-regional="item.regional"
-    @click="clickAction"
-  >
-    <path :d="item.svgData" />
-    <text
-      :transform="item.textData"
-      class="item text-weight-medium"
-      style="font-size: 10px"
-      fill="white"
-    >
-      {{ item.pessoas || 0 }}
-    </text>
-    <circle
-      v-if="showCircleInfo"
-      :cy="item.circleData.cy"
-      :cx="item.circleData.cx"
-      r="10"
-      :class="[counterClassObject]"
-    />
-  </g>
-</template>
-
-<script setup>
-import { computed, onMounted, ref } from "vue";
-
-const props = defineProps({
-  item: {
-    type: Object,
-    default: () => ({
-      altText: "--",
-    }),
-  },
-  showCircleInfo: {
-    type: Boolean,
-    default: true,
-  },
-});
-
-const emit = defineEmits(["stateSelectedEvent", "stateMouseOverEvent"]);
-
-const active = ref(false);
-const counterActive = ref(false);
-const altText = ref(props.item.altText || "-");
-const chart_ref = ref(null);
-
-const classObject = computed(() => {
-  return active.value ? ["mapa-svg-estados-active"] : ["mapa-svg-estados"];
-});
-
-const counterClassObject = computed(() => {
-  return counterActive.value ? ["sphere active"] : ["sphere"];
-});
-
-// const pad = (value) => {
-//   if (!value) return "";
-//   return ("000000000" + value).slice(-2);
-// };
-
-const clickAction = () => {
-  // console.log("mapa-estado: clickAction()");
-  emit("stateSelectedEvent", {
-    src: {
-      item: props.item,
-    },
-    enable,
-  });
-};
-const resetAction = () => {
-  disable();
-};
-const disable = () => {
-  // console.log("mapa-estado: disabled ", props.item.uf);
-  active.value = false;
-  hideCounter();
-};
-
-const enable = () => {
-  // console.log("mapa-estado: enable ");
-  active.value = true;
-  showCounter();
-};
-const setAltText = (val) => {
-  altText.value = val;
-};
-const hideCounter = () => {
-  counterActive.value = false;
-};
-const showCounter = () => {
-  counterActive.value = true;
-};
-
-onMounted(() => {
-  altText.value = props.item.altText;
-});
-
-defineExpose({
-  resetAction,
-  setAltText,
-});
-</script>
-
-<style>
-.item {
-  fill: rgb(240, 221, 221);
-}
-</style>

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 14
src/components/charts/maps/Paraguai/DadosParaguai.js


+ 0 - 225
src/components/charts/maps/Paraguai/MapaParaguai.vue

@@ -1,225 +0,0 @@
-<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
-<template>
-  <div>
-    <q-card style="height: 100%">
-      <q-card-section class="row justify-between">
-        <div class="column">
-          <span class="text-bold text-description q-mb-sm">
-            {{ props.title }}
-          </span>
-          <span>{{ props.subtitle }}</span>
-        </div>
-        <q-btn
-          icon="mdi-tray-arrow-down"
-          dense
-          flat
-          class="q-my-auto"
-          @click="downloadImage"
-        />
-      </q-card-section>
-
-      <q-separator inset />
-      <q-card-section>
-        <div style="display: flex; flex-direction: column">
-          <div @mouseover="hideInfoBox">
-            <svg
-              ref="ref_mapa"
-              xmlns="http://www.w3.org/2000/svg"
-              class="mapa-svg-estados"
-              viewBox="-100 -60 1250 1250"
-              @click="mapclick"
-            >
-              <g id="mapa-svg-area">
-                <MapaEstado
-                  v-for="item in items"
-                  ref="child"
-                  :key="item.id"
-                  :item="item"
-                  :show-circle-info="showCircleInfo"
-                  :class="item.classObject"
-                  :style="item.color ? `fill: ${item.color}` : ''"
-                  @state-selected-event="onStateSelectedEvent"
-                  @state-mouse-over-event="onStateMouseOverEvent"
-                ></MapaEstado>
-              </g>
-            </svg>
-          </div>
-          <div class="bg-background--2 q-pa-md" style="border-radius: 0.5rem">
-            <div
-              v-if="selected"
-              style="display: flex; flex-direction: column; gap: 0.5rem"
-            >
-              <span> <b> Estado:</b> {{ dadosEstado.name }} </span>
-              <span><b>Participantes:</b> {{ dadosEstado.pessoas || 0 }}</span>
-            </div>
-            <div
-              v-else
-              style="display: flex; flex-direction: column; gap: 0.5rem"
-            >
-              <span>
-                <b>Selecione um estado</b>
-              </span>
-            </div>
-          </div>
-        </div>
-      </q-card-section>
-    </q-card>
-  </div>
-</template>
-
-<script setup>
-import { computed, onMounted, ref } from "vue";
-import MapaEstado from "../MapaEstado.vue";
-import { DadosParaguai } from "./DadosParaguai";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-
-const selected = ref(null);
-const showCircleInfo = ref(false);
-const infoBoxActive = ref(false);
-const infoBoxPosX = ref(0);
-const infoBoxPosY = ref(0);
-const infoBoxData = ref("");
-const child = ref(null);
-const items = ref(DadosParaguai);
-const ref_mapa = ref(null);
-
-const props = defineProps({
-  data: {
-    type: Array,
-    required: true,
-  },
-  title: {
-    type: String,
-    required: false,
-    default: "PARTICIPANTES POR DEPARTAMENTO - PARAGUAI",
-  },
-  subtitle: {
-    type: String,
-    required: false,
-    default: "Número de participantes do evento por departamento do Paraguai",
-  },
-});
-
-const mapclick = (event) => {
-  // console.log("mapa-brasil: mapclick");
-  if (event.target.tagName == "svg") {
-    resetSelectionAction();
-    infoBoxActive.value = false;
-  }
-};
-const onStateSelectedEvent = (args) => {
-  // console.log("mapa-brasil: onStateSelectedEvent: ", args);
-  selected.value = args.src.item.id;
-  resetSelectionAction();
-  args.enable();
-};
-const onStateMouseOverEvent = (args) => {
-  // console.log("mapa-brasil: onStateMouseOverEvent: ", args);
-  setInfoBoxPosition({ x: args.event.pageX, y: args.event.pageY });
-  setInfoBoxData([
-    args.src.item.name,
-    args.src.item.regional,
-    args.src.item.altText,
-  ]);
-  infoBoxActive.value = true;
-};
-const resetSelectionAction = () => {
-  // console.log("mapa-brasil: resetSelectionAction", child.value);
-  for (let index = 0; index < child.value.length; index++) {
-    child.value[index].resetAction();
-  }
-};
-const setInfoBoxPosition = (args) => {
-  infoBoxPosX.value = args.x + 30;
-  infoBoxPosY.value = args.y;
-};
-const setInfoBoxData = (args) => {
-  infoBoxData.value = args.filter(function (a) {
-    return a !== "" ? a : null;
-  });
-};
-const hideInfoBox = (args) => {
-  if (
-    ["DIV", "SVG"].indexOf(args.target.tagName.toString().toUpperCase()) > -1
-  ) {
-    infoBoxActive.value = false;
-  }
-};
-
-onMounted(() => {
-  const dataOrganizada = [...props.data].sort(
-    (a, b) => a?.total_pessoas_por_estado - b?.total_pessoas_por_estado
-  );
-  const maiorNumero =
-    dataOrganizada[dataOrganizada.length - 1]?.total_pessoas_por_estado;
-  const faixa = maiorNumero / 5;
-  const colors = ["#f6a0a1", "#f27e7f", "#ee585a", "#EB3537", "#c31315"];
-  items.value.forEach((item) => {
-    const estado = dataOrganizada.find((e) => e.estado_id === item.id);
-    if (estado) {
-      const indexFaixa = Math.ceil(estado?.total_pessoas_por_estado / faixa);
-      item.color = colors[indexFaixa - 1];
-      item.pessoas = estado.total_pessoas_por_estado;
-    } else {
-      item.color = "#494949";
-      item.pessoas = 0;
-    }
-  });
-});
-
-const dadosEstado = computed(() => {
-  const estado = items.value.find((item) => item.id === selected.value);
-  return estado;
-});
-
-const downloadImage = () => {
-  const svgString = new XMLSerializer().serializeToString(ref_mapa.value);
-  const base64String = btoa(svgString);
-  base64ToJPEG(base64String, props.title);
-};
-</script>
-
-<style lang="scss">
-svg text {
-  fill: var(--default-stroke);
-  font-family: monospace;
-}
-
-.mapa-svg-estados {
-  fill: var(--default-fill);
-  -webkit-transition: 0.8s ease;
-  -moz-transition: 0.8s ease;
-  -ms-transition: 0.8s ease;
-  -o-transition: 0.8s ease;
-  transition: 0.8s ease;
-  stroke-dasharray: 180%;
-  stroke-dashoffset: -120%;
-  stroke-width: 1px;
-  stroke: var(--default-stroke);
-  text {
-    fill: var(--default-stroke);
-    stroke: none !important;
-  }
-}
-
-.mapa-svg-estados:hover {
-  cursor: pointer;
-  fill: #8d1012 !important;
-}
-
-.mapa-svg-estados-active {
-  cursor: pointer;
-  stroke: #ffffff;
-  fill: #ffc712 !important;
-  stroke-dashoffset: 0%;
-  transition: 0.8s ease;
-  -webkit-transition: 0.8s ease;
-  -moz-transition: 0.8s ease;
-  -ms-transition: 0.8s ease;
-  -o-transition: 0.8s ease;
-  text {
-    fill: #ffffff;
-    stroke: none !important;
-  }
-}
-</style>

+ 0 - 101
src/components/charts/mini/MiniBarChart.vue

@@ -1,101 +0,0 @@
-<template>
-  <Bar
-    :id="id"
-    ref="chart_ref"
-    :options="chartOptions"
-    :data="computedChartData"
-  />
-</template>
-
-<script setup>
-import {
-  Chart as ChartJS,
-  CategoryScale,
-  LinearScale,
-  BarElement,
-  Tooltip,
-} from "chart.js";
-import { computed, useTemplateRef } from "vue";
-import { Bar } from "vue-chartjs";
-import { getCssVar } from "quasar";
-
-ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip);
-
-const chart_ref = useTemplateRef(null);
-
-const { data, barColor, horizontal, showTooltip } = defineProps({
-  data: {
-    type: Array,
-    required: true,
-  },
-  barColor: {
-    type: String,
-    default: () => getCssVar("primary"),
-  },
-  horizontal: {
-    type: Boolean,
-    default: false,
-  },
-  showTooltip: {
-    type: Boolean,
-    default: true,
-  },
-});
-
-const chartOptions = computed(() => ({
-  responsive: true,
-  maintainAspectRatio: false,
-  indexAxis: horizontal ? "y" : "x",
-
-  plugins: {
-    legend: {
-      display: false,
-    },
-    tooltip: {
-      enabled: showTooltip,
-      displayColors: false,
-      callbacks: {
-        label: (context) => `${context.raw}`,
-      },
-    },
-  },
-
-  scales: {
-    x: {
-      display: false,
-      grid: {
-        display: false,
-      },
-    },
-    y: {
-      display: false,
-      grid: {
-        display: false,
-      },
-      beginAtZero: true,
-    },
-  },
-
-  animation: {
-    duration: 750,
-    easing: "easeOutQuad",
-  },
-}));
-
-const computedChartData = computed(() => ({
-  labels: Array(data.length).fill(""),
-  datasets: [
-    {
-      data: data,
-      backgroundColor: barColor,
-      borderRadius: 2,
-      barThickness: 8,
-      maxBarThickness: 10,
-    },
-  ],
-}));
-
-defineExpose({
-  chart_ref,
-});
-</script>

+ 0 - 116
src/components/charts/mini/MiniLineChart.vue

@@ -1,116 +0,0 @@
-<template>
-  <Line ref="chart_ref" :options="chartOptions" :data="computedChartData" />
-</template>
-
-<script setup>
-import {
-  Chart as ChartJS,
-  CategoryScale,
-  LinearScale,
-  LineElement,
-  PointElement,
-  Tooltip,
-  Filler,
-} from "chart.js";
-import { computed, useTemplateRef } from "vue";
-import { Line } from "vue-chartjs";
-import { getCssVar } from "quasar";
-
-ChartJS.register(
-  CategoryScale,
-  LinearScale,
-  LineElement,
-  PointElement,
-  Tooltip,
-  Filler,
-);
-
-const chart_ref = useTemplateRef(null);
-
-const { data, lineColor, fillColor, showTooltip, showPoints } = defineProps({
-  data: {
-    type: Array,
-    required: true,
-  },
-  lineColor: {
-    type: String,
-    default: () => getCssVar("primary"),
-  },
-  fillColor: {
-    type: String,
-    default: "rgba(25, 118, 210, 0.1)",
-  },
-  showTooltip: {
-    type: Boolean,
-    default: true,
-  },
-  showPoints: {
-    type: Boolean,
-    default: false,
-  },
-});
-
-const chartOptions = computed(() => ({
-  responsive: true,
-  maintainAspectRatio: false,
-
-  plugins: {
-    legend: {
-      display: false,
-    },
-    tooltip: {
-      enabled: showTooltip,
-      displayColors: false,
-      callbacks: {
-        label: (context) => `${context.raw}`,
-      },
-    },
-  },
-
-  scales: {
-    x: {
-      display: false,
-      grid: { display: false },
-    },
-    y: {
-      display: false,
-      grid: { display: false },
-      beginAtZero: true,
-    },
-  },
-
-  elements: {
-    line: {
-      tension: 0.4,
-      borderWidth: 2,
-    },
-    point: {
-      radius: showPoints ? 3 : 0,
-      hitRadius: 5,
-      borderWidth: 0,
-      backgroundColor: showPoints ? lineColor : "rgba(0,0,0,0)",
-    },
-  },
-
-  animation: {
-    duration: 750,
-    easing: "easeOutQuad",
-  },
-}));
-
-const computedChartData = computed(() => ({
-  labels: Array(data?.length)?.fill(""),
-  datasets: [
-    {
-      data: data,
-      borderColor: lineColor,
-      backgroundColor: fillColor,
-      fill: true,
-    },
-  ],
-}));
-
-defineExpose({
-  chart_ref,
-});
-</script>

+ 0 - 267
src/components/charts/normal/BarChart.vue

@@ -1,267 +0,0 @@
-<template>
-  <div v-bind="$attrs" class="chart-wrapper full-width full-height">
-    <q-resize-observer @resize="onResize" />
-    <div v-if="hasData" class="chart-container">
-      <Bar
-        ref="chart_ref"
-        :options="chartBarOptions"
-        :data="chartBarData"
-        :plugins="[ChartDataLabels]"
-      />
-    </div>
-    <div v-else class="no-data-container">
-      <span :class="textColor">{{ $t("http.errors.no_records_found") }}</span>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ref, computed } from "vue";
-import { Bar } from "vue-chartjs";
-import {
-  Chart as ChartJS,
-  Title,
-  Tooltip,
-  Legend,
-  BarElement,
-  CategoryScale,
-  LinearScale,
-} from "chart.js";
-import ChartDataLabels from "chartjs-plugin-datalabels";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-import { useQuasar, colors, getCssVar } from "quasar";
-
-ChartJS.register(
-  Title,
-  Tooltip,
-  Legend,
-  BarElement,
-  CategoryScale,
-  LinearScale,
-);
-
-const $q = useQuasar();
-const chart_ref = ref(null);
-const { lighten } = colors;
-
-const props = defineProps({
-  data: {
-    type: Object,
-    default: () => ({
-      chart_data: [],
-      current_total: 0,
-    }),
-  },
-  dataSetLabel: {
-    type: String,
-    default: "Quantidade",
-  },
-  labelX: {
-    type: String,
-    default: "Categorias",
-  },
-  labelY: {
-    type: String,
-    default: "Valores",
-  },
-  showLegend: {
-    type: Boolean,
-    default: false,
-  },
-  title: {
-    type: String,
-    default: "Título",
-  },
-  backgroundColors: {
-    type: Array,
-    default: null,
-  },
-});
-
-const onResize = () => {
-  if (chart_ref.value?.chart) {
-    setTimeout(() => {
-      chart_ref.value.chart.resize();
-    }, 50);
-  }
-};
-
-const textColor = computed(() => {
-  return $q.dark.isActive ? "text-white" : "text-black";
-});
-
-const labelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const gridColor = computed(() => {
-  return $q.dark.isActive ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.1)";
-});
-
-const dataLabelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const hasData = computed(() => {
-  return props.data?.chart_data && props.data.chart_data.length > 0;
-});
-
-const chartLabels = computed(() => {
-  return props.data?.chart_data?.map((item) => item.label) || [];
-});
-
-const chartValues = computed(() => {
-  return props.data?.chart_data?.map((item) => item.value) || [];
-});
-
-const chartThemeColors = computed(() => {
-  if (props.backgroundColors) {
-    return props.backgroundColors;
-  }
-
-  const primaryColor = getCssVar("primary");
-  if (!primaryColor) return [];
-
-  const numColors = chartValues.value.length;
-  const step = numColors > 0 ? 50 / numColors : 0;
-  return Array.from({ length: numColors }, (_, i) =>
-    lighten(primaryColor, i * step),
-  );
-});
-
-const chartBarData = computed(() => ({
-  labels: chartLabels.value,
-  datasets: [
-    {
-      label: props.dataSetLabel,
-      data: chartValues.value,
-      backgroundColor: chartThemeColors.value,
-      borderColor: chartThemeColors.value,
-      borderWidth: 1,
-    },
-  ],
-}));
-
-const chartBarOptions = computed(() => ({
-  responsive: true,
-  maintainAspectRatio: false,
-  plugins: {
-    legend: {
-      display: props.showLegend,
-      position: "top",
-      labels: {
-        color: labelColor.value,
-        font: {
-          size: 14,
-        },
-      },
-    },
-    datalabels: {
-      color: dataLabelColor.value,
-      anchor: "end",
-      align: "top",
-      offset: 4,
-      font: {
-        size: 12,
-        weight: "bold",
-      },
-      formatter: (value) => {
-        return value > 0 ? value : "";
-      },
-    },
-    tooltip: {
-      backgroundColor: $q.dark.isActive
-        ? "rgba(0, 0, 0, 0.8)"
-        : "rgba(255, 255, 255, 0.9)",
-      titleColor: labelColor.value,
-      bodyColor: labelColor.value,
-      borderColor: labelColor.value,
-      borderWidth: 1,
-    },
-  },
-  scales: {
-    x: {
-      display: true,
-      title: {
-        display: !!props.labelX,
-        text: props.labelX,
-        color: labelColor.value,
-        font: {
-          size: 14,
-        },
-      },
-      grid: {
-        color: gridColor.value,
-        tickColor: gridColor.value,
-      },
-      ticks: {
-        color: labelColor.value,
-        font: {
-          size: 12,
-        },
-      },
-    },
-    y: {
-      display: true,
-      title: {
-        display: !!props.labelY,
-        text: props.labelY,
-        color: labelColor.value,
-        font: {
-          size: 14,
-        },
-      },
-      suggestedMin: 0,
-      grid: {
-        color: gridColor.value,
-        tickColor: gridColor.value,
-      },
-      ticks: {
-        color: labelColor.value,
-        font: {
-          size: 12,
-        },
-        stepSize: 1,
-      },
-    },
-  },
-}));
-
-const downloadImage = () => {
-  const image = chart_ref.value.chart?.toBase64Image("image/jpeg", 1);
-  base64ToJPEG(image, props.title || "bar-chart");
-};
-
-defineExpose({
-  downloadImage,
-  chart_ref,
-});
-</script>
-
-<style scoped>
-.chart-wrapper {
-  position: relative;
-}
-
-.chart-container {
-  position: absolute;
-  top: 10px;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.no-data-container {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  padding: 1.5rem;
-}
-</style>

+ 0 - 204
src/components/charts/normal/DoughnutChart.vue

@@ -1,204 +0,0 @@
-<template>
-  <div v-bind="$attrs" class="chart-wrapper full-width full-height">
-    <q-resize-observer @resize="onResize" />
-    <div v-if="hasData" class="chart-container">
-      <Doughnut
-        ref="chart_ref"
-        :options="chartPieOptions"
-        :data="chartPieData"
-        :plugins="[ChartDataLabels]"
-      />
-    </div>
-    <div v-else class="no-data-container">
-      <span :class="textColor">{{ $t("http.errors.no_records_found") }}</span>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ref, computed } from "vue";
-import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
-import { Doughnut } from "vue-chartjs";
-import ChartDataLabels from "chartjs-plugin-datalabels";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-import { useQuasar, colors, getCssVar } from "quasar";
-
-ChartJS.register(ArcElement, Tooltip, Legend);
-
-const $q = useQuasar();
-const { lighten } = colors;
-
-const props = defineProps({
-  data: {
-    type: Object,
-    default: () => ({
-      chart_data: [],
-    }),
-  },
-  backgroundColors: {
-    type: Array,
-    default: null,
-  },
-  title: {
-    type: String,
-    default: "doughnut-chart",
-  },
-  dataSetLabel: {
-    type: String,
-    default: "Dados",
-  },
-});
-
-const chart_ref = ref(null);
-
-const onResize = () => {
-  if (chart_ref.value?.chart) {
-    setTimeout(() => {
-      chart_ref.value.chart.resize();
-    }, 50);
-  }
-};
-
-const textColor = computed(() => {
-  return $q.dark.isActive ? "text-white" : "text-black";
-});
-
-const labelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const dataLabelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const hasData = computed(() => {
-  return props.data?.chart_data && props.data.chart_data.length > 0;
-});
-
-const chartLabels = computed(() => {
-  return props.data?.chart_data?.map((item) => item.label) || [];
-});
-
-const chartValues = computed(() => {
-  return props.data?.chart_data?.map((item) => item.value) || [];
-});
-
-const chartPercentages = computed(() => {
-  const total = props.data?.current_total || 0;
-  if (total === 0) return [];
-
-  return (
-    props.data?.chart_data?.map((item) =>
-      Math.round((item.value / total) * 100),
-    ) || []
-  );
-});
-
-const chartThemeColors = computed(() => {
-  if (props.backgroundColors) {
-    return props.backgroundColors;
-  }
-
-  const primaryColor = getCssVar("primary");
-  if (!primaryColor) return [];
-
-  const numColors = chartValues.value.length;
-  const step = numColors > 0 ? 50 / numColors : 0;
-  return Array.from({ length: numColors }, (_, i) =>
-    lighten(primaryColor, i * step),
-  );
-});
-
-const chartPieData = computed(() => ({
-  labels: chartLabels.value,
-  datasets: [
-    {
-      label: props.dataSetLabel,
-      data: chartPercentages.value,
-      backgroundColor: chartThemeColors.value,
-    },
-  ],
-}));
-
-const chartPieOptions = computed(() => ({
-  responsive: true,
-  maintainAspectRatio: false,
-  plugins: {
-    legend: {
-      position: "bottom",
-      labels: {
-        color: labelColor.value,
-        font: {
-          size: 12,
-        },
-        padding: 20,
-      },
-    },
-    datalabels: {
-      color: dataLabelColor.value,
-      font: {
-        size: 12,
-        weight: "bold",
-      },
-      formatter: (value) => {
-        return value > 0 ? value + "%" : "";
-      },
-    },
-    tooltip: {
-      backgroundColor: $q.dark.isActive
-        ? "rgba(0, 0, 0, 0.8)"
-        : "rgba(255, 255, 255, 0.9)",
-      titleColor: labelColor.value,
-      bodyColor: labelColor.value,
-      borderColor: labelColor.value,
-      borderWidth: 1,
-      callbacks: {
-        label: (context) => {
-          const label = context.label || "";
-          const percentage = context.parsed;
-          const actualValue = chartValues.value[context.dataIndex];
-          return `${label}: ${actualValue} (${percentage}%)`;
-        },
-      },
-    },
-  },
-}));
-
-const downloadImage = () => {
-  const image = chart_ref.value.chart?.toBase64Image("image/jpeg", 1);
-  base64ToJPEG(image, props.title || "pie-chart");
-};
-
-defineExpose({
-  downloadImage,
-  chart_ref,
-});
-</script>
-
-<style scoped>
-.chart-wrapper {
-  position: relative;
-}
-
-.chart-container {
-  position: absolute;
-  top: 10px;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.no-data-container {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  padding: 1.5rem;
-}
-</style>

+ 0 - 265
src/components/charts/normal/LineChart.vue

@@ -1,265 +0,0 @@
-<template>
-  <div v-bind="$attrs" class="chart-wrapper full-width full-height">
-    <q-resize-observer @resize="onResize" />
-    <div v-if="hasData" class="chart-container">
-      <Line
-        ref="chart_ref"
-        :options="chartLineOptions"
-        :data="chartLineData"
-        :plugins="[ChartDataLabels]"
-      />
-    </div>
-    <div v-else class="no-data-container">
-      <span :class="textColor">{{ $t("http.errors.no_records_found") }}</span>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ref, computed } from "vue";
-import { Line } from "vue-chartjs";
-import {
-  Chart as ChartJS,
-  Title,
-  Tooltip,
-  Legend,
-  LineElement,
-  PointElement,
-  CategoryScale,
-  LinearScale,
-} from "chart.js";
-import ChartDataLabels from "chartjs-plugin-datalabels";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-import { useQuasar, getCssVar, colors } from "quasar";
-
-ChartJS.register(
-  Title,
-  Tooltip,
-  Legend,
-  LineElement,
-  PointElement,
-  CategoryScale,
-  LinearScale,
-);
-
-const $q = useQuasar();
-const { lighten } = colors;
-const chart_ref = ref(null);
-
-const props = defineProps({
-  data: {
-    type: Object,
-    default: () => ({
-      chart_data: [],
-    }),
-  },
-  title: {
-    type: String,
-    default: "",
-  },
-  dataSetLabel: {
-    type: String,
-    default: "Valores",
-  },
-  labelX: {
-    type: String,
-    default: "Categorias",
-  },
-  labelY: {
-    type: String,
-    default: "Valores",
-  },
-  backgroundColors: {
-    type: Array,
-    default: null,
-  },
-});
-
-const onResize = () => {
-  if (chart_ref.value?.chart) {
-    setTimeout(() => {
-      chart_ref.value.chart.resize();
-    }, 50);
-  }
-};
-
-const textColor = computed(() => {
-  return $q.dark.isActive ? "text-white" : "text-black";
-});
-
-const labelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const gridColor = computed(() => {
-  return $q.dark.isActive ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.1)";
-});
-
-const dataLabelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const hasData = computed(() => {
-  return props.data?.chart_data && props.data.chart_data.length > 0;
-});
-
-const chartLabels = computed(() => {
-  return props.data?.chart_data?.map((item) => item.label) || [];
-});
-
-const chartValues = computed(() => {
-  return props.data?.chart_data?.map((item) => item.value) || [];
-});
-
-const chartThemeColors = computed(() => {
-  if (props.backgroundColors) {
-    return props.backgroundColors;
-  }
-
-  const primaryColor = getCssVar("primary");
-  if (!primaryColor) return [];
-
-  const numColors = chartValues.value.length;
-  const step = numColors > 0 ? 50 / numColors : 0;
-  return Array.from({ length: numColors }, (_, i) =>
-    lighten(primaryColor, i * step),
-  );
-});
-
-const chartLineData = computed(() => ({
-  labels: chartLabels.value,
-  datasets: [
-    {
-      label: props.dataSetLabel,
-      data: chartValues.value,
-      borderColor: chartThemeColors.value[0],
-      backgroundColor: chartThemeColors.value,
-      fill: false,
-      cubicInterpolationMode: "monotone",
-      tension: 0.4,
-    },
-  ],
-}));
-
-const chartLineOptions = computed(() => ({
-  responsive: true,
-  maintainAspectRatio: false,
-  plugins: {
-    legend: {
-      display: false,
-    },
-    title: {
-      display: !!props.title,
-      text: props.title,
-      color: labelColor.value,
-      font: {
-        size: 16,
-      },
-    },
-    datalabels: {
-      color: dataLabelColor.value,
-      anchor: "end",
-      align: "top",
-      offset: 4,
-      font: {
-        size: 12,
-        weight: "bold",
-      },
-      formatter: (value) => {
-        return value > 0 ? value : "";
-      },
-    },
-    tooltip: {
-      backgroundColor: $q.dark.isActive
-        ? "rgba(0, 0, 0, 0.8)"
-        : "rgba(255, 255, 255, 0.9)",
-      titleColor: labelColor.value,
-      bodyColor: labelColor.value,
-      borderColor: labelColor.value,
-      borderWidth: 1,
-    },
-  },
-  interaction: {
-    intersect: false,
-  },
-  scales: {
-    x: {
-      display: true,
-      title: {
-        display: !!props.labelX,
-        text: props.labelX,
-        color: labelColor.value,
-        font: {
-          size: 14,
-        },
-      },
-      grid: {
-        color: gridColor.value,
-        tickColor: gridColor.value,
-      },
-      ticks: {
-        color: labelColor.value,
-      },
-    },
-    y: {
-      display: true,
-      title: {
-        display: !!props.labelY,
-        text: props.labelY,
-        color: labelColor.value,
-        font: {
-          size: 14,
-        },
-      },
-      suggestedMin: 0,
-      grid: {
-        color: gridColor.value,
-        tickColor: gridColor.value,
-      },
-      ticks: {
-        color: labelColor.value,
-        stepSize: 1,
-      },
-    },
-  },
-}));
-
-const downloadImage = () => {
-  if (!chart_ref.value?.chart) return;
-  const image = chart_ref.value.chart.toBase64Image("image/jpeg", 1);
-  base64ToJPEG(image, props.title || "line-chart");
-};
-
-defineExpose({
-  downloadImage,
-  chart_ref,
-});
-</script>
-
-<style scoped>
-.chart-wrapper {
-  position: relative;
-}
-
-.chart-container {
-  position: absolute;
-  top: 10px;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.no-data-container {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  padding: 1.5rem;
-}
-</style>

+ 0 - 205
src/components/charts/normal/PieChart.vue

@@ -1,205 +0,0 @@
-<template>
-  <div v-bind="$attrs" class="chart-wrapper full-width full-height">
-    <q-resize-observer @resize="onResize" />
-    <div v-if="hasData" class="chart-container">
-      <Pie
-        ref="chart_ref"
-        :options="chartPieOptions"
-        :data="chartPieData"
-        :plugins="[ChartDataLabels]"
-      />
-    </div>
-    <div v-else class="no-data-container">
-      <span :class="textColor">{{ $t("http.errors.no_records_found") }}</span>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ref, computed } from "vue";
-import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
-import { Pie } from "vue-chartjs";
-import ChartDataLabels from "chartjs-plugin-datalabels";
-import { base64ToJPEG } from "src/helpers/convertBase64Image";
-import { useQuasar, getCssVar, colors } from "quasar";
-
-ChartJS.register(ArcElement, Tooltip, Legend);
-
-const $q = useQuasar();
-const { lighten } = colors;
-
-const props = defineProps({
-  data: {
-    type: Object,
-    default: () => ({
-      chart_data: [],
-      current_total: 0,
-    }),
-  },
-  dataSetLabel: {
-    type: String,
-    default: "Dados",
-  },
-  title: {
-    type: String,
-    default: "Título",
-  },
-  backgroundColors: {
-    type: Array,
-    default: null,
-  },
-});
-
-const chart_ref = ref(null);
-
-const onResize = () => {
-  if (chart_ref.value?.chart) {
-    setTimeout(() => {
-      chart_ref.value.chart.resize();
-    }, 50);
-  }
-};
-
-const textColor = computed(() => {
-  return $q.dark.isActive ? "text-white" : "text-black";
-});
-
-const labelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const dataLabelColor = computed(() => {
-  return $q.dark.isActive ? "#ffffff" : "#000000";
-});
-
-const hasData = computed(() => {
-  return props.data?.chart_data && props.data.chart_data.length > 0;
-});
-
-const chartLabels = computed(() => {
-  return props.data?.chart_data?.map((item) => item.label) || [];
-});
-
-const chartValues = computed(() => {
-  return props.data?.chart_data?.map((item) => item.value) || [];
-});
-
-const chartPercentages = computed(() => {
-  const total = props.data?.current_total || 0;
-  if (total === 0) return [];
-
-  return (
-    props.data?.chart_data?.map((item) =>
-      Math.round((item.value / total) * 100),
-    ) || []
-  );
-});
-
-const chartThemeColors = computed(() => {
-  if (props.backgroundColors) {
-    return props.backgroundColors;
-  }
-
-  const primaryColor = getCssVar("primary");
-  if (!primaryColor) return [];
-
-  const numColors = chartValues.value.length;
-  const step = numColors > 0 ? 50 / numColors : 0;
-  return Array.from({ length: numColors }, (_, i) =>
-    lighten(primaryColor, i * step),
-  );
-});
-
-const chartPieData = computed(() => ({
-  labels: chartLabels.value,
-  datasets: [
-    {
-      label: props.dataSetLabel,
-      data: chartPercentages.value,
-      backgroundColor: chartThemeColors.value,
-    },
-  ],
-}));
-
-const chartPieOptions = computed(() => ({
-  responsive: true,
-  maintainAspectRatio: false,
-  plugins: {
-    legend: {
-      position: "bottom",
-      labels: {
-        color: labelColor.value,
-        font: {
-          size: 12,
-        },
-        padding: 20,
-      },
-    },
-    datalabels: {
-      color: dataLabelColor.value,
-      font: {
-        size: 12,
-        weight: "bold",
-      },
-      formatter: (value) => {
-        return value > 0 ? value + "%" : "";
-      },
-    },
-    tooltip: {
-      backgroundColor: $q.dark.isActive
-        ? "rgba(0, 0, 0, 0.8)"
-        : "rgba(255, 255, 255, 0.9)",
-      titleColor: labelColor.value,
-      bodyColor: labelColor.value,
-      borderColor: labelColor.value,
-      borderWidth: 1,
-      callbacks: {
-        label: (context) => {
-          const label = context.label || "";
-          const percentage = context.parsed;
-          const actualValue = chartValues.value[context.dataIndex];
-          return `${label}: ${actualValue} (${percentage}%)`;
-        },
-      },
-    },
-  },
-}));
-
-const downloadImage = () => {
-  const image = chart_ref.value.chart?.toBase64Image("image/jpeg", 1);
-  base64ToJPEG(image, props.title || "pie-chart");
-};
-
-defineExpose({
-  downloadImage,
-  chart_ref,
-});
-</script>
-
-<style scoped>
-.chart-wrapper {
-  position: relative;
-}
-
-.chart-container {
-  position: absolute;
-  top: 10px;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.no-data-container {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  padding: 1.5rem;
-}
-</style>

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff