Jelajahi Sumber

refactor: traduz ui para portugues

ebagabee 1 bulan lalu
induk
melakukan
aea3f97516

+ 21 - 0
src/api/student_contract.js

@@ -0,0 +1,21 @@
+import api from "src/api";
+
+export const getContractsByStudent = async (studentId) => {
+  const { data } = await api.get("/student-contract", { params: { student_id: studentId } });
+  return data.payload;
+};
+
+export const getFranchisorContractSummary = async () => {
+  const { data } = await api.get("/student-contract/franchisor/summary");
+  return data.payload;
+};
+
+export const getFranchisorFrozenContracts = async () => {
+  const { data } = await api.get("/student-contract/franchisor/frozen");
+  return data.payload;
+};
+
+export const getFranchisorCancelledContracts = async () => {
+  const { data } = await api.get("/student-contract/franchisor/cancelled");
+  return data.payload;
+};

+ 14 - 10
src/pages/dashboard/DashboardPage.vue

@@ -64,7 +64,7 @@
         <DashboardStatCard
           title="Contratos Congelados"
           icon="mdi-snowflake"
-          value="57"
+          :value="frozenContracts"
           subtitle="É hora de incentivar nossos alunos"
           clickable
           @click="openFrozenContractsDialog"
@@ -72,7 +72,7 @@
         <DashboardStatCard
           title="Contratos Cancelados"
           icon="mdi-cancel"
-          value="57"
+          :value="cancelledContracts"
           subtitle="É hora de incentivar nossos alunos"
           clickable
           @click="openCancelledContractsDialog"
@@ -80,7 +80,7 @@
         <DashboardStatCard
           title="Receita Geral"
           icon="mdi-currency-usd"
-          value="R$ 51.548,80"
+          value="R$ 0,00"
           subtitle="0 pagamentos pendentes"
         />
       </div>
@@ -89,30 +89,27 @@
         <DashboardStatCard
           title="Frequência Média"
           icon="mdi-account-multiple-outline"
-          value="87%"
-          badge="Alta"
-          badge-color="approved"
-          custom-style="padding: 6px 24px"
+          value="0%"
           clickable
           @click="openAverageAttendanceDialog"
         />
         <DashboardStatCard
           title="Estoque Geral de Produtos"
           icon="mdi-currency-usd"
-          value="56"
+          value="0"
           clickable
           @click="openProductStockDialog"
         />
         <DashboardStatCard
           title="Tarefas Pendentes"
           icon="mdi-draw"
-          value="4"
+          value="0"
           subtitle="Não deixe para amanhã"
         />
         <DashboardStatCard
           title="Tickets Abertos"
           icon="mdi-calendar-outline"
-          value="2"
+          value="0"
           subtitle="Estável"
           clickable
           @click="openTicketsDialog"
@@ -170,6 +167,7 @@ import BirthdaysCard from "src/components/charts/BirthdaysCard.vue";
 import HolidaysCard from "src/components/charts/HolidaysCard.vue";
 import ActiveStudentsDialog from "src/pages/dashboard/components/ActiveStudentsDialog.vue";
 import { getStudentSummaryFranchisor } from "src/api/student";
+import { getFranchisorContractSummary } from "src/api/student_contract";
 import FrozenContractsDialog from "src/pages/dashboard/components/FrozenContractsDialog.vue";
 import CancelledContractsDialog from "src/pages/dashboard/components/CancelledContractsDialog.vue";
 import AverageAttendanceDialog from "src/pages/dashboard/components/AverageAttendanceDialog.vue";
@@ -184,6 +182,8 @@ const isLoading = ref(true);
 
 const totalStudents = ref(0);
 const activeContracts = ref(0);
+const frozenContracts = ref(0);
+const cancelledContracts = ref(0);
 
 const openActiveStudentsDialog = () => {
   $q.dialog({ component: ActiveStudentsDialog });
@@ -445,6 +445,10 @@ onMounted(async () => {
     totalStudents.value = summary.total;
     activeContracts.value = summary.active;
   });
+  getFranchisorContractSummary().then((summary) => {
+    frozenContracts.value = summary.frozen;
+    cancelledContracts.value = summary.cancelled;
+  });
   await updateDashboardData();
 });
 </script>

+ 2 - 2
src/pages/dashboard/StudentDetailPage.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <DefaultHeaderPage title="Student Detail" />
+    <DefaultHeaderPage title="Detalhe do Aluno" />
 
     <div class="q-pa-md">
       <div v-if="loading" class="flex flex-center q-pa-xl">
@@ -45,7 +45,7 @@
         </div>
       </div>
 
-      <div v-else class="text-grey-6 q-pa-md">Student not found.</div>
+      <div v-else class="text-grey-6 q-pa-md">Aluno não encontrado.</div>
     </div>
   </div>
 </template>

