|
|
@@ -9,248 +9,298 @@
|
|
|
@close="onDialogCancel"
|
|
|
/>
|
|
|
|
|
|
+ <template v-if="props.contract">
|
|
|
+ <q-tabs
|
|
|
+ v-model="activeTab"
|
|
|
+ dense
|
|
|
+ align="left"
|
|
|
+ class="q-px-md text-grey-7"
|
|
|
+ active-color="primary"
|
|
|
+ indicator-color="primary"
|
|
|
+ >
|
|
|
+ <q-tab name="dados" label="Dados do Contrato" />
|
|
|
+ <q-tab name="midias" label="Mídias do Contrato" />
|
|
|
+ </q-tabs>
|
|
|
+ <q-separator />
|
|
|
+ </template>
|
|
|
+
|
|
|
<q-card-section class="q-pt-sm" style="height: 65vh; overflow-y: auto">
|
|
|
- <div class="text-subtitle1 q-mb-md">Dados do Aluno</div>
|
|
|
-
|
|
|
- <div class="row q-col-gutter-sm">
|
|
|
- <div class="col-12">
|
|
|
- <DefaultInput
|
|
|
- :model-value="props.student.name"
|
|
|
- label="Aluno"
|
|
|
- disable
|
|
|
- />
|
|
|
+ <div v-show="activeTab === 'dados'">
|
|
|
+ <div class="text-subtitle1 q-mb-md">Dados do Aluno</div>
|
|
|
+
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <div class="col-12">
|
|
|
+ <DefaultInput
|
|
|
+ :model-value="props.student.name"
|
|
|
+ label="Aluno"
|
|
|
+ disable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-6">
|
|
|
+ <DefaultInput
|
|
|
+ :model-value="props.student.document_number"
|
|
|
+ label="CPF"
|
|
|
+ disable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-6">
|
|
|
+ <DefaultInput
|
|
|
+ :model-value="formattedBirthDate"
|
|
|
+ label="Data de Nascimento"
|
|
|
+ disable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="col-6">
|
|
|
- <DefaultInput
|
|
|
- :model-value="props.student.document_number"
|
|
|
- label="CPF"
|
|
|
- disable
|
|
|
- />
|
|
|
+ <div class="text-subtitle1 q-mt-lg q-mb-md">Dados do Contrato</div>
|
|
|
+
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput v-model="form.protocol" label="Protocolo" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInputDatePicker
|
|
|
+ v-model="form.signature_date"
|
|
|
+ label="Data Assinatura"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInputDatePicker
|
|
|
+ v-model="form.end_date"
|
|
|
+ label="Data Encerramento"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-5">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="form.package_id"
|
|
|
+ label="Pacote de Aulas"
|
|
|
+ :options="packages"
|
|
|
+ option-value="id"
|
|
|
+ option-label="name"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-7">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.class_quantity"
|
|
|
+ label="Qtd. Aulas"
|
|
|
+ type="number"
|
|
|
+ disable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="form.weekday"
|
|
|
+ label="Dia da Semana"
|
|
|
+ :options="weekdays"
|
|
|
+ option-value="value"
|
|
|
+ option-label="label"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.start_time"
|
|
|
+ label="Hora de Início"
|
|
|
+ mask="##:##"
|
|
|
+ >
|
|
|
+ <template #append>
|
|
|
+ <q-icon name="mdi-clock-outline" />
|
|
|
+ </template>
|
|
|
+ </DefaultInput>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.end_time"
|
|
|
+ label="Hora de Término"
|
|
|
+ mask="##:##"
|
|
|
+ >
|
|
|
+ <template #append>
|
|
|
+ <q-icon name="mdi-clock-outline" />
|
|
|
+ </template>
|
|
|
+ </DefaultInput>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="form.second_weekday"
|
|
|
+ label="2° Dia da Semana"
|
|
|
+ :options="weekdays"
|
|
|
+ option-value="value"
|
|
|
+ option-label="label"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.second_start_time"
|
|
|
+ label="Hora de Início"
|
|
|
+ mask="##:##"
|
|
|
+ >
|
|
|
+ <template #append>
|
|
|
+ <q-icon name="mdi-clock-outline" />
|
|
|
+ </template>
|
|
|
+ </DefaultInput>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.second_end_time"
|
|
|
+ label="Hora de Término"
|
|
|
+ mask="##:##"
|
|
|
+ >
|
|
|
+ <template #append>
|
|
|
+ <q-icon name="mdi-clock-outline" />
|
|
|
+ </template>
|
|
|
+ </DefaultInput>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="col-6">
|
|
|
- <DefaultInput
|
|
|
- :model-value="formattedBirthDate"
|
|
|
- label="Data de Nascimento"
|
|
|
- disable
|
|
|
- />
|
|
|
+ <div class="text-subtitle1 q-mt-lg q-mb-md">Dados Financeiros</div>
|
|
|
+
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.due_day"
|
|
|
+ label="Dia de Vencimento"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultCurrencyInput
|
|
|
+ v-model="form.enrollment_fee"
|
|
|
+ label="Taxa de Matrícula"
|
|
|
+ disable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-4">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.total_classes"
|
|
|
+ label="Total de Aulas"
|
|
|
+ type="number"
|
|
|
+ disable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-3">
|
|
|
+ <DefaultCurrencyInput v-model="form.down_payment" label="Entrada" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-3">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="form.installments"
|
|
|
+ label="Parcelas"
|
|
|
+ :options="installmentOptions"
|
|
|
+ option-value="value"
|
|
|
+ option-label="label"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-6">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.early_payment_discount"
|
|
|
+ label="Desconto até o vencimento (%)"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-3">
|
|
|
+ <DefaultCurrencyInput
|
|
|
+ v-model="form.material_value"
|
|
|
+ label="Valor dos Materiais"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-3">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="form.material_installments"
|
|
|
+ label="Parcelas"
|
|
|
+ :options="installmentOptions"
|
|
|
+ option-value="value"
|
|
|
+ option-label="label"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-6">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.interest_rate"
|
|
|
+ label="Juros (%) a.m"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-6">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="form.payment_method"
|
|
|
+ label="Forma de Pagamento"
|
|
|
+ :options="paymentMethods"
|
|
|
+ option-value="value"
|
|
|
+ option-label="label"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="col-6">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.late_fee"
|
|
|
+ label="Multa (%)"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="text-subtitle1 q-mt-lg q-mb-md">Dados do Contrato</div>
|
|
|
-
|
|
|
- <div class="row q-col-gutter-sm">
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput v-model="form.protocol" label="Protocolo" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInputDatePicker
|
|
|
- v-model="form.signature_date"
|
|
|
- label="Data Assinatura"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInputDatePicker
|
|
|
- v-model="form.end_date"
|
|
|
- label="Data Encerramento"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-5">
|
|
|
- <DefaultSelect
|
|
|
- v-model="form.package_id"
|
|
|
- label="Pacote de Aulas"
|
|
|
- :options="packages"
|
|
|
- option-value="id"
|
|
|
- option-label="name"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-7">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.class_quantity"
|
|
|
- label="Qtd. Aulas"
|
|
|
- type="number"
|
|
|
- disable
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultSelect
|
|
|
- v-model="form.weekday"
|
|
|
- label="Dia da Semana"
|
|
|
- :options="weekdays"
|
|
|
- option-value="value"
|
|
|
- option-label="label"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.start_time"
|
|
|
- label="Hora de Início"
|
|
|
- mask="##:##"
|
|
|
- >
|
|
|
- <template #append>
|
|
|
- <q-icon name="mdi-clock-outline" />
|
|
|
- </template>
|
|
|
- </DefaultInput>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.end_time"
|
|
|
- label="Hora de Término"
|
|
|
- mask="##:##"
|
|
|
- >
|
|
|
- <template #append>
|
|
|
- <q-icon name="mdi-clock-outline" />
|
|
|
- </template>
|
|
|
- </DefaultInput>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultSelect
|
|
|
- v-model="form.second_weekday"
|
|
|
- label="2° Dia da Semana"
|
|
|
- :options="weekdays"
|
|
|
- option-value="value"
|
|
|
- option-label="label"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.second_start_time"
|
|
|
- label="Hora de Início"
|
|
|
- mask="##:##"
|
|
|
- >
|
|
|
- <template #append>
|
|
|
- <q-icon name="mdi-clock-outline" />
|
|
|
- </template>
|
|
|
- </DefaultInput>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.second_end_time"
|
|
|
- label="Hora de Término"
|
|
|
- mask="##:##"
|
|
|
- >
|
|
|
- <template #append>
|
|
|
- <q-icon name="mdi-clock-outline" />
|
|
|
- </template>
|
|
|
- </DefaultInput>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="text-subtitle1 q-mt-lg q-mb-md">Dados Financeiros</div>
|
|
|
-
|
|
|
- <div class="row q-col-gutter-sm">
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.due_day"
|
|
|
- label="Dia de Vencimento"
|
|
|
- type="number"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultCurrencyInput
|
|
|
- v-model="form.enrollment_fee"
|
|
|
- label="Taxa de Matrícula"
|
|
|
- disable
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-4">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.total_classes"
|
|
|
- label="Total de Aulas"
|
|
|
- type="number"
|
|
|
- disable
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-3">
|
|
|
- <DefaultCurrencyInput v-model="form.down_payment" label="Entrada" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-3">
|
|
|
- <DefaultSelect
|
|
|
- v-model="form.installments"
|
|
|
- label="Parcelas"
|
|
|
- :options="installmentOptions"
|
|
|
- option-value="value"
|
|
|
- option-label="label"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-6">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.early_payment_discount"
|
|
|
- label="Desconto até o vencimento (%)"
|
|
|
- type="number"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-3">
|
|
|
- <DefaultCurrencyInput
|
|
|
- v-model="form.material_value"
|
|
|
- label="Valor dos Materiais"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-3">
|
|
|
- <DefaultSelect
|
|
|
- v-model="form.material_installments"
|
|
|
- label="Parcelas"
|
|
|
- :options="installmentOptions"
|
|
|
- option-value="value"
|
|
|
- option-label="label"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-6">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.interest_rate"
|
|
|
- label="Juros (%) a.m"
|
|
|
- type="number"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-6">
|
|
|
- <DefaultSelect
|
|
|
- v-model="form.payment_method"
|
|
|
- label="Forma de Pagamento"
|
|
|
- :options="paymentMethods"
|
|
|
- option-value="value"
|
|
|
- option-label="label"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="col-6">
|
|
|
- <DefaultInput
|
|
|
- v-model="form.late_fee"
|
|
|
- label="Multa (%)"
|
|
|
- type="number"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <div v-if="props.contract" v-show="activeTab === 'midias'">
|
|
|
+ <DefaultTable
|
|
|
+ v-model:rows="files"
|
|
|
+ title="Mídias"
|
|
|
+ :columns="mediaColumns"
|
|
|
+ descricao="mídias"
|
|
|
+ :feminino="true"
|
|
|
+ no-api-call
|
|
|
+ :show-search-field="false"
|
|
|
+ :loading="loadingFiles"
|
|
|
+ >
|
|
|
+ <template #body-cell-actions="{ row }">
|
|
|
+ <q-td align="center">
|
|
|
+ <q-item-section class="no-wrap" style="flex-direction: row; gap: 4px">
|
|
|
+ <q-btn
|
|
|
+ outline
|
|
|
+ icon="mdi-eye-outline"
|
|
|
+ style="width: 36px"
|
|
|
+ @click.prevent.stop="openFile(row.file_url)"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ outline
|
|
|
+ icon="mdi-trash-can-outline"
|
|
|
+ style="width: 36px"
|
|
|
+ color="negative"
|
|
|
+ @click.prevent.stop="handleDeleteMedia(row)"
|
|
|
+ />
|
|
|
+ </q-item-section>
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
+ </DefaultTable>
|
|
|
</div>
|
|
|
</q-card-section>
|
|
|
|
|
|
@@ -264,6 +314,7 @@
|
|
|
@click="onDialogCancel"
|
|
|
/>
|
|
|
<q-btn
|
|
|
+ v-if="activeTab === 'dados'"
|
|
|
color="primary"
|
|
|
label="SALVAR"
|
|
|
:loading="saving"
|
|
|
@@ -276,12 +327,13 @@
|
|
|
|
|
|
<script setup>
|
|
|
import { computed, ref, watch, onMounted } from "vue";
|
|
|
-import { useDialogPluginComponent } from "quasar";
|
|
|
+import { useDialogPluginComponent, useQuasar } from "quasar";
|
|
|
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
|
|
|
import DefaultInput from "src/components/defaults/DefaultInput.vue";
|
|
|
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
|
|
|
import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
|
|
|
import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
|
|
|
+import DefaultTable from "src/components/defaults/DefaultTable.vue";
|
|
|
import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
|
import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
|
|
|
import { formatDateYMDtoDMY, formatDateDMYtoYMD } from "src/helpers/utils";
|
|
|
@@ -290,6 +342,7 @@ import {
|
|
|
createStudentContract,
|
|
|
updateStudentContract,
|
|
|
} from "src/api/studentContract";
|
|
|
+import { getContractMedias, deleteStudentMedia } from "src/api/student_media";
|
|
|
|
|
|
const props = defineProps({
|
|
|
student: {
|
|
|
@@ -307,6 +360,12 @@ defineEmits([...useDialogPluginComponent.emits]);
|
|
|
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
useDialogPluginComponent();
|
|
|
|
|
|
+const $q = useQuasar();
|
|
|
+
|
|
|
+const activeTab = ref("dados");
|
|
|
+const files = ref([]);
|
|
|
+const loadingFiles = ref(false);
|
|
|
+
|
|
|
const trimTime = (t) => (t ? t.slice(0, 5) : null);
|
|
|
|
|
|
const { form } = useFormUpdateTracker({
|
|
|
@@ -355,10 +414,30 @@ const weekdays = [
|
|
|
{ value: 0, label: "Domingo" },
|
|
|
];
|
|
|
|
|
|
+const mediaColumns = [
|
|
|
+ { name: "created_at", label: "Data de Anexo", field: "created_at", align: "left" },
|
|
|
+ { name: "actions", label: "Ações", field: null, align: "center" },
|
|
|
+];
|
|
|
+
|
|
|
const packages = ref([]);
|
|
|
|
|
|
+async function fetchFiles() {
|
|
|
+ if (!props.contract) return;
|
|
|
+ loadingFiles.value = true;
|
|
|
+ try {
|
|
|
+ files.value = await getContractMedias(props.contract.id);
|
|
|
+ } finally {
|
|
|
+ loadingFiles.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
onMounted(async () => {
|
|
|
packages.value = await getUnitPackages();
|
|
|
+ await fetchFiles();
|
|
|
+});
|
|
|
+
|
|
|
+watch(activeTab, (tab) => {
|
|
|
+ if (tab === "midias") fetchFiles();
|
|
|
});
|
|
|
|
|
|
watch(
|
|
|
@@ -409,6 +488,27 @@ function buildPayload() {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+function openFile(url) {
|
|
|
+ window.open(url, "_blank");
|
|
|
+}
|
|
|
+
|
|
|
+function handleDeleteMedia(media) {
|
|
|
+ $q.dialog({
|
|
|
+ title: "Excluir mídia",
|
|
|
+ message: "Deseja excluir esta mídia permanentemente?",
|
|
|
+ ok: { color: "negative", label: "Excluir" },
|
|
|
+ cancel: { color: "primary", outline: true, label: "Cancelar" },
|
|
|
+ }).onOk(async () => {
|
|
|
+ try {
|
|
|
+ await deleteStudentMedia(media.id);
|
|
|
+ files.value = files.value.filter((f) => f.id !== media.id);
|
|
|
+ } catch (e) {
|
|
|
+ console.error(e);
|
|
|
+ $q.notify({ type: "negative", message: "Erro ao excluir mídia." });
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
async function handleSave() {
|
|
|
const payload = buildPayload();
|
|
|
await execute(() =>
|