|
@@ -8,8 +8,10 @@
|
|
|
:badges="studentsStatusBadges"
|
|
:badges="studentsStatusBadges"
|
|
|
:value="String(totalAlunos)"
|
|
:value="String(totalAlunos)"
|
|
|
:value-color="activeStudentsColor"
|
|
:value-color="activeStudentsColor"
|
|
|
|
|
+ clickable
|
|
|
icon="mdi-account-multiple-outline"
|
|
icon="mdi-account-multiple-outline"
|
|
|
title="Total alunos"
|
|
title="Total alunos"
|
|
|
|
|
+ @click="openStudentsDialog"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
<!-- TODO: usar dados reais de receita (zerado por enquanto). -->
|
|
<!-- TODO: usar dados reais de receita (zerado por enquanto). -->
|
|
@@ -285,6 +287,7 @@ import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
|
|
|
import AddEditContractDialog from "src/pages/students/components/AddEditContractDialog.vue";
|
|
import AddEditContractDialog from "src/pages/students/components/AddEditContractDialog.vue";
|
|
|
import FeriadosDialog from "./components/FeriadosDialog.vue";
|
|
import FeriadosDialog from "./components/FeriadosDialog.vue";
|
|
|
import FeriadosEditDialog from "./components/FeriadosEditDialog.vue";
|
|
import FeriadosEditDialog from "./components/FeriadosEditDialog.vue";
|
|
|
|
|
+import StudentsStatusDialog from "./components/StudentsStatusDialog.vue";
|
|
|
|
|
|
|
|
ChartJS.register(ArcElement, Tooltip, Legend);
|
|
ChartJS.register(ArcElement, Tooltip, Legend);
|
|
|
|
|
|
|
@@ -303,47 +306,50 @@ const studentsByStatus = ref({ active: 0, ex_student: 0, lead: 0, locked: 0 });
|
|
|
const totalAlunos = ref(0);
|
|
const totalAlunos = ref(0);
|
|
|
const unitConfig = ref({
|
|
const unitConfig = ref({
|
|
|
active_students_min: 30,
|
|
active_students_min: 30,
|
|
|
- active_students_medium: 50,
|
|
|
|
|
active_students_max: 80,
|
|
active_students_max: 80,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const activeStudentsColor = computed(() => {
|
|
const activeStudentsColor = computed(() => {
|
|
|
const count = totalAlunos.value;
|
|
const count = totalAlunos.value;
|
|
|
const min = unitConfig.value.active_students_min;
|
|
const min = unitConfig.value.active_students_min;
|
|
|
- const med = unitConfig.value.active_students_medium;
|
|
|
|
|
|
|
+ const max = unitConfig.value.active_students_max;
|
|
|
|
|
|
|
|
if (count < min) return "negative"; // Vermelho
|
|
if (count < min) return "negative"; // Vermelho
|
|
|
- if (count >= min && count < med) return "warning"; // Amarelo
|
|
|
|
|
- return "positive"; // Verde (>= med)
|
|
|
|
|
|
|
+ if (count < max) return "warning"; // Amarelo
|
|
|
|
|
+ return "positive"; // Verde (>= max)
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const studentsStatusBadges = computed(() => [
|
|
const studentsStatusBadges = computed(() => [
|
|
|
- { color: "info", label: `${studentsByStatus.value.lead} Lead` },
|
|
|
|
|
{ color: "positive", label: `${studentsByStatus.value.active} Ativo` },
|
|
{ color: "positive", label: `${studentsByStatus.value.active} Ativo` },
|
|
|
- { color: "grey", label: `${studentsByStatus.value.ex_student} Ex-aluno` },
|
|
|
|
|
- { color: "warning", label: `${studentsByStatus.value.locked} Trancado` },
|
|
|
|
|
|
|
+ { color: "orange", label: `${studentsByStatus.value.locked} Trancado` },
|
|
|
|
|
+ { color: "grey-7", label: `${studentsByStatus.value.ex_student} Ex-aluno` },
|
|
|
|
|
+ { color: "blue", label: `${studentsByStatus.value.lead} Lead` },
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
-const gaugeData = ref({
|
|
|
|
|
- datasets: [
|
|
|
|
|
- {
|
|
|
|
|
- backgroundColor: [
|
|
|
|
|
- "#00a550",
|
|
|
|
|
- "#4dbb7e",
|
|
|
|
|
- "#9ad2ad",
|
|
|
|
|
- "#cce156",
|
|
|
|
|
- "#fff100",
|
|
|
|
|
- "#ffbe00",
|
|
|
|
|
- "#ff8c00",
|
|
|
|
|
- "#FC3D23",
|
|
|
|
|
- "#D01616",
|
|
|
|
|
- "#8A0000",
|
|
|
|
|
- ],
|
|
|
|
|
- borderColor: "transparent",
|
|
|
|
|
- data: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
|
|
|
- needleValue: 0,
|
|
|
|
|
- },
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+// Faixas do medidor "Contratos Ativos" — mesma meta configurável de
|
|
|
|
|
+// alunos ativos (Dashboard > Metas do Dashboard): vermelho até o mínimo,
|
|
|
|
|
+// amarelo entre mínimo e máximo, verde a partir do máximo.
|
|
|
|
|
+const gaugeScaleMax = computed(() => {
|
|
|
|
|
+ const max = Math.max(unitConfig.value.active_students_max, 1);
|
|
|
|
|
+
|
|
|
|
|
+ return max * 1.2;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const gaugeData = computed(() => {
|
|
|
|
|
+ const min = Math.max(unitConfig.value.active_students_min, 0);
|
|
|
|
|
+ const max = Math.max(unitConfig.value.active_students_max, min + 1);
|
|
|
|
|
+ const scaleMax = Math.max(gaugeScaleMax.value, max + 1);
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ datasets: [
|
|
|
|
|
+ {
|
|
|
|
|
+ backgroundColor: ["#D01616", "#ffbe00", "#00a550"],
|
|
|
|
|
+ borderColor: "transparent",
|
|
|
|
|
+ data: [min, max - min, scaleMax - max],
|
|
|
|
|
+ needleValue: Math.min(activeContracts.value, scaleMax),
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ };
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const gaugeOptions = ref({
|
|
const gaugeOptions = ref({
|
|
@@ -352,12 +358,7 @@ const gaugeOptions = ref({
|
|
|
maintainAspectRatio: false,
|
|
maintainAspectRatio: false,
|
|
|
plugins: {
|
|
plugins: {
|
|
|
datalabels: {
|
|
datalabels: {
|
|
|
- color: "black",
|
|
|
|
|
- font: {
|
|
|
|
|
- size: 14,
|
|
|
|
|
- weight: "bold",
|
|
|
|
|
- },
|
|
|
|
|
- formatter: (_value, context) => context.dataIndex,
|
|
|
|
|
|
|
+ display: false,
|
|
|
},
|
|
},
|
|
|
legend: {
|
|
legend: {
|
|
|
display: false,
|
|
display: false,
|
|
@@ -484,20 +485,19 @@ const gaugeNeedlePlugin = {
|
|
|
const { ctx, data } = chart;
|
|
const { ctx, data } = chart;
|
|
|
|
|
|
|
|
const meta = chart.getDatasetMeta(0).data[0];
|
|
const meta = chart.getDatasetMeta(0).data[0];
|
|
|
- const needleValue = data.datasets[0].needleValue;
|
|
|
|
|
|
|
+ const dataset = data.datasets[0];
|
|
|
|
|
+ const needleValue = dataset.needleValue;
|
|
|
|
|
+ const total = dataset.data.reduce((sum, value) => sum + value, 0) || 1;
|
|
|
const outerRadius = meta.outerRadius - 20;
|
|
const outerRadius = meta.outerRadius - 20;
|
|
|
const xCenter = meta.x;
|
|
const xCenter = meta.x;
|
|
|
const yCenter = meta.y;
|
|
const yCenter = meta.y;
|
|
|
|
|
|
|
|
- const circumference =
|
|
|
|
|
- (meta.circumference / Math.PI / data.datasets[0].data[0]) *
|
|
|
|
|
- needleValue;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ const fraction = Math.min(needleValue, total) / total;
|
|
|
const angle = Math.PI;
|
|
const angle = Math.PI;
|
|
|
|
|
|
|
|
ctx.save();
|
|
ctx.save();
|
|
|
ctx.translate(xCenter, yCenter);
|
|
ctx.translate(xCenter, yCenter);
|
|
|
- ctx.rotate(angle * (circumference + 1.5));
|
|
|
|
|
|
|
+ ctx.rotate(angle * (fraction + 1.5));
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
ctx.beginPath();
|
|
|
ctx.fillStyle = "grey";
|
|
ctx.fillStyle = "grey";
|
|
@@ -569,11 +569,6 @@ const fetchSummary = async () => {
|
|
|
if (summary.unit_config) {
|
|
if (summary.unit_config) {
|
|
|
unitConfig.value = summary.unit_config;
|
|
unitConfig.value = summary.unit_config;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- gaugeData.value.datasets[0].needleValue = Math.min(
|
|
|
|
|
- activeContracts.value,
|
|
|
|
|
- 10,
|
|
|
|
|
- );
|
|
|
|
|
} catch {
|
|
} catch {
|
|
|
// silencioso
|
|
// silencioso
|
|
|
}
|
|
}
|
|
@@ -608,6 +603,12 @@ const onRegistrarPresenca = () => {
|
|
|
router.push({ name: "ClassPage" });
|
|
router.push({ name: "ClassPage" });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const openStudentsDialog = () => {
|
|
|
|
|
+ $q.dialog({
|
|
|
|
|
+ component: StudentsStatusDialog,
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const openEditFromDashboard = (feriado) => {
|
|
const openEditFromDashboard = (feriado) => {
|
|
|
$q.dialog({
|
|
$q.dialog({
|
|
|
component: FeriadosEditDialog,
|
|
component: FeriadosEditDialog,
|