|
@@ -2,175 +2,68 @@
|
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
<q-card
|
|
<q-card
|
|
|
class="q-dialog-plugin overflow-hidden"
|
|
class="q-dialog-plugin overflow-hidden"
|
|
|
- style="width: 900px; max-width: 95vw"
|
|
|
|
|
|
|
+ style="width: 1000px; max-width: 97vw"
|
|
|
>
|
|
>
|
|
|
<DefaultDialogHeader title="Dados do Aluno" @close="onDialogCancel" />
|
|
<DefaultDialogHeader title="Dados do Aluno" @close="onDialogCancel" />
|
|
|
|
|
|
|
|
- <q-form ref="formRef" @submit="onSave">
|
|
|
|
|
- <q-card-section class="q-pt-sm" style="max-height: 65vh; overflow-y: auto">
|
|
|
|
|
- <div class="text-subtitle2 q-mb-sm">Dados do Aluno</div>
|
|
|
|
|
|
|
+ <q-card-section class="q-pt-sm" style="max-height: 75vh; overflow-y: auto">
|
|
|
|
|
+ <CustomTabComponent
|
|
|
|
|
+ v-model:active-tab="currentTab"
|
|
|
|
|
+ :tabs="tabs"
|
|
|
|
|
+ class="q-mb-md"
|
|
|
|
|
+ />
|
|
|
|
|
|
|
|
- <div class="row q-col-gutter-sm">
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.name"
|
|
|
|
|
- label="Nome do aluno"
|
|
|
|
|
- class="col-md-5 col-12"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <div v-show="currentTab === 'profile'">
|
|
|
|
|
+ <StudentDataTab :student="props.student" @saved="onStudentSaved" />
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- <DefaultInputDatePicker
|
|
|
|
|
- v-model="form.birthdate"
|
|
|
|
|
- label="Data de Nascimento"
|
|
|
|
|
- class="col-md-5 col-12"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <div v-show="currentTab === 'responsible'">
|
|
|
|
|
+ <ResponsibleTab :student-id="props.student.id" />
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- <div class="col-md-2 col-12 flex justify-center items-start">
|
|
|
|
|
- <div style="position: relative; display: inline-block">
|
|
|
|
|
- <q-avatar size="72px" color="grey-3">
|
|
|
|
|
- <img v-if="avatarPreview" :src="avatarPreview" />
|
|
|
|
|
- <q-icon v-else name="mdi-account" size="42px" color="grey-6" />
|
|
|
|
|
- </q-avatar>
|
|
|
|
|
- <q-btn
|
|
|
|
|
- round
|
|
|
|
|
- dense
|
|
|
|
|
- color="primary"
|
|
|
|
|
- icon="mdi-camera"
|
|
|
|
|
- size="xs"
|
|
|
|
|
- style="position: absolute; bottom: 0; right: 0"
|
|
|
|
|
- @click="triggerFileInput"
|
|
|
|
|
- />
|
|
|
|
|
- <input
|
|
|
|
|
- ref="fileInputRef"
|
|
|
|
|
- type="file"
|
|
|
|
|
- accept="image/*"
|
|
|
|
|
- style="display: none"
|
|
|
|
|
- @change="onAvatarChange"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div v-show="currentTab === 'contracts'">
|
|
|
|
|
+ <ContractTab />
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.cpf"
|
|
|
|
|
- label="CPF / CNH"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- :mask="masks.Brasil.cpf"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <div v-show="currentTab === 'history'">
|
|
|
|
|
+ <HistoryTab />
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- <DefaultSelect
|
|
|
|
|
- v-model="form.gender"
|
|
|
|
|
- label="Gênero"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- emit-value
|
|
|
|
|
- map-options
|
|
|
|
|
- :options="genderOptions"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <div v-show="currentTab === 'media'">
|
|
|
|
|
+ <MediaTab />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </q-card-section>
|
|
|
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.email"
|
|
|
|
|
- label="E-mail"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <q-separator />
|
|
|
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.phone"
|
|
|
|
|
- label="Celular com DDD"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- :mask="masks.Brasil.celular"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultCepInput
|
|
|
|
|
- v-model="form.cep"
|
|
|
|
|
- class="col-md-3 col-12"
|
|
|
|
|
- :disable="false"
|
|
|
|
|
- @rua="(v) => (form.address = v)"
|
|
|
|
|
- @bairro="(v) => (form.neighborhood = v)"
|
|
|
|
|
- @uf="(v) => stateSelectRef?.selectStateByCode(v)"
|
|
|
|
|
- @numero="() => {}"
|
|
|
|
|
- @complemento="() => {}"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.address"
|
|
|
|
|
- label="Endereço"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.address_number"
|
|
|
|
|
- label="Número"
|
|
|
|
|
- class="col-md-3 col-12"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.neighborhood"
|
|
|
|
|
- label="Bairro"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <StateSelect
|
|
|
|
|
- ref="stateSelectRef"
|
|
|
|
|
- v-model="form.state"
|
|
|
|
|
- label="Estado"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- outlined
|
|
|
|
|
- :initial-id="props.student.state_id ?? null"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.complement"
|
|
|
|
|
- label="Complemento"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.payer"
|
|
|
|
|
- label="Pagador"
|
|
|
|
|
- class="col-md-6 col-12"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultSelect
|
|
|
|
|
- v-model="form.how_found"
|
|
|
|
|
- label="Como nos conheceu?"
|
|
|
|
|
- class="col-12"
|
|
|
|
|
- emit-value
|
|
|
|
|
- map-options
|
|
|
|
|
- :options="howFoundOptions"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <DefaultInput
|
|
|
|
|
- v-model="form.notes"
|
|
|
|
|
- label="Observações"
|
|
|
|
|
- class="col-12"
|
|
|
|
|
- type="textarea"
|
|
|
|
|
- autogrow
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </q-card-section>
|
|
|
|
|
-
|
|
|
|
|
- <q-separator />
|
|
|
|
|
-
|
|
|
|
|
- <q-card-actions align="right">
|
|
|
|
|
- <q-btn outline color="primary" label="CANCELAR" no-caps @click="onDialogCancel" />
|
|
|
|
|
- <q-btn color="primary" label="SALVAR" no-caps type="submit" :loading="loading" />
|
|
|
|
|
- </q-card-actions>
|
|
|
|
|
- </q-form>
|
|
|
|
|
|
|
+ <q-card-actions align="right">
|
|
|
|
|
+ <q-btn outline color="primary" label="FECHAR" no-caps @click="onDialogCancel" />
|
|
|
|
|
+ </q-card-actions>
|
|
|
</q-card>
|
|
</q-card>
|
|
|
</q-dialog>
|
|
</q-dialog>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref, useTemplateRef } from "vue";
|
|
|
|
|
|
|
+import { ref, defineAsyncComponent } from "vue";
|
|
|
import { useDialogPluginComponent } from "quasar";
|
|
import { useDialogPluginComponent } from "quasar";
|
|
|
-
|
|
|
|
|
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
|
|
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 DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
|
|
|
|
|
-import DefaultCepInput from "src/components/defaults/DefaultCepInput.vue";
|
|
|
|
|
-import StateSelect from "src/components/selects/StateSelect.vue";
|
|
|
|
|
-import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
|
|
|
-import { updateStudent } from "src/api/student";
|
|
|
|
|
-import masks from "src/helpers/masks";
|
|
|
|
|
-import { formatDateYMDtoDMY, formatDateDMYtoYMD } from "src/helpers/utils";
|
|
|
|
|
|
|
+import CustomTabComponent from "src/components/shared/CustomTabComponent.vue";
|
|
|
|
|
+
|
|
|
|
|
+const StudentDataTab = defineAsyncComponent(
|
|
|
|
|
+ () => import("src/pages/students/tabs/StudentDataTab.vue"),
|
|
|
|
|
+);
|
|
|
|
|
+const ResponsibleTab = defineAsyncComponent(
|
|
|
|
|
+ () => import("src/pages/students/tabs/ResponsibleTab.vue"),
|
|
|
|
|
+);
|
|
|
|
|
+const ContractTab = defineAsyncComponent(
|
|
|
|
|
+ () => import("src/pages/students/tabs/ContractTab.vue"),
|
|
|
|
|
+);
|
|
|
|
|
+const HistoryTab = defineAsyncComponent(
|
|
|
|
|
+ () => import("src/pages/students/tabs/HistoryTab.vue"),
|
|
|
|
|
+);
|
|
|
|
|
+const MediaTab = defineAsyncComponent(
|
|
|
|
|
+ () => import("src/pages/students/tabs/MediaTab.vue"),
|
|
|
|
|
+);
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
|
student: {
|
|
student: {
|
|
@@ -184,112 +77,17 @@ defineEmits([...useDialogPluginComponent.emits]);
|
|
|
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
useDialogPluginComponent();
|
|
useDialogPluginComponent();
|
|
|
|
|
|
|
|
-const formRef = useTemplateRef("formRef");
|
|
|
|
|
-const fileInputRef = useTemplateRef("fileInputRef");
|
|
|
|
|
-const stateSelectRef = useTemplateRef("stateSelectRef");
|
|
|
|
|
-
|
|
|
|
|
-const avatarPreview = ref(props.student.photo_url ?? null);
|
|
|
|
|
-const avatarFile = ref(null);
|
|
|
|
|
|
|
+const currentTab = ref("profile");
|
|
|
|
|
|
|
|
-const genderOptions = [
|
|
|
|
|
- { label: "Prefiro não informar", value: "no_preference" },
|
|
|
|
|
- { label: "Masculino", value: "male" },
|
|
|
|
|
- { label: "Feminino", value: "female" },
|
|
|
|
|
- { label: "Outro", value: "other" },
|
|
|
|
|
|
|
+const tabs = [
|
|
|
|
|
+ { name: "profile", label: "Perfil do Aluno" },
|
|
|
|
|
+ { name: "responsible", label: "Responsáveis" },
|
|
|
|
|
+ { name: "contracts", label: "Contratos" },
|
|
|
|
|
+ { name: "history", label: "Histórico" },
|
|
|
|
|
+ { name: "media", label: "Mídias" },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
-const howFoundOptions = [
|
|
|
|
|
- { label: "Indicação", value: "referral" },
|
|
|
|
|
- { label: "Redes Sociais", value: "social_media" },
|
|
|
|
|
- { label: "Google", value: "google" },
|
|
|
|
|
- { label: "Outro", value: "other" },
|
|
|
|
|
-];
|
|
|
|
|
-
|
|
|
|
|
-const form = ref({
|
|
|
|
|
- name: props.student.name ?? null,
|
|
|
|
|
- birthdate: props.student.birth_date
|
|
|
|
|
- ? formatDateYMDtoDMY(props.student.birth_date)
|
|
|
|
|
- : null,
|
|
|
|
|
- cpf: props.student.document_number ?? null,
|
|
|
|
|
- gender: props.student.gender ?? "no_preference",
|
|
|
|
|
- email: props.student.email ?? null,
|
|
|
|
|
- phone: props.student.phone ?? null,
|
|
|
|
|
- cep: props.student.postal_code ?? null,
|
|
|
|
|
- address: props.student.street ?? null,
|
|
|
|
|
- address_number: props.student.address_number ?? null,
|
|
|
|
|
- neighborhood: props.student.neighborhood ?? null,
|
|
|
|
|
- state: null,
|
|
|
|
|
- complement: props.student.complement ?? null,
|
|
|
|
|
- payer: props.student.payer_name ?? null,
|
|
|
|
|
- how_found: props.student.how_did_you_know_us ?? null,
|
|
|
|
|
- notes: props.student.notes ?? null,
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-const { loading, execute } = useSubmitHandler({
|
|
|
|
|
- formRef,
|
|
|
|
|
- onSuccess: () => {
|
|
|
|
|
- onDialogOK(true);
|
|
|
|
|
- },
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-function triggerFileInput() {
|
|
|
|
|
- fileInputRef.value?.click();
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-function onAvatarChange(event) {
|
|
|
|
|
- const file = event.target.files[0];
|
|
|
|
|
- if (file) {
|
|
|
|
|
- avatarFile.value = file;
|
|
|
|
|
- avatarPreview.value = URL.createObjectURL(file);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-function buildPayload() {
|
|
|
|
|
- if (avatarFile.value) {
|
|
|
|
|
- const formData = new FormData();
|
|
|
|
|
- formData.append("name", form.value.name ?? "");
|
|
|
|
|
- if (form.value.birthdate) {
|
|
|
|
|
- formData.append("birth_date", formatDateDMYtoYMD(form.value.birthdate));
|
|
|
|
|
- }
|
|
|
|
|
- formData.append("document_number", form.value.cpf ?? "");
|
|
|
|
|
- formData.append("gender", form.value.gender ?? "");
|
|
|
|
|
- formData.append("email", form.value.email ?? "");
|
|
|
|
|
- formData.append("phone", form.value.phone ?? "");
|
|
|
|
|
- formData.append("postal_code", form.value.cep ?? "");
|
|
|
|
|
- formData.append("street", form.value.address ?? "");
|
|
|
|
|
- formData.append("address_number", form.value.address_number ?? "");
|
|
|
|
|
- formData.append("neighborhood", form.value.neighborhood ?? "");
|
|
|
|
|
- if (form.value.state?.value) {
|
|
|
|
|
- formData.append("state_id", form.value.state.value);
|
|
|
|
|
- }
|
|
|
|
|
- formData.append("complement", form.value.complement ?? "");
|
|
|
|
|
- formData.append("payer_name", form.value.payer ?? "");
|
|
|
|
|
- formData.append("how_did_you_know_us", form.value.how_found ?? "");
|
|
|
|
|
- formData.append("notes", form.value.notes ?? "");
|
|
|
|
|
- formData.append("avatar", avatarFile.value);
|
|
|
|
|
- return formData;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return {
|
|
|
|
|
- name: form.value.name,
|
|
|
|
|
- birth_date: form.value.birthdate ? formatDateDMYtoYMD(form.value.birthdate) : null,
|
|
|
|
|
- document_number: form.value.cpf,
|
|
|
|
|
- gender: form.value.gender,
|
|
|
|
|
- email: form.value.email || null,
|
|
|
|
|
- phone: form.value.phone,
|
|
|
|
|
- postal_code: form.value.cep,
|
|
|
|
|
- street: form.value.address,
|
|
|
|
|
- address_number: form.value.address_number,
|
|
|
|
|
- neighborhood: form.value.neighborhood,
|
|
|
|
|
- state_id: form.value.state?.value ?? null,
|
|
|
|
|
- complement: form.value.complement,
|
|
|
|
|
- payer_name: form.value.payer,
|
|
|
|
|
- how_did_you_know_us: form.value.how_found,
|
|
|
|
|
- notes: form.value.notes,
|
|
|
|
|
- };
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-async function onSave() {
|
|
|
|
|
- await execute(() => updateStudent(buildPayload(), props.student.id));
|
|
|
|
|
|
|
+function onStudentSaved() {
|
|
|
|
|
+ onDialogOK(true);
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|