+ 4 - 4
src/pages/dashboard/components/ActiveStudentsDialog.vue

@@ -2,7 +2,7 @@
   <q-dialog ref="dialogRef" @hide="onDialogHide">
     <q-card style="width: 800px; max-width: 95vw; border-radius: 12px">
       <q-bar class="bg-transparent q-px-md" style="height: 55px">
-        <span class="text-h6 text-dark" style="font-weight: 600">Active Students</span>
+        <span class="text-h6 text-dark" style="font-weight: 600">Alunos Ativos</span>
         <q-space />
         <q-btn dense flat icon="mdi-close" @click="onDialogCancel" />
       </q-bar>
@@ -10,9 +10,9 @@
       <q-card-section class="q-pt-none q-pb-md q-px-md">
         <q-card flat bordered style="border-radius: 8px">
           <q-card-section class="q-pb-xs">
-            <div class="text-subtitle2 text-dark">Active students list</div>
+            <div class="text-subtitle2 text-dark">Lista de alunos ativos</div>
             <div class="text-caption text-grey-6">
-              {{ students.length }} Active Students
+              {{ students.length }} Alunos Ativos
               <q-spinner v-if="loading" size="16px" color="primary" class="q-ml-sm" />
             </div>
           </q-card-section>
@@ -22,7 +22,7 @@
               v-model="search"
               dense
               borderless
-              placeholder="Search by name, phone or unit"
+              placeholder="Busque por nome, tel/whats ou unidade"
             >
               <template #prepend>
                 <q-icon name="mdi-magnify" color="grey-6" />

+ 41 - 77
src/pages/dashboard/components/CancelledContractsDialog.vue

@@ -2,9 +2,7 @@
   <q-dialog ref="dialogRef" @hide="onDialogHide">
     <q-card style="width: 800px; max-width: 95vw; border-radius: 12px">
       <q-bar class="bg-transparent q-px-md" style="height: 55px">
-        <span class="text-h6 text-dark" style="font-weight: 600"
-          >Contratos Cancelados</span
-        >
+        <span class="text-h6 text-dark" style="font-weight: 600">Contratos Cancelados</span>
         <q-space />
         <q-btn dense flat icon="mdi-close" @click="onDialogCancel" />
       </q-bar>
@@ -12,9 +10,10 @@
       <q-card-section class="q-pt-none q-pb-md q-px-md">
         <q-card flat bordered style="border-radius: 8px">
           <q-card-section class="q-pb-xs">
-            <div class="text-subtitle2 text-dark">Lista de alunos</div>
+            <div class="text-subtitle2 text-dark">Lista de contratos cancelados</div>
             <div class="text-caption text-grey-6">
-              {{ contratos.length }} Alunos Cadastrados
+              {{ contracts.length }} Contratos Cancelados
+              <q-spinner v-if="loading" size="16px" color="primary" class="q-ml-sm" />
             </div>
           </q-card-section>
 
@@ -23,7 +22,7 @@
               v-model="search"
               dense
               borderless
-              placeholder="Busque por status, nome, tel/whats"
+              placeholder="Busque por nome, tel/whats ou unidade"
             >
               <template #prepend>
                 <q-icon name="mdi-magnify" color="grey-6" />
@@ -42,26 +41,15 @@
           <q-separator />
 
           <div style="max-height: 320px; overflow-y: auto">
-            <template
-              v-for="(contrato, index) in filteredContratos"
-              :key="contrato.id"
-            >
-              <div
-                class="list-row q-px-md q-py-sm"
-                :class="{ 'row-selected': index === selectedIndex }"
-                @click="selectedIndex = index"
-              >
-                <span class="text-body2 text-dark">{{ contrato.nome }}</span>
+            <template v-for="(contract, index) in filteredContracts" :key="contract.id">
+              <div class="list-row q-px-md q-py-sm">
+                <span class="text-body2 text-dark">{{ contract.studentName }}</span>
                 <div class="column" style="gap: 2px">
-                  <span class="text-caption text-dark">{{
-                    contrato.telefone
-                  }}</span>
-                  <span class="text-caption text-grey-6">{{
-                    contrato.unidade
-                  }}</span>
+                  <span class="text-caption text-dark">{{ contract.studentPhone }}</span>
+                  <span class="text-caption text-grey-6">{{ contract.unitName }}</span>
                 </div>
                 <q-badge
-                  label="Cancelados"
+                  label="Cancelado"
                   color="negative"
                   style="
                     border-radius: 8px;
@@ -72,7 +60,7 @@
                   "
                 />
               </div>
-              <q-separator v-if="index < filteredContratos.length - 1" />
+              <q-separator v-if="index < filteredContracts.length - 1" />
             </template>
           </div>
         </q-card>
