|
@@ -9,7 +9,7 @@
|
|
|
>
|
|
>
|
|
|
<q-icon
|
|
<q-icon
|
|
|
color="white"
|
|
color="white"
|
|
|
- name="photo_camera"
|
|
|
|
|
|
|
+ name="photo_camera"
|
|
|
size="52px"
|
|
size="52px"
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
@@ -24,11 +24,14 @@
|
|
|
:loading="loadingSelfie"
|
|
:loading="loadingSelfie"
|
|
|
@click="takeSelfie"
|
|
@click="takeSelfie"
|
|
|
/>
|
|
/>
|
|
|
- <div class="text-text text-center font12">{{ t('provider.login.steps.step_4.selfie_hint') }}</div>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <div class="font12 text-center text-text">
|
|
|
|
|
+ {{ t('provider.login.steps.step_4.selfie_hint') }}
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <div class="row items-center q-gutter-x-xs">
|
|
|
|
|
|
|
+ <div class="items-center q-gutter-x-xs row">
|
|
|
<q-icon
|
|
<q-icon
|
|
|
color="positive"
|
|
color="positive"
|
|
|
name="check_circle"
|
|
name="check_circle"
|
|
@@ -66,13 +69,13 @@
|
|
|
@click="takeDocFront"
|
|
@click="takeDocFront"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
- <div class="text-text text-center font12">
|
|
|
|
|
|
|
+ <div class="font12 text-center text-text">
|
|
|
{{ t('provider.login.steps.step_4.document_hint') }}
|
|
{{ t('provider.login.steps.step_4.document_hint') }}
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <div class="row items-center q-gutter-x-xs">
|
|
|
|
|
|
|
+ <div class="items-center q-gutter-x-xs row">
|
|
|
<q-icon
|
|
<q-icon
|
|
|
color="positive"
|
|
color="positive"
|
|
|
name="check_circle"
|
|
name="check_circle"
|
|
@@ -88,7 +91,10 @@
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<Teleport to="body">
|
|
<Teleport to="body">
|
|
|
- <div v-if="showResult" class="fs-overlay">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="showResult"
|
|
|
|
|
+ class="fs-overlay"
|
|
|
|
|
+ >
|
|
|
<div class="fs-result">
|
|
<div class="fs-result">
|
|
|
<q-img
|
|
<q-img
|
|
|
class="q-mb-xl"
|
|
class="q-mb-xl"
|
|
@@ -109,18 +115,21 @@
|
|
|
|
|
|
|
|
<template v-if="resultError">
|
|
<template v-if="resultError">
|
|
|
<q-icon
|
|
<q-icon
|
|
|
- class="q-mt-md"
|
|
|
|
|
- color="negative"
|
|
|
|
|
|
|
+ class="q-mt-md"
|
|
|
|
|
+ color="negative"
|
|
|
name="cancel"
|
|
name="cancel"
|
|
|
size="28px"
|
|
size="28px"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
- <div class="text-primary text-center q-mt-xs q-px-lg font14">
|
|
|
|
|
|
|
+ <div class="font14 q-mt-xs q-px-lg text-center text-primary">
|
|
|
{{ t('provider.login.steps.step_4.error_message') }}
|
|
{{ t('provider.login.steps.step_4.error_message') }}
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
- <div v-else class="text-primary text-center q-mt-md q-px-lg font14">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-else
|
|
|
|
|
+ class="font14 q-mt-md q-px-lg text-center text-primary"
|
|
|
|
|
+ >
|
|
|
{{ resultMessage }}
|
|
{{ resultMessage }}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -131,11 +140,16 @@
|
|
|
padding="14px 48px"
|
|
padding="14px 48px"
|
|
|
rounded
|
|
rounded
|
|
|
style="min-width: 200px"
|
|
style="min-width: 200px"
|
|
|
- :label="resultError ? t('provider.login.steps.step_4.btn_retry') : t('provider.login.steps.step_4.btn_continue')"
|
|
|
|
|
|
|
+ :label="resultError
|
|
|
|
|
+ ? t('provider.login.steps.step_4.btn_retry')
|
|
|
|
|
+ : t('provider.login.steps.step_4.btn_continue')"
|
|
|
@click="closeResult"
|
|
@click="closeResult"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
- <div v-if="!resultError && showDocHint" class="text-grey-6 text-center q-mt-sm font12">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="!resultError && showDocHint"
|
|
|
|
|
+ class="font12 q-mt-sm text-center text-grey-6"
|
|
|
|
|
+ >
|
|
|
{{ t('provider.login.steps.step_4.document_hint_result') }}
|
|
{{ t('provider.login.steps.step_4.document_hint_result') }}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -145,44 +159,54 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { Camera, CameraDirection, CameraResultType, CameraSource } from '@capacitor/camera';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ Camera,
|
|
|
|
|
+ CameraDirection,
|
|
|
|
|
+ CameraResultType,
|
|
|
|
|
+ CameraSource,
|
|
|
|
|
+} from '@capacitor/camera';
|
|
|
import { computed, ref } from 'vue';
|
|
import { computed, ref } from 'vue';
|
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
|
|
|
|
import LogoDiaria from 'src/assets/logo_diaria_campos_login.svg';
|
|
import LogoDiaria from 'src/assets/logo_diaria_campos_login.svg';
|
|
|
|
|
|
|
|
-const { t } = useI18n();
|
|
|
|
|
-
|
|
|
|
|
-const form = defineModel({ type: Object, required: true });
|
|
|
|
|
const emit = defineEmits(['update:show-sub-step']);
|
|
const emit = defineEmits(['update:show-sub-step']);
|
|
|
|
|
|
|
|
-const loadingSelfie = ref(false);
|
|
|
|
|
-const loadingDoc = ref(false);
|
|
|
|
|
|
|
+const form = defineModel({
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
-const showResult = ref(false);
|
|
|
|
|
|
|
+const { t } = useI18n();
|
|
|
|
|
+
|
|
|
|
|
+const loadingDoc = ref(false);
|
|
|
|
|
+const loadingSelfie = ref(false);
|
|
|
const resultError = ref(false);
|
|
const resultError = ref(false);
|
|
|
const resultIcon = ref('photo_camera');
|
|
const resultIcon = ref('photo_camera');
|
|
|
const resultMessage = ref('');
|
|
const resultMessage = ref('');
|
|
|
const showDocHint = ref(false);
|
|
const showDocHint = ref(false);
|
|
|
-
|
|
|
|
|
-// foto de documento frente — aguarda verso antes de fechar
|
|
|
|
|
|
|
+const showResult = ref(false);
|
|
|
const tempDocFrontFile = ref(null);
|
|
const tempDocFrontFile = ref(null);
|
|
|
|
|
|
|
|
-const docDone = computed(() => !!form.value.document_front && !!form.value.document_back);
|
|
|
|
|
|
|
+const docDone = computed(() => (
|
|
|
|
|
+ !!form.value.document_back
|
|
|
|
|
+ && !!form.value.document_front
|
|
|
|
|
+));
|
|
|
|
|
+
|
|
|
const selfieDone = computed(() => !!form.value.selfie);
|
|
const selfieDone = computed(() => !!form.value.selfie);
|
|
|
|
|
|
|
|
const base64ToFile = (base64, filename, mimeType = 'image/jpeg') => {
|
|
const base64ToFile = (base64, filename, mimeType = 'image/jpeg') => {
|
|
|
const byteString = atob(base64);
|
|
const byteString = atob(base64);
|
|
|
-
|
|
|
|
|
const ab = new ArrayBuffer(byteString.length);
|
|
const ab = new ArrayBuffer(byteString.length);
|
|
|
-
|
|
|
|
|
const ia = new Uint8Array(ab);
|
|
const ia = new Uint8Array(ab);
|
|
|
|
|
|
|
|
for (let i = 0; i < byteString.length; i++) {
|
|
for (let i = 0; i < byteString.length; i++) {
|
|
|
ia[i] = byteString.charCodeAt(i);
|
|
ia[i] = byteString.charCodeAt(i);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return new File([ab], filename, { type: mimeType });
|
|
|
|
|
|
|
+ return new File([ab], filename, {
|
|
|
|
|
+ type: mimeType,
|
|
|
|
|
+ });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const closeResult = () => {
|
|
const closeResult = () => {
|
|
@@ -197,76 +221,94 @@ const closeResult = () => {
|
|
|
|
|
|
|
|
const openCamera = async (direction) => {
|
|
const openCamera = async (direction) => {
|
|
|
const photo = await Camera.getPhoto({
|
|
const photo = await Camera.getPhoto({
|
|
|
- resultType: CameraResultType.Base64,
|
|
|
|
|
- source: CameraSource.Camera,
|
|
|
|
|
- quality: 85,
|
|
|
|
|
- direction: direction === 'front' ? CameraDirection.Front : CameraDirection.Rear,
|
|
|
|
|
allowEditing: false,
|
|
allowEditing: false,
|
|
|
|
|
+ direction: direction === 'front'
|
|
|
|
|
+ ? CameraDirection.Front
|
|
|
|
|
+ : CameraDirection.Rear,
|
|
|
|
|
+ quality: 85,
|
|
|
|
|
+ resultType: CameraResultType.Base64,
|
|
|
saveToGallery: false,
|
|
saveToGallery: false,
|
|
|
|
|
+ source: CameraSource.Camera,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- return base64ToFile(photo.base64String.replace(/\s/g, ''), 'photo.jpg', `image/${photo.format}`);
|
|
|
|
|
|
|
+ return base64ToFile(
|
|
|
|
|
+ photo.base64String.replace(/\s/g, ''),
|
|
|
|
|
+ 'photo.jpg',
|
|
|
|
|
+ `image/${photo.format}`,
|
|
|
|
|
+ );
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const takeDocFront = async () => {
|
|
|
|
|
- if (loadingDoc.value) return;
|
|
|
|
|
-
|
|
|
|
|
- loadingDoc.value = true;
|
|
|
|
|
-
|
|
|
|
|
|
|
+const takeDocBack = async () => {
|
|
|
try {
|
|
try {
|
|
|
const file = await openCamera('rear');
|
|
const file = await openCamera('rear');
|
|
|
|
|
|
|
|
- tempDocFrontFile.value = file;
|
|
|
|
|
|
|
+ form.value.document_back = file;
|
|
|
|
|
+ form.value.document_front = tempDocFrontFile.value;
|
|
|
|
|
+ resultError.value = false;
|
|
|
|
|
+ resultIcon.value = 'mdi-card-account-details-outline';
|
|
|
|
|
+ resultMessage.value = t('provider.login.steps.step_4.document_success');
|
|
|
|
|
+ showDocHint.value = true;
|
|
|
|
|
+ showResult.value = true;
|
|
|
|
|
+ tempDocFrontFile.value = null;
|
|
|
|
|
|
|
|
- await takeDocBack();
|
|
|
|
|
|
|
+ emit('update:show-sub-step', true);
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
const msg = (err?.message || '').toLowerCase();
|
|
const msg = (err?.message || '').toLowerCase();
|
|
|
|
|
|
|
|
- if (!msg.includes('cancel') && !msg.includes('dismiss') && !msg.includes('no image')) {
|
|
|
|
|
- resultIcon.value = 'mdi-card-account-details-outline';
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ !msg.includes('cancel')
|
|
|
|
|
+ && !msg.includes('dismiss')
|
|
|
|
|
+ && !msg.includes('no image')
|
|
|
|
|
+ ) {
|
|
|
resultError.value = true;
|
|
resultError.value = true;
|
|
|
|
|
+ resultIcon.value = 'mdi-card-account-details-outline';
|
|
|
showDocHint.value = false;
|
|
showDocHint.value = false;
|
|
|
showResult.value = true;
|
|
showResult.value = true;
|
|
|
|
|
|
|
|
emit('update:show-sub-step', true);
|
|
emit('update:show-sub-step', true);
|
|
|
}
|
|
}
|
|
|
- } finally {
|
|
|
|
|
- loadingDoc.value = false;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ tempDocFrontFile.value = null;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const takeDocBack = async () => {
|
|
|
|
|
|
|
+const takeDocFront = async () => {
|
|
|
|
|
+ if (loadingDoc.value) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ loadingDoc.value = true;
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
const file = await openCamera('rear');
|
|
const file = await openCamera('rear');
|
|
|
|
|
|
|
|
- form.value.document_front = tempDocFrontFile.value;
|
|
|
|
|
- form.value.document_back = file;
|
|
|
|
|
- tempDocFrontFile.value = null;
|
|
|
|
|
- resultIcon.value = 'mdi-card-account-details-outline';
|
|
|
|
|
- resultMessage.value = t('provider.login.steps.step_4.document_success');
|
|
|
|
|
- resultError.value = false;
|
|
|
|
|
- showDocHint.value = true;
|
|
|
|
|
- showResult.value = true;
|
|
|
|
|
|
|
+ tempDocFrontFile.value = file;
|
|
|
|
|
|
|
|
- emit('update:show-sub-step', true);
|
|
|
|
|
|
|
+ await takeDocBack();
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
const msg = (err?.message || '').toLowerCase();
|
|
const msg = (err?.message || '').toLowerCase();
|
|
|
|
|
|
|
|
- if (!msg.includes('cancel') && !msg.includes('dismiss') && !msg.includes('no image')) {
|
|
|
|
|
- resultIcon.value = 'mdi-card-account-details-outline';
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ !msg.includes('cancel')
|
|
|
|
|
+ && !msg.includes('dismiss')
|
|
|
|
|
+ && !msg.includes('no image')
|
|
|
|
|
+ ) {
|
|
|
resultError.value = true;
|
|
resultError.value = true;
|
|
|
|
|
+ resultIcon.value = 'mdi-card-account-details-outline';
|
|
|
showDocHint.value = false;
|
|
showDocHint.value = false;
|
|
|
showResult.value = true;
|
|
showResult.value = true;
|
|
|
|
|
|
|
|
emit('update:show-sub-step', true);
|
|
emit('update:show-sub-step', true);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- tempDocFrontFile.value = null;
|
|
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loadingDoc.value = false;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const takeSelfie = async () => {
|
|
const takeSelfie = async () => {
|
|
|
- if (loadingSelfie.value) return;
|
|
|
|
|
|
|
+ if (loadingSelfie.value) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
loadingSelfie.value = true;
|
|
loadingSelfie.value = true;
|
|
|
|
|
|
|
@@ -274,9 +316,9 @@ const takeSelfie = async () => {
|
|
|
const file = await openCamera('front');
|
|
const file = await openCamera('front');
|
|
|
|
|
|
|
|
form.value.selfie = file;
|
|
form.value.selfie = file;
|
|
|
|
|
+ resultError.value = false;
|
|
|
resultIcon.value = 'photo_camera';
|
|
resultIcon.value = 'photo_camera';
|
|
|
resultMessage.value = t('provider.login.steps.step_4.selfie_success');
|
|
resultMessage.value = t('provider.login.steps.step_4.selfie_success');
|
|
|
- resultError.value = false;
|
|
|
|
|
showDocHint.value = false;
|
|
showDocHint.value = false;
|
|
|
showResult.value = true;
|
|
showResult.value = true;
|
|
|
|
|
|
|
@@ -284,9 +326,13 @@ const takeSelfie = async () => {
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
const msg = (err?.message || '').toLowerCase();
|
|
const msg = (err?.message || '').toLowerCase();
|
|
|
|
|
|
|
|
- if (!msg.includes('cancel') && !msg.includes('dismiss') && !msg.includes('no image')) {
|
|
|
|
|
- resultIcon.value = 'photo_camera';
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ !msg.includes('cancel')
|
|
|
|
|
+ && !msg.includes('dismiss')
|
|
|
|
|
+ && !msg.includes('no image')
|
|
|
|
|
+ ) {
|
|
|
resultError.value = true;
|
|
resultError.value = true;
|
|
|
|
|
+ resultIcon.value = 'photo_camera';
|
|
|
showDocHint.value = false;
|
|
showDocHint.value = false;
|
|
|
showResult.value = true;
|
|
showResult.value = true;
|
|
|
|
|
|
|
@@ -309,15 +355,17 @@ const takeSelfie = async () => {
|
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
|
transition: transform 0.15s ease;
|
|
transition: transform 0.15s ease;
|
|
|
|
|
|
|
|
- &:active { transform: scale(0.95); }
|
|
|
|
|
-
|
|
|
|
|
- &--pending {
|
|
|
|
|
- background-color: rgba(139, 92, 246, 0.18);
|
|
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ transform: scale(0.95);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
&--done {
|
|
&--done {
|
|
|
background: linear-gradient(-90deg, #ec48d1 5%, #6b11cb 65%, #2574fc 100%);
|
|
background: linear-gradient(-90deg, #ec48d1 5%, #6b11cb 65%, #2574fc 100%);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ &--pending {
|
|
|
|
|
+ background-color: rgba(139, 92, 246, 0.18);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.fs-overlay {
|
|
.fs-overlay {
|
|
@@ -353,4 +401,4 @@ const takeSelfie = async () => {
|
|
|
background-color: rgba(139, 92, 246, 0.18);
|
|
background-color: rgba(139, 92, 246, 0.18);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+</style>
|