|
|
@@ -0,0 +1,129 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <DefaultHeaderPage title="Contratos" />
|
|
|
+
|
|
|
+ <div class="q-px-sm">
|
|
|
+ <div class="stat-cards-row q-mb-md">
|
|
|
+ <DashboardStatCard
|
|
|
+ title="Contratos Ativos"
|
|
|
+ icon="mdi-file-check-outline"
|
|
|
+ :value="String(metrics.active)"
|
|
|
+ />
|
|
|
+ <DashboardStatCard
|
|
|
+ title="Contratos Congelados"
|
|
|
+ icon="mdi-snowflake"
|
|
|
+ :value="String(metrics.frozen)"
|
|
|
+ />
|
|
|
+ <DashboardStatCard
|
|
|
+ title="Contratos Cancelados"
|
|
|
+ icon="mdi-file-remove-outline"
|
|
|
+ :value="String(metrics.cancelled)"
|
|
|
+ />
|
|
|
+ <DashboardStatCard
|
|
|
+ title="Contratos Inadimplentes"
|
|
|
+ icon="mdi-alert-circle-outline"
|
|
|
+ value="0"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <DefaultTable
|
|
|
+ v-model:rows="rows"
|
|
|
+ title="Contratos"
|
|
|
+ :columns
|
|
|
+ descricao="contratos"
|
|
|
+ :feminino="false"
|
|
|
+ no-api-call
|
|
|
+ :loading="isLoading"
|
|
|
+ >
|
|
|
+ <template #body-cell-contato="{ row }">
|
|
|
+ <q-td>
|
|
|
+ <div>{{ row.student_phone }}</div>
|
|
|
+ <div class="text-grey-6 text-caption">
|
|
|
+ {{ row.student_city }}<template v-if="row.student_city && row.student_state_code">, </template>{{ row.student_state_code }}
|
|
|
+ </div>
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #body-cell-status="{ row }">
|
|
|
+ <q-td align="center">
|
|
|
+ <q-badge
|
|
|
+ :color="statusColor(row.status)"
|
|
|
+ :label="statusLabel(row.status)"
|
|
|
+ />
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
+ </DefaultTable>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, onMounted } from "vue";
|
|
|
+import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
|
|
|
+import DefaultTable from "src/components/defaults/DefaultTable.vue";
|
|
|
+import DashboardStatCard from "src/components/charts/DashboardStatCard.vue";
|
|
|
+import { getAllContracts } from "src/api/studentContract";
|
|
|
+
|
|
|
+const rows = ref([]);
|
|
|
+const isLoading = ref(false);
|
|
|
+
|
|
|
+const metrics = computed(() => ({
|
|
|
+ active: rows.value.filter((r) => r.status === "active").length,
|
|
|
+ frozen: rows.value.filter((r) => r.status === "frozen").length,
|
|
|
+ cancelled: rows.value.filter((r) => r.status === "cancelled").length,
|
|
|
+}));
|
|
|
+
|
|
|
+const columns = ref([
|
|
|
+ { name: "name", label: "Nome", field: "student_name", align: "left" },
|
|
|
+ { name: "contato", label: "Contato/Endereço", field: null, align: "left" },
|
|
|
+ { name: "status", label: "Status Contrato", field: "status", align: "center" },
|
|
|
+]);
|
|
|
+
|
|
|
+async function loadContracts() {
|
|
|
+ isLoading.value = true;
|
|
|
+ try {
|
|
|
+ rows.value = await getAllContracts();
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function statusColor(status) {
|
|
|
+ if (status === "active") return "positive";
|
|
|
+ if (status === "frozen") return "info";
|
|
|
+ if (status === "cancelled") return "negative";
|
|
|
+ return "warning";
|
|
|
+}
|
|
|
+
|
|
|
+function statusLabel(status) {
|
|
|
+ if (status === "active") return "Ativo";
|
|
|
+ if (status === "frozen") return "Congelado";
|
|
|
+ if (status === "cancelled") return "Cancelado";
|
|
|
+ return "Inativo";
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(loadContracts);
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.stat-cards-row {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: nowrap;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-cards-row > * {
|
|
|
+ flex: 1 1 0;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .stat-cards-row {
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-cards-row > * {
|
|
|
+ flex: 1 1 calc(50% - 8px);
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|