@@ -91,63 +79,43 @@
 </template>
 
 <script setup>
-import { ref, computed } from "vue";
+import { ref, computed, onMounted } from "vue";
 import { useDialogPluginComponent } from "quasar";
+import { getFranchisorCancelledContracts } from "src/api/student_contract";
 
 defineEmits([...useDialogPluginComponent.emits]);
 
 const { dialogRef, onDialogHide, onDialogCancel } = useDialogPluginComponent();
 
 const search = ref("");
-const selectedIndex = ref(0);
-
-const contratos = [
-  {
-    id: 1,
-    nome: "Heloisa Faria",
-    telefone: "(45)99999-9999",
-    unidade: "Unidade franco",
-  },
-  {
-    id: 2,
-    nome: "Carol",
-    telefone: "(45)99999-9999",
-    unidade: "Arapongas-PR",
-  },
-  {
-    id: 3,
-    nome: "Marcelo Souza",
-    telefone: "(45)98888-8888",
-    unidade: "Curitiba-PR",
-  },
-  {
-    id: 4,
-    nome: "Ana Lúcia",
-    telefone: "(45)97777-7777",
-    unidade: "Londrina-PR",
-  },
-  {
-    id: 5,
-    nome: "Ricardo Silva",
-    telefone: "(45)96666-6666",
-    unidade: "Ponta Grossa-PR",
-  },
-  {
-    id: 6,
-    nome: "Juliana Costa",
-    telefone: "(45)95555-5555",
-    unidade: "Maringá-PR",
-  },
-];
-
-const filteredContratos = computed(() => {
-  if (!search.value) return contratos;
+const loading = ref(false);
+const contracts = ref([]);
+
+onMounted(async () => {
+  loading.value = true;
+  try {
+    const data = await getFranchisorCancelledContracts();
+    contracts.value = data.map((c) => ({
+      id: c.id,
+      studentName: c.student_name ?? "—",
+      studentPhone: c.student_phone ?? "—",
+      unitName: c.unit_name ?? "—",
+    }));
+  } catch {
+    // silent
+  } finally {
+    loading.value = false;
+  }
+});
+
+const filteredContracts = computed(() => {
+  if (!search.value) return contracts.value;
   const q = search.value.toLowerCase();
-  return contratos.filter(
+  return contracts.value.filter(
     (c) =>
-      c.nome.toLowerCase().includes(q) ||
-      c.telefone.includes(q) ||
-      c.unidade.toLowerCase().includes(q),
+      c.studentName.toLowerCase().includes(q) ||
+      c.studentPhone.includes(q) ||
+      c.unitName.toLowerCase().includes(q),
   );
 });
 </script>
@@ -164,15 +132,11 @@ const filteredContratos = computed(() => {
   grid-template-columns: 1fr 1fr 100px;
   align-items: center;
   align-content: center;
-  cursor: pointer;
+  cursor: default;
   transition: background-color 0.15s;
 }
 
 .list-row:hover {
   background-color: #f5f5f5;
 }
-
-.row-selected {
-  background-color: #b2dfdb !important;
-}
 </style>

+ 40 - 76
src/pages/dashboard/components/FrozenContractsDialog.vue

@@ -2,9 +2,7 @@
   <q-dialog ref="dialogRef" @hide="onDialogHide">
     <q-card style="width: 800px; max-width: 95vw; border-radius: 12px">
       <q-bar class="bg-transparent q-px-md" style="height: 55px">
-        <span class="text-h6 text-dark" style="font-weight: 600"
-          >Contratos Congelados</span
-        >
+        <span class="text-h6 text-dark" style="font-weight: 600">Contratos Congelados</span>
         <q-space />
         <q-btn dense flat icon="mdi-close" @click="onDialogCancel" />
       </q-bar>
@@ -12,9 +10,10 @@
       <q-card-section class="q-pt-none q-pb-md q-px-md">
         <q-card flat bordered style="border-radius: 8px">
           <q-card-section class="q-pb-xs">
-            <div class="text-subtitle2 text-dark">Lista de alunos</div>
+            <div class="text-subtitle2 text-dark">Lista de contratos congelados</div>
             <div class="text-caption text-grey-6">
-              {{ contratos.length }} Alunos Cadastrados
+              {{ contracts.length }} Contratos Congelados
+              <q-spinner v-if="loading" size="16px" color="primary" class="q-ml-sm" />
             </div>
           </q-card-section>
 
@@ -23,7 +22,7 @@
               v-model="search"
               dense
               borderless
-              placeholder="Busque por status, nome, tel/whats"
+              placeholder="Busque por nome, tel/whats ou unidade"
             >
               <template #prepend>
                 <q-icon name="mdi-magnify" color="grey-6" />
@@ -42,23 +41,12 @@
           <q-separator />
 
           <div style="max-height: 320px; overflow-y: auto">
-            <template
-              v-for="(contrato, index) in filteredContratos"
-              :key="contrato.id"
-            >
-              <div
-                class="list-row q-px-md q-py-sm"
-                :class="{ 'row-selected': index === selectedIndex }"
-                @click="selectedIndex = index"
-              >
-                <span class="text-body2 text-dark">{{ contrato.nome }}</span>
+            <template v-for="(contract, index) in filteredContracts" :key="contract.id">
+              <div class="list-row q-px-md q-py-sm">
+                <span class="text-body2 text-dark">{{ contract.studentName }}</span>
                 <div class="column" style="gap: 2px">
-                  <span class="text-caption text-dark">{{
-                    contrato.telefone
-                  }}</span>
-                  <span class="text-caption text-grey-6">{{
-                    contrato.unidade
-                  }}</span>
+                  <span class="text-caption text-dark">{{ contract.studentPhone }}</span>
+                  <span class="text-caption text-grey-6">{{ contract.unitName }}</span>
                 </div>
                 <q-badge
                   label="Congelado"
@@ -72,7 +60,7 @@
                   "
                 />
               </div>
-              <q-separator v-if="index < filteredContratos.length - 1" />
+              <q-separator v-if="index < filteredContracts.length - 1" />
             </template>
           </div>
         </q-card>
@@ -91,63 +79,43 @@
 </template>
 
 <script setup>
-import { ref, computed } from "vue";
+import { ref, computed, onMounted } from "vue";
 import { useDialogPluginComponent } from "quasar";
+import { getFranchisorFrozenContracts } from "src/api/student_contract";
 
 defineEmits([...useDialogPluginComponent.emits]);
 
 const { dialogRef, onDialogHide, onDialogCancel } = useDialogPluginComponent();
 
 const search = ref("");
-const selectedIndex = ref(0);
-
-const contratos = [
-  {
-    id: 1,
-    nome: "Heloisa Faria",
-    telefone: "(45)99999-9999",
-    unidade: "Unidade franco",
-  },
-  {
-    id: 2,
-    nome: "Carol",
-    telefone: "(45)99999-9999",
-    unidade: "Arapongas-PR",
-  },
-  {
-    id: 3,
-    nome: "Marcelo Souza",
-    telefone: "(45)98888-8888",
-    unidade: "Curitiba-PR",
-  },
-  {
-    id: 4,
-    nome: "Ana Lúcia",
-    telefone: "(45)97777-7777",
-    unidade: "Londrina-PR",
-  },
-  {
-    id: 5,
-    nome: "Ricardo Silva",
-    telefone: "(45)96666-6666",
-    unidade: "Ponta Grossa-PR",
-  },
-  {
-    id: 6,
-    nome: "Juliana Costa",
-    telefone: "(45)95555-5555",
-    unidade: "Maringá-PR",
-  },
-];
-
-const filteredContratos = computed(() => {
-  if (!search.value) return contratos;
+const loading = ref(false);
+const contracts = ref([]);
+
+onMounted(async () => {
+  loading.value = true;
+  try {
+    const data = await getFranchisorFrozenContracts();
+    contracts.value = data.map((c) => ({
+      id: c.id,
+      studentName: c.student_name ?? "—",
+      studentPhone: c.student_phone ?? "—",
+      unitName: c.unit_name ?? "—",
+    }));
+  } catch {
+    // silent
+  } finally {
+    loading.value = false;
+  }
+});
+
+const filteredContracts = computed(() => {
+  if (!search.value) return contracts.value;
   const q = search.value.toLowerCase();
-  return contratos.filter(
+  return contracts.value.filter(
     (c) =>
-      c.nome.toLowerCase().includes(q) ||
-      c.telefone.includes(q) ||
-      c.unidade.toLowerCase().includes(q),
+      c.studentName.toLowerCase().includes(q) ||
+      c.studentPhone.includes(q) ||
+      c.unitName.toLowerCase().includes(q),
   );
 });
 </script>
@@ -164,15 +132,11 @@ const filteredContratos = computed(() => {
   grid-template-columns: 1fr 1fr 100px;
   align-items: center;
   align-content: center;
-  cursor: pointer;
+  cursor: default;
   transition: background-color 0.15s;
 }
 
 .list-row:hover {
   background-color: #f5f5f5;
 }
-
-.row-selected {
-  background-color: #b2dfdb !important;
-}
 </style>

+ 1 - 1
src/router/routes/student.route.js

@@ -4,7 +4,7 @@ export default [
     name: "StudentDetailPage",
     component: () => import("pages/dashboard/StudentDetailPage.vue"),
     meta: {
-      title: { value: "Student Detail", translate: false },
+      title: { value: "Detalhe do Aluno", translate: false },
       requireAuth: true,
     },
   },