|
@@ -1,3 +1,4 @@
|
|
|
|
|
+<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
|
|
<template>
|
|
<template>
|
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
<q-card class="q-dialog-plugin column full-width" style="width: 900px; max-width: 80vw;height: 90vh;">
|
|
<q-card class="q-dialog-plugin column full-width" style="width: 900px; max-width: 80vw;height: 90vh;">
|
|
@@ -117,10 +118,30 @@
|
|
|
|
|
|
|
|
<div class="col-12 q-mt-md">
|
|
<div class="col-12 q-mt-md">
|
|
|
<div class="row q-col-gutter-md">
|
|
<div class="row q-col-gutter-md">
|
|
|
- <div class="col-auto flex items-center">
|
|
|
|
|
|
|
+ <div class="col-auto flex flex-center column">
|
|
|
<q-avatar size="80px" color="grey-3">
|
|
<q-avatar size="80px" color="grey-3">
|
|
|
- <q-icon name="mdi-account" size="50px" color="grey-6" />
|
|
|
|
|
|
|
+ <img v-if="avatarPreview" :src="avatarPreview" style="object-fit: cover; width: 100%; height: 100%;" />
|
|
|
|
|
+ <q-icon v-else name="mdi-account" size="50px" color="grey-6" />
|
|
|
</q-avatar>
|
|
</q-avatar>
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-if="provider"
|
|
|
|
|
+ ref="fileInputRef"
|
|
|
|
|
+ type="file"
|
|
|
|
|
+ accept="image/jpeg,image/png,image/webp"
|
|
|
|
|
+ style="display: none;"
|
|
|
|
|
+ @change="onFileSelected"
|
|
|
|
|
+ />
|
|
|
|
|
+ <q-btn
|
|
|
|
|
+ v-if="provider"
|
|
|
|
|
+ flat
|
|
|
|
|
+ no-caps
|
|
|
|
|
+ dense
|
|
|
|
|
+ color="primary"
|
|
|
|
|
+ size="sm"
|
|
|
|
|
+ class="q-mt-xs"
|
|
|
|
|
+ label="Alterar foto"
|
|
|
|
|
+ @click="fileInputRef.click()"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="col row q-col-gutter-sm">
|
|
<div class="col row q-col-gutter-sm">
|
|
@@ -156,12 +177,33 @@
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="col-md-6 col-12">
|
|
|
|
|
|
|
+ <div class="col-12">
|
|
|
|
|
|
|
|
<div class="text-subtitle2 text-grey-7 q-mb-sm">
|
|
<div class="text-subtitle2 text-grey-7 q-mb-sm">
|
|
|
{{ $t('provider.fields.document_verified') }}
|
|
{{ $t('provider.fields.document_verified') }}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <div v-if="documentFrontUrl || documentBackUrl" class="row q-col-gutter-sm q-mb-sm">
|
|
|
|
|
+ <div v-if="documentFrontUrl" class="col">
|
|
|
|
|
+ <div class="text-caption text-grey-6 q-mb-xs">Frente</div>
|
|
|
|
|
+ <q-img
|
|
|
|
|
+ :src="documentFrontUrl"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ style="height: 110px; width: 300px; object-fit: contain;border-radius: 6px; cursor: pointer;"
|
|
|
|
|
+ @click="docLightbox = documentFrontUrl"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-if="documentBackUrl" class="col">
|
|
|
|
|
+ <div class="text-caption text-grey-6 q-mb-xs">Verso</div>
|
|
|
|
|
+ <q-img
|
|
|
|
|
+ :src="documentBackUrl"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ style="height: 110px; width: 300px; object-fit: contain;border-radius: 6px; cursor: pointer;"
|
|
|
|
|
+ @click="docLightbox = documentBackUrl"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<q-checkbox
|
|
<q-checkbox
|
|
|
v-model="form.document_verified"
|
|
v-model="form.document_verified"
|
|
|
label="Validar documentos"
|
|
label="Validar documentos"
|
|
@@ -186,7 +228,7 @@
|
|
|
type="submit"
|
|
type="submit"
|
|
|
unelevated
|
|
unelevated
|
|
|
:loading="loading"
|
|
:loading="loading"
|
|
|
- :disable="!hasUpdatedFields"
|
|
|
|
|
|
|
+ :disable="!hasUpdatedFields && !avatarFile"
|
|
|
/>
|
|
/>
|
|
|
</q-card-actions>
|
|
</q-card-actions>
|
|
|
</q-form>
|
|
</q-form>
|
|
@@ -223,13 +265,20 @@
|
|
|
</div>
|
|
</div>
|
|
|
</q-card>
|
|
</q-card>
|
|
|
</q-dialog>
|
|
</q-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <q-dialog v-model="docLightboxOpen" maximized>
|
|
|
|
|
+ <div class="flex flex-center bg-black" style="height: 100%;" @click="docLightbox = null">
|
|
|
|
|
+ <q-img :src="docLightbox" fit="contain" style="max-height: 100vh; max-width: 100vw;" />
|
|
|
|
|
+ <q-btn flat round icon="mdi-close" color="white" class="absolute-top-right q-ma-sm" @click.stop="docLightbox = null" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </q-dialog>
|
|
|
</template>
|
|
</template>
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, useTemplateRef, onMounted, watch, computed } from "vue";
|
|
import { ref, useTemplateRef, onMounted, watch, computed } from "vue";
|
|
|
import { useInputRules } from "src/composables/useInputRules";
|
|
import { useInputRules } from "src/composables/useInputRules";
|
|
|
import { useDialogPluginComponent } from "quasar";
|
|
import { useDialogPluginComponent } from "quasar";
|
|
|
import { useI18n } from "vue-i18n";
|
|
import { useI18n } from "vue-i18n";
|
|
|
-import { createProvider, updateProvider } from "src/api/provider";
|
|
|
|
|
|
|
+import { createProvider, updateProvider, getProvider } from "src/api/provider";
|
|
|
import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
|
|
import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
|
|
|
import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
|
import { dynamicCpfCnpjMask, validateCpfCnpj, calculateDailyPrices } from "src/helpers/utils";
|
|
import { dynamicCpfCnpjMask, validateCpfCnpj, calculateDailyPrices } from "src/helpers/utils";
|
|
@@ -274,7 +323,17 @@ const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
useDialogPluginComponent();
|
|
useDialogPluginComponent();
|
|
|
|
|
|
|
|
const formRef = useTemplateRef("formRef");
|
|
const formRef = useTemplateRef("formRef");
|
|
|
|
|
+const fileInputRef = useTemplateRef("fileInputRef");
|
|
|
const tab = ref("data");
|
|
const tab = ref("data");
|
|
|
|
|
+const avatarFile = ref(null);
|
|
|
|
|
+const avatarPreview = ref(null);
|
|
|
|
|
+const documentFrontUrl = ref(null);
|
|
|
|
|
+const documentBackUrl = ref(null);
|
|
|
|
|
+const docLightbox = ref(null);
|
|
|
|
|
+const docLightboxOpen = computed({
|
|
|
|
|
+ get: () => !!docLightbox.value,
|
|
|
|
|
+ set: (v) => { if (!v) docLightbox.value = null; },
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
const { form, getUpdatedFields, hasUpdatedFields } = useFormUpdateTracker({
|
|
const { form, getUpdatedFields, hasUpdatedFields } = useFormUpdateTracker({
|
|
|
user_id: provider ? provider?.user_id : null,
|
|
user_id: provider ? provider?.user_id : null,
|
|
@@ -310,9 +369,29 @@ const validateDocument = (val) => {
|
|
|
return validateCpfCnpj(val) || t("validation.rules.cpf") + " / " + t("validation.rules.cnpj");
|
|
return validateCpfCnpj(val) || t("validation.rules.cpf") + " / " + t("validation.rules.cnpj");
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const onFileSelected = (event) => {
|
|
|
|
|
+ const file = event.target.files[0];
|
|
|
|
|
+ if (!file) return;
|
|
|
|
|
+ avatarFile.value = file;
|
|
|
|
|
+ avatarPreview.value = URL.createObjectURL(file);
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const onOKClick = async () => {
|
|
const onOKClick = async () => {
|
|
|
if (provider) {
|
|
if (provider) {
|
|
|
- await submitForm(() => updateProvider(getUpdatedFields.value, provider.id));
|
|
|
|
|
|
|
+ if (avatarFile.value) {
|
|
|
|
|
+ const formData = new FormData();
|
|
|
|
|
+ const fields = getUpdatedFields.value;
|
|
|
|
|
+ Object.entries(fields).forEach(([key, value]) => {
|
|
|
|
|
+ if (value !== null && value !== undefined) {
|
|
|
|
|
+ formData.append(key, String(value));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ formData.append('avatar', avatarFile.value);
|
|
|
|
|
+ formData.append('_method', 'PUT');
|
|
|
|
|
+ await submitForm(() => updateProvider(formData, provider.id, true));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await submitForm(() => updateProvider(getUpdatedFields.value, provider.id));
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
await submitForm(() => createProvider({ ...form }));
|
|
await submitForm(() => createProvider({ ...form }));
|
|
|
}
|
|
}
|
|
@@ -338,6 +417,11 @@ onMounted(async () => {
|
|
|
label: provider.user?.name || "",
|
|
label: provider.user?.name || "",
|
|
|
value: provider.user?.id,
|
|
value: provider.user?.id,
|
|
|
};
|
|
};
|
|
|
|
|
+ avatarPreview.value = provider.profile_media?.url ?? null;
|
|
|
|
|
+
|
|
|
|
|
+ const full = await getProvider(provider.id);
|
|
|
|
|
+ documentFrontUrl.value = full.document_front_media?.url ?? null;
|
|
|
|
|
+ documentBackUrl.value = full.document_back_media?.url ?? null;
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|