| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- <template>
- <q-dialog ref="dialogRef" @hide="onDialogHide">
- <q-card
- class="q-dialog-plugin overflow-hidden"
- style="width: 860px; max-width: 95vw"
- >
- <DefaultDialogHeader
- :title="partner ? 'Editar Sócio' : 'Adicionar Sócio'"
- @close="onDialogCancel"
- />
- <q-form ref="formRef" @submit="onOKClick">
- <q-card-section class="q-pt-none">
- <div class="column items-center q-mb-md">
- <AvatarImageComponent
- ref="avatarRef"
- @update:file="onAvatarChange"
- />
- </div>
- <div class="row q-col-gutter-sm">
- <DefaultInput
- v-model="form.name"
- label="Nome completo"
- class="col-8"
- outlined
- :rules="[inputRules.required]"
- />
- <DefaultInput
- v-model="form.role"
- label="Função"
- class="col-4"
- outlined
- />
- <DefaultInput
- v-model="form.social_name"
- label="Nome social"
- class="col-6"
- outlined
- />
- <DefaultInput
- v-model="form.cpf"
- label="CPF"
- class="col-3"
- outlined
- :mask="masks.Brasil.cpf"
- :rules="[inputRules.required]"
- />
- <DefaultInput v-model="form.rg" label="RG" class="col-3" outlined />
- <DefaultInput
- v-model="birthDateDisplay"
- label="Data de Nascimento"
- class="col-3"
- outlined
- :mask="masks.Brasil.date"
- placeholder="DD/MM/AAAA"
- />
- <DefaultInput
- v-model="form.participation"
- label="Participação (%)"
- class="col-3"
- outlined
- type="number"
- min="0"
- max="100"
- />
- <DefaultInput
- v-model="form.email"
- label="E-mail"
- class="col-6"
- outlined
- :rules="[inputRules.email]"
- />
- <DefaultInput
- v-model="form.secondary_email"
- label="E-mail Secundário"
- class="col-6"
- outlined
- :rules="[inputRules.email]"
- />
- <DefaultInput
- v-model="form.phone_number"
- label="Telefone"
- class="col-6"
- outlined
- :mask="masks.Brasil.telefone"
- />
- <DefaultInput
- v-model="form.cell_number"
- label="Celular"
- class="col-6"
- outlined
- :mask="masks.Brasil.celular"
- />
- <DefaultCepInput
- v-model="form.postal_code"
- class="col-6"
- outlined
- @rua="form.street = $event"
- @bairro="form.neighborhood = $event"
- @uf="stateSelectRef?.selectStateByCode($event)"
- @cidade="citySelectRef?.selectCityByName($event)"
- />
- <DefaultInput
- v-model="form.street"
- label="Endereço"
- class="col-6"
- outlined
- />
- <DefaultInput
- v-model="form.address_number"
- label="Número"
- class="col-6"
- outlined
- />
- <DefaultInput
- v-model="form.neighborhood"
- label="Bairro"
- class="col-4"
- outlined
- />
- <StateSelect
- ref="stateSelectRef"
- v-model="selectedState"
- label="Estado"
- class="col-4"
- outlined
- />
- <CitySelect
- ref="citySelectRef"
- v-model="selectedCity"
- label="Cidade"
- class="col-4"
- outlined
- :state="selectedState"
- />
- <DefaultInput
- v-model="form.complement"
- label="Complemento"
- class="col-12"
- outlined
- />
- </div>
- </q-card-section>
- <q-card-actions>
- <q-space />
- <q-btn
- outline
- color="negative"
- label="Cancelar"
- @click="onDialogCancel"
- />
- <q-btn
- color="primary-2"
- :label="partner ? 'Salvar' : 'Adicionar'"
- type="submit"
- :loading="loading"
- />
- </q-card-actions>
- </q-form>
- </q-card>
- </q-dialog>
- </template>
- <script setup>
- import { ref, watch, onMounted } from "vue";
- import { useDialogPluginComponent } from "quasar";
- import { useInputRules } from "src/composables/useInputRules";
- import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
- import { useSubmitHandler } from "src/composables/useSubmitHandler";
- import { createPartner, updatePartner } from "src/api/unit_partner";
- import masks from "src/helpers/masks";
- import { formatDateDMYtoYMD, formatDateYMDtoDMY } from "src/helpers/utils";
- import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
- import DefaultInput from "src/components/defaults/DefaultInput.vue";
- import DefaultCepInput from "src/components/defaults/DefaultCepInput.vue";
- import AvatarImageComponent from "src/components/shared/AvatarImageComponent.vue";
- import StateSelect from "src/components/selects/StateSelect.vue";
- import CitySelect from "src/components/selects/CitySelect.vue";
- defineEmits([...useDialogPluginComponent.emits]);
- const { partner, unitId, offlineMode } = defineProps({
- partner: {
- type: Object,
- default: null,
- },
- unitId: {
- type: Number,
- default: null,
- },
- offlineMode: {
- type: Boolean,
- default: false,
- },
- });
- const { inputRules } = useInputRules();
- const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
- useDialogPluginComponent();
- const formRef = ref(null);
- const avatarRef = ref(null);
- const stateSelectRef = ref(null);
- const citySelectRef = ref(null);
- const selectedState = ref(null);
- const selectedCity = ref(null);
- const avatarChanged = ref(false);
- const avatarFile = ref(null);
- // Exibe DD/MM/YYYY para o usuário; form.birth_date armazena YYYY-MM-DD para o backend
- const birthDateDisplay = ref(
- partner?.birth_date ? formatDateYMDtoDMY(partner.birth_date) : null,
- );
- watch(birthDateDisplay, (val) => {
- try {
- form.birth_date = val?.length === 10 ? formatDateDMYtoYMD(val) : null;
- } catch {
- form.birth_date = null;
- }
- });
- const { form, getFormAsFormData } = useFormUpdateTracker({
- unit_id: unitId,
- name: partner?.name ?? null,
- social_name: partner?.social_name ?? null,
- role: partner?.role ?? null,
- cpf: partner?.cpf ?? null,
- rg: partner?.rg ?? null,
- birth_date: partner?.birth_date ?? null,
- participation: partner?.participation ?? null,
- email: partner?.email ?? null,
- secondary_email: partner?.secondary_email ?? null,
- phone_number: partner?.phone_number ?? null,
- cell_number: partner?.cell_number ?? null,
- postal_code: partner?.postal_code ?? null,
- street: partner?.street ?? null,
- address_number: partner?.address_number ?? null,
- neighborhood: partner?.neighborhood ?? null,
- complement: partner?.complement ?? null,
- city_id: partner?.city_id ?? null,
- state_id: partner?.state_id ?? null,
- });
- watch(selectedState, (state) => {
- form.state_id = state?.value ?? null;
- });
- watch(selectedCity, (city) => {
- form.city_id = city?.value ?? null;
- });
- function onAvatarChange(file) {
- avatarChanged.value = true;
- avatarFile.value = file;
- }
- const { loading, execute } = useSubmitHandler({
- formRef,
- onSuccess: (result) => onDialogOK(result),
- });
- async function onOKClick() {
- if (offlineMode) {
- const partnerData = { ...form };
- if (avatarFile.value instanceof File) {
- if (partner?.avatar_url?.startsWith("blob:")) {
- URL.revokeObjectURL(partner.avatar_url);
- }
- partnerData.avatar = avatarFile.value;
- partnerData.avatar_url = URL.createObjectURL(avatarFile.value);
- } else if (partner?.avatar_url) {
- partnerData.avatar_url = partner.avatar_url;
- }
- onDialogOK(partnerData);
- return;
- }
- await execute(() => {
- const formData = getFormAsFormData();
- if (avatarChanged.value) {
- formData.append("avatar", avatarFile.value ?? "");
- }
- if (partner) {
- return updatePartner(partner.id, formData);
- }
- return createPartner(formData);
- });
- }
- onMounted(() => {
- if (!partner) return;
- if (partner.avatar_url) {
- avatarRef.value?.setImageUrl(partner.avatar_url);
- }
- if (partner.state_id) {
- stateSelectRef.value?.selectStateById(partner.state_id);
- }
- if (partner.city_id) {
- citySelectRef.value?.selectCityById(partner.city_id);
- }
- });
- </script>
|