| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001 |
- <template>
- <q-dialog ref="dialogRef" @hide="onDialogHide">
- <q-card
- class="q-dialog-plugin dialog-form-card"
- style="width: 100%; max-width: 1100px"
- >
- <DefaultDialogHeader
- title="Cadastrar Aluno"
- @close="onDialogCancel"
- />
- <DefaultForm
- ref="formRef"
- @submit="onOKClick"
- >
- <q-scroll-area
- ref="scrollAreaRef"
- class="dialog-form-scroll"
- >
- <q-card-section class="q-pt-sm">
- <CustomTabComponent
- :active-tab="activeTab"
- :tabs="tabs"
- class="q-mb-md"
- @update:active-tab="handleTabChange"
- />
- <div
- v-show="activeTab === 'student'"
- ref="studentTabRef"
- >
- <q-banner
- v-if="validationErrors.registration_draft_token"
- class="bg-red-1 text-negative q-mb-md"
- rounded
- >
- {{ validationErrors.registration_draft_token }}
- </q-banner>
- <div class="flex justify-center q-mb-md">
- <AvatarImageComponent
- ref="avatarRef"
- @update:file="onAvatarChange"
- />
- </div>
- <div class="row q-col-gutter-sm">
- <DefaultInput
- v-model="form.name"
- class="col-6"
- label="Nome do Aluno"
- :error="!!validationErrors.name"
- :error-message="validationErrors.name"
- :rules="[inputRules.required]"
- />
- <DefaultInputDatePicker
- v-model="form.birthdate"
- class="col-6"
- label="Data de Nascimento"
- :error="!!validationErrors.birth_date"
- :error-message="validationErrors.birth_date"
- :rules="[inputRules.required]"
- />
- <DefaultInput
- v-model="form.cpf"
- class="col-6"
- label="CPF"
- :error="!!validationErrors.document_number"
- :error-message="validationErrors.document_number"
- :mask="masks.Brasil.cpf"
- :rules="[inputRules.cpf]"
- />
- <DefaultSelect
- v-model="form.gender"
- class="col-6"
- emit-value
- label="Gênero"
- map-options
- :error="!!validationErrors.gender"
- :error-message="validationErrors.gender"
- :options="genderOptions"
- />
- <DefaultInput
- v-model="form.email"
- class="col-6"
- label="E-mail"
- type="email"
- :error="!!validationErrors.email"
- :error-message="validationErrors.email"
- :rules="[inputRules.email]"
- />
- <DefaultInput
- v-model="form.phone"
- class="col-6"
- label="Celular com DDD"
- :error="!!validationErrors.phone"
- :error-message="validationErrors.phone"
- :mask="masks.Brasil.celular"
- />
- <DefaultCepInput
- v-model="form.cep"
- class="col-4"
- :error="!!validationErrors.postal_code"
- :error-message="validationErrors.postal_code"
- :rules="[inputRules.cep]"
- @bairro="(value) => (form.neighborhood = value)"
- @cidade="
- (value) =>
- citySelectRef?.selectCityByName(value)
- "
- @rua="(value) => (form.address = value)"
- @uf="
- (value) =>
- stateSelectRef?.selectStateByCode(value)
- "
- />
- <DefaultInput
- v-model="form.address"
- class="col-5"
- label="Endereço"
- :error="!!validationErrors.street"
- :error-message="validationErrors.street"
- />
- <DefaultInput
- v-model="form.address_number"
- class="col-3"
- label="Número"
- :error="!!validationErrors.address_number"
- :error-message="validationErrors.address_number"
- />
- <DefaultInput
- v-model="form.neighborhood"
- class="col-4"
- label="Bairro"
- :error="!!validationErrors.neighborhood"
- :error-message="validationErrors.neighborhood"
- />
- <CitySelect
- ref="citySelectRef"
- v-model="selectedCity"
- class="col-4"
- label="Cidade"
- :error="!!validationErrors.city_id"
- :error-message="validationErrors.city_id"
- :state="selectedState"
- />
- <StateSelect
- ref="stateSelectRef"
- v-model="selectedState"
- class="col-4"
- label="Estado"
- :error="!!validationErrors.state_id"
- :error-message="validationErrors.state_id"
- />
- <DefaultInput
- v-model="form.complement"
- class="col-6"
- label="Complemento"
- :error="!!validationErrors.complement"
- :error-message="validationErrors.complement"
- />
- <DefaultInput
- v-model="form.payer"
- class="col-6"
- label="Pagador"
- :error="!!validationErrors.payer_name"
- :error-message="validationErrors.payer_name"
- />
- <DefaultSelect
- v-model="form.how_found"
- class="col-12"
- emit-value
- label="Como nos conheceu?"
- map-options
- :error="!!validationErrors.how_did_you_know_us"
- :error-message="
- validationErrors.how_did_you_know_us
- "
- :options="howFoundOptions"
- />
- <DefaultInput
- v-model="form.notes"
- autogrow
- class="col-12"
- label="Observações"
- type="textarea"
- :error="!!validationErrors.notes"
- :error-message="validationErrors.notes"
- :input-style="{ minHeight: '120px' }"
- />
- </div>
- </div>
- <div
- v-if="isStudentUnderage"
- v-show="activeTab === 'responsible'"
- ref="responsibleTabRef"
- >
- <q-banner
- class="bg-orange-1 text-orange-10 q-mb-md"
- rounded
- >
- O aluno é menor de 18 anos. Cadastre um responsável para
- concluir.
- </q-banner>
- <div class="row q-col-gutter-sm">
- <DefaultInput
- v-model="responsibleForm.name"
- class="col-6"
- label="Nome"
- :error="!!validationErrors['responsible.name']"
- :error-message="
- validationErrors['responsible.name']
- "
- :rules="
- activeTab === 'responsible'
- ? [inputRules.required]
- : []
- "
- />
- <DefaultInput
- v-model="responsibleForm.degree"
- class="col-6"
- label="Grau de Parentesco"
- :error="!!validationErrors['responsible.degree']"
- :error-message="
- validationErrors['responsible.degree']
- "
- :rules="responsibleRequiredRules"
- />
- <DefaultInputDatePicker
- v-model="responsibleForm.birth_date"
- class="col-4"
- label="Data de Nascimento"
- :error="
- !!validationErrors['responsible.birth_date']
- "
- :error-message="
- validationErrors['responsible.birth_date']
- "
- :rules="responsibleRequiredRules"
- />
- <DefaultInput
- v-model="responsibleForm.cpf"
- class="col-4"
- label="CPF"
- :error="!!validationErrors['responsible.cpf']"
- :error-message="
- validationErrors['responsible.cpf']
- "
- :mask="masks.Brasil.cpf"
- :rules="
- activeTab === 'responsible'
- ? [inputRules.required, inputRules.cpf]
- : []
- "
- />
- <DefaultSelect
- v-model="responsibleForm.gender"
- class="col-4"
- emit-value
- label="Gênero"
- map-options
- :error="!!validationErrors['responsible.gender']"
- :error-message="
- validationErrors['responsible.gender']
- "
- :options="genderOptions"
- />
- <DefaultInput
- v-model="responsibleForm.email"
- class="col-6"
- label="E-mail"
- type="email"
- :error="!!validationErrors['responsible.email']"
- :error-message="
- validationErrors['responsible.email']
- "
- :rules="responsibleEmailRules"
- />
- <DefaultInput
- v-model="responsibleForm.phone"
- class="col-6"
- label="Telefone"
- :error="!!validationErrors['responsible.phone']"
- :error-message="
- validationErrors['responsible.phone']
- "
- :mask="masks.Brasil.celular"
- :rules="responsibleRequiredRules"
- />
- <DefaultCepInput
- v-model="responsibleForm.postal_code"
- class="col-4"
- :error="
- !!validationErrors['responsible.postal_code']
- "
- :error-message="
- validationErrors['responsible.postal_code']
- "
- :rules="responsibleCepRules"
- @bairro="
- (value) =>
- (responsibleForm.neighborhood = value)
- "
- @cidade="
- (value) =>
- responsibleCitySelectRef?.selectCityByName(
- value,
- )
- "
- @rua="
- (value) =>
- (responsibleForm.street = value)
- "
- @uf="
- (value) =>
- responsibleStateSelectRef?.selectStateByCode(
- value,
- )
- "
- />
- <DefaultInput
- v-model="responsibleForm.street"
- class="col-5"
- label="Endereço"
- :error="!!validationErrors['responsible.street']"
- :error-message="
- validationErrors['responsible.street']
- "
- :rules="responsibleRequiredRules"
- />
- <DefaultInput
- v-model="responsibleForm.address_number"
- class="col-3"
- label="Número"
- :error="
- !!validationErrors[
- 'responsible.address_number'
- ]
- "
- :error-message="
- validationErrors[
- 'responsible.address_number'
- ]
- "
- />
- <DefaultInput
- v-model="responsibleForm.neighborhood"
- class="col-4"
- label="Bairro"
- :error="
- !!validationErrors[
- 'responsible.neighborhood'
- ]
- "
- :error-message="
- validationErrors[
- 'responsible.neighborhood'
- ]
- "
- :rules="responsibleRequiredRules"
- />
- <CitySelect
- ref="responsibleCitySelectRef"
- v-model="responsibleSelectedCity"
- class="col-4"
- label="Cidade"
- :error="
- !!validationErrors['responsible.city_id']
- "
- :error-message="
- validationErrors['responsible.city_id']
- "
- :rules="responsibleRequiredRules"
- :state="responsibleSelectedState"
- />
- <StateSelect
- ref="responsibleStateSelectRef"
- v-model="responsibleSelectedState"
- class="col-4"
- label="Estado"
- :error="
- !!validationErrors['responsible.state_id']
- "
- :error-message="
- validationErrors['responsible.state_id']
- "
- :rules="responsibleRequiredRules"
- />
- <DefaultInput
- v-model="responsibleForm.complement"
- class="col-12"
- label="Complemento"
- :error="
- !!validationErrors['responsible.complement']
- "
- :error-message="
- validationErrors['responsible.complement']
- "
- />
- <DefaultInput
- v-model="responsibleForm.notes"
- autogrow
- class="col-12"
- label="Observações"
- type="textarea"
- :error="!!validationErrors['responsible.notes']"
- :error-message="
- validationErrors['responsible.notes']
- "
- :input-style="{ minHeight: '120px' }"
- />
- </div>
- </div>
- </q-card-section>
- </q-scroll-area>
- <q-card-actions
- align="right"
- class="q-px-md q-pb-md"
- >
- <q-btn
- color="primary"
- label="Cancelar"
- no-caps
- outline
- @click="onDialogCancel"
- />
- <q-btn
- color="primary"
- no-caps
- type="submit"
- :label="primaryActionLabel"
- :loading="loading"
- />
- </q-card-actions>
- </DefaultForm>
- </q-card>
- </q-dialog>
- </template>
- <script setup>
- import {
- computed,
- nextTick,
- ref,
- useTemplateRef,
- watch,
- } from "vue";
- import {
- createStudent,
- createStudentRegistrationDraft,
- } from "src/api/student";
- import {
- formatDateDMYtoYMD,
- isUnderage,
- } from "src/helpers/utils";
- import { useDialogPluginComponent } from "quasar";
- import { useInputRules } from "src/composables/useInputRules";
- import { useScroll } from "src/composables/useScroll";
- import { useSubmitHandler } from "src/composables/useSubmitHandler";
- import masks from "src/helpers/masks";
- import DefaultCepInput from "src/components/defaults/DefaultCepInput.vue";
- import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
- import DefaultForm from "src/components/defaults/DefaultForm.vue";
- import DefaultInput from "src/components/defaults/DefaultInput.vue";
- import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
- import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
- import CitySelect from "src/components/selects/CitySelect.vue";
- import StateSelect from "src/components/selects/StateSelect.vue";
- import AvatarImageComponent from "src/components/shared/AvatarImageComponent.vue";
- import CustomTabComponent from "src/components/shared/CustomTabComponent.vue";
- defineEmits([...useDialogPluginComponent.emits]);
- const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
- useDialogPluginComponent();
- const { inputRules } = useInputRules();
- const { scrollToComponent } = useScroll();
- const citySelectRef = useTemplateRef("citySelectRef");
- const formRef = useTemplateRef("formRef");
- const responsibleCitySelectRef = useTemplateRef(
- "responsibleCitySelectRef",
- );
- const responsibleStateSelectRef = useTemplateRef(
- "responsibleStateSelectRef",
- );
- const responsibleTabRef = useTemplateRef("responsibleTabRef");
- const scrollAreaRef = useTemplateRef("scrollAreaRef");
- const stateSelectRef = useTemplateRef("stateSelectRef");
- const studentTabRef = useTemplateRef("studentTabRef");
- const activeTab = ref("student");
- const avatarFile = ref(null);
- const registrationDraftToken = ref(null);
- const responsibleSelectedCity = ref(null);
- const responsibleSelectedState = ref(null);
- const selectedCity = ref(null);
- const selectedState = ref(null);
- const form = ref({
- address: null,
- address_number: null,
- birthdate: null,
- cep: null,
- city_id: null,
- complement: null,
- cpf: null,
- email: null,
- gender: "no_preference",
- how_found: null,
- name: null,
- neighborhood: null,
- notes: null,
- payer: null,
- phone: null,
- state_id: null,
- });
- const responsibleForm = ref({
- address_number: null,
- birth_date: null,
- city_id: null,
- complement: null,
- cpf: null,
- degree: null,
- email: null,
- gender: "no_preference",
- name: null,
- neighborhood: null,
- notes: null,
- phone: null,
- postal_code: null,
- state_id: null,
- street: null,
- });
- const isStudentUnderage = computed(() =>
- isUnderage(form.value.birthdate),
- );
- const responsibleCepRules = computed(() =>
- activeTab.value === "responsible"
- ? [inputRules.required, inputRules.cep]
- : [inputRules.cep],
- );
- const responsibleEmailRules = computed(() =>
- activeTab.value === "responsible"
- ? [inputRules.required, inputRules.email]
- : [inputRules.email],
- );
- const responsibleRequiredRules = computed(() =>
- activeTab.value === "responsible"
- ? [inputRules.required]
- : [],
- );
- const tabs = computed(() => [
- {
- label: "Dados do Aluno",
- name: "student",
- },
- ...(isStudentUnderage.value
- ? [
- {
- label: "Responsável",
- name: "responsible",
- },
- ]
- : []),
- ]);
- const primaryActionLabel = computed(() =>
- isStudentUnderage.value &&
- activeTab.value === "student"
- ? "Próximo"
- : "Cadastrar",
- );
- const genderOptions = [
- {
- label: "Prefiro não informar",
- value: "no_preference",
- },
- {
- label: "Masculino",
- value: "male",
- },
- {
- label: "Feminino",
- value: "female",
- },
- {
- label: "Outro",
- value: "other",
- },
- ];
- const howFoundOptions = [
- {
- label: "Indicação",
- value: "referral",
- },
- {
- label: "Redes Sociais",
- value: "social_media",
- },
- {
- label: "Google",
- value: "google",
- },
- {
- label: "Outro",
- value: "other",
- },
- ];
- const REGISTRATION_DRAFT_TOKEN_STORAGE_KEY =
- "student_registration_draft_token";
- localStorage.removeItem(
- REGISTRATION_DRAFT_TOKEN_STORAGE_KEY,
- );
- const scrollToTabError = async (
- component,
- container,
- options,
- ) => {
- const element = component?.$el ?? component;
- const studentElement =
- studentTabRef.value?.$el ?? studentTabRef.value;
- const responsibleElement =
- responsibleTabRef.value?.$el ??
- responsibleTabRef.value;
- if (studentElement?.contains(element)) {
- await setActiveTab("student");
- } else if (responsibleElement?.contains(element)) {
- await setActiveTab("responsible");
- }
- return scrollToComponent(
- component,
- container,
- options,
- );
- };
- const {
- loading: saving,
- validationErrors: submitValidationErrors,
- execute: executeSubmit,
- } = useSubmitHandler({
- containerRef: scrollAreaRef,
- formRef,
- onSuccess: (student) => {
- clearRegistrationDraftToken();
- onDialogOK(student);
- },
- scrollFn: scrollToTabError,
- });
- const {
- loading: validatingStudent,
- validationErrors: draftValidationErrors,
- execute: executeDraft,
- } = useSubmitHandler({
- containerRef: scrollAreaRef,
- formRef,
- scrollFn: scrollToTabError,
- });
- const loading = computed(
- () => saving.value || validatingStudent.value,
- );
- const validationErrors = computed(() => ({
- ...draftValidationErrors.value,
- ...submitValidationErrors.value,
- }));
- const appendResponsibleToFormData = (formData) => {
- const responsible = buildResponsiblePayload();
- Object.entries(responsible).forEach(([field, value]) => {
- formData.append(
- `responsible[${field}]`,
- value ?? "",
- );
- });
- };
- const appendStudentToFormData = (formData) => {
- const student = buildStudentPayload();
- Object.entries(student).forEach(([field, value]) => {
- formData.append(field, value ?? "");
- });
- };
- const buildPayload = () => {
- if (isStudentUnderage.value) {
- if (avatarFile.value) {
- const formData = new FormData();
- appendStudentToFormData(formData);
- formData.append(
- "registration_draft_token",
- registrationDraftToken.value,
- );
- formData.append("avatar", avatarFile.value);
- appendResponsibleToFormData(formData);
- return formData;
- }
- return {
- ...buildStudentPayload(),
- registration_draft_token:
- registrationDraftToken.value,
- responsible: buildResponsiblePayload(),
- };
- }
- if (avatarFile.value) {
- const formData = new FormData();
- appendStudentToFormData(formData);
- formData.append("avatar", avatarFile.value);
- return formData;
- }
- return buildStudentPayload();
- };
- const buildRegistrationDraftPayload = () => ({
- birth_date: form.value.birthdate
- ? formatDateDMYtoYMD(form.value.birthdate)
- : null,
- document_number: form.value.cpf,
- email: form.value.email || null,
- name: form.value.name,
- registration_draft_token:
- registrationDraftToken.value,
- });
- const buildResponsiblePayload = () => ({
- address_number: responsibleForm.value.address_number,
- birth_date: responsibleForm.value.birth_date
- ? formatDateDMYtoYMD(
- responsibleForm.value.birth_date,
- )
- : null,
- city_id: responsibleForm.value.city_id,
- complement: responsibleForm.value.complement,
- cpf: responsibleForm.value.cpf,
- degree: responsibleForm.value.degree,
- email: responsibleForm.value.email || null,
- gender: responsibleForm.value.gender,
- name: responsibleForm.value.name,
- neighborhood: responsibleForm.value.neighborhood,
- notes: responsibleForm.value.notes,
- phone: responsibleForm.value.phone,
- postal_code: responsibleForm.value.postal_code,
- state_id: responsibleForm.value.state_id,
- street: responsibleForm.value.street,
- });
- const buildStudentPayload = () => ({
- address_number: form.value.address_number,
- birth_date: form.value.birthdate
- ? formatDateDMYtoYMD(form.value.birthdate)
- : null,
- city_id: form.value.city_id,
- complement: form.value.complement,
- document_number: form.value.cpf,
- email: form.value.email || null,
- gender: form.value.gender,
- how_did_you_know_us: form.value.how_found,
- name: form.value.name,
- neighborhood: form.value.neighborhood,
- notes: form.value.notes,
- payer_name: form.value.payer,
- phone: form.value.phone,
- postal_code: form.value.cep,
- state_id: form.value.state_id,
- street: form.value.address,
- });
- const clearRegistrationDraftToken = () => {
- registrationDraftToken.value = null;
- localStorage.removeItem(
- REGISTRATION_DRAFT_TOKEN_STORAGE_KEY,
- );
- };
- const goToResponsible = async () => {
- if (validatingStudent.value) return;
- const createDraft = () =>
- createStudentRegistrationDraft(
- buildRegistrationDraftPayload(),
- );
- let draft;
- try {
- draft = await executeDraft(createDraft);
- } catch (error) {
- const draftTokenError =
- draftValidationErrors.value
- .registration_draft_token;
- if (
- !draftTokenError ||
- !registrationDraftToken.value
- ) {
- throw error;
- }
- clearRegistrationDraftToken();
- draft = await executeDraft(createDraft);
- }
- const nextToken = draft?.registration_draft_token;
- if (
- nextToken &&
- nextToken !== registrationDraftToken.value
- ) {
- saveRegistrationDraftToken(nextToken);
- }
- await setActiveTab("responsible", true);
- };
- const handleTabChange = async (tab) => {
- if (tab === activeTab.value) return;
- if (tab === "responsible") {
- await goToResponsible();
- return;
- }
- await setActiveTab(tab, true);
- };
- const onAvatarChange = (file) => {
- avatarFile.value = file;
- };
- const onOKClick = async () => {
- if (
- isStudentUnderage.value &&
- activeTab.value === "student"
- ) {
- await goToResponsible();
- return;
- }
- await executeSubmit(() =>
- createStudent(buildPayload()),
- );
- };
- const saveRegistrationDraftToken = (token) => {
- registrationDraftToken.value = token;
- localStorage.setItem(
- REGISTRATION_DRAFT_TOKEN_STORAGE_KEY,
- token,
- );
- };
- const setActiveTab = async (
- tab,
- resetScroll = false,
- ) => {
- activeTab.value = tab;
- await nextTick();
- if (resetScroll) {
- scrollAreaRef.value?.setScrollPosition(
- "vertical",
- 0,
- 0,
- );
- }
- };
- watch(selectedState, (state) => {
- form.value.state_id = state?.value ?? null;
- });
- watch(selectedCity, (city) => {
- form.value.city_id = city?.value ?? null;
- });
- watch(responsibleSelectedState, (state) => {
- responsibleForm.value.state_id =
- state?.value ?? null;
- });
- watch(responsibleSelectedCity, (city) => {
- responsibleForm.value.city_id =
- city?.value ?? null;
- });
- watch(isStudentUnderage, (underage) => {
- if (
- !underage &&
- activeTab.value === "responsible"
- ) {
- activeTab.value = "student";
- }
- });
- watch(validationErrors, (errors) => {
- const fields = Object.keys(errors);
- if (
- fields.some(
- (field) => !field.startsWith("responsible"),
- )
- ) {
- activeTab.value = "student";
- return;
- }
- if (
- fields.some((field) =>
- field.startsWith("responsible"),
- )
- ) {
- activeTab.value = "responsible";
- }
- });
- </script>
|