|
@@ -134,7 +134,10 @@
|
|
|
v-model="form.password_confirmation"
|
|
v-model="form.password_confirmation"
|
|
|
v-model:error="validationErrors.password_confirmation"
|
|
v-model:error="validationErrors.password_confirmation"
|
|
|
:label="$t('auth.confirm_password')"
|
|
:label="$t('auth.confirm_password')"
|
|
|
- :rules="[inputRules.required, inputRules.samePassword(form.password)]"
|
|
|
|
|
|
|
+ :rules="[
|
|
|
|
|
+ inputRules.required,
|
|
|
|
|
+ inputRules.samePassword(form.password),
|
|
|
|
|
+ ]"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
<p class="password-hint">{{ $t("auth.password_hint") }}</p>
|
|
<p class="password-hint">{{ $t("auth.password_hint") }}</p>
|
|
@@ -177,12 +180,16 @@ import {
|
|
|
} from "src/api/firstAccess";
|
|
} from "src/api/firstAccess";
|
|
|
import { getFirstAccessData, clearFirstAccessData } from "./firstAccessStorage";
|
|
import { getFirstAccessData, clearFirstAccessData } from "./firstAccessStorage";
|
|
|
import masks from "src/helpers/masks";
|
|
import masks from "src/helpers/masks";
|
|
|
|
|
+import compressImage from "src/helpers/compressImage";
|
|
|
|
|
|
|
|
import Logo from "src/assets/logo_serprati.svg";
|
|
import Logo from "src/assets/logo_serprati.svg";
|
|
|
import DefaultInput from "src/components/defaults/DefaultInput.vue";
|
|
import DefaultInput from "src/components/defaults/DefaultInput.vue";
|
|
|
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
|
|
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
|
|
|
import DefaultPasswordInput from "src/components/defaults/DefaultPasswordInput.vue";
|
|
import DefaultPasswordInput from "src/components/defaults/DefaultPasswordInput.vue";
|
|
|
|
|
|
|
|
|
|
+const MAX_PHOTO_SIZE_MB = 5;
|
|
|
|
|
+const MAX_PHOTO_SIZE_BYTES = MAX_PHOTO_SIZE_MB * 1024 * 1024;
|
|
|
|
|
+
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const $q = useQuasar();
|
|
const $q = useQuasar();
|
|
|
const { t } = useI18n();
|
|
const { t } = useI18n();
|
|
@@ -218,11 +225,49 @@ const unlockField = (field) => {
|
|
|
lockedFields.value = lockedFields.value.filter((locked) => locked !== field);
|
|
lockedFields.value = lockedFields.value.filter((locked) => locked !== field);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const notifyUnmappedError = (error) => {
|
|
|
|
|
+ const response = error?.response;
|
|
|
|
|
+
|
|
|
|
|
+ if (!response) {
|
|
|
|
|
+ $q.notify({
|
|
|
|
|
+ type: "negative",
|
|
|
|
|
+ timeout: 10000,
|
|
|
|
|
+ message: t("http.errors.no_connection", {
|
|
|
|
|
+ detail: error?.message ?? "erro desconhecido",
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const unmapped = Object.entries(response.data?.errors ?? {})
|
|
|
|
|
+ .filter(([field]) => !(field in form.value))
|
|
|
|
|
+ .map(([field, messages]) => `${field}: ${[messages].flat()[0]}`);
|
|
|
|
|
+
|
|
|
|
|
+ if (unmapped.length) {
|
|
|
|
|
+ $q.notify({
|
|
|
|
|
+ type: "negative",
|
|
|
|
|
+ timeout: 10000,
|
|
|
|
|
+ message: t("http.errors.unexpected", { detail: unmapped.join(" | ") }),
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!response.data?.message && response.status !== 422) {
|
|
|
|
|
+ $q.notify({
|
|
|
|
|
+ type: "negative",
|
|
|
|
|
+ timeout: 10000,
|
|
|
|
|
+ message: t("http.errors.unexpected", {
|
|
|
|
|
+ detail: `HTTP ${response.status}`,
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const {
|
|
const {
|
|
|
loading,
|
|
loading,
|
|
|
validationErrors,
|
|
validationErrors,
|
|
|
execute: submitForm,
|
|
execute: submitForm,
|
|
|
-} = useSubmitHandler({ formRef });
|
|
|
|
|
|
|
+} = useSubmitHandler({ formRef, onError: notifyUnmappedError });
|
|
|
|
|
|
|
|
const prefillRules = {
|
|
const prefillRules = {
|
|
|
name: [inputRules.required],
|
|
name: [inputRules.required],
|
|
@@ -249,13 +294,26 @@ watch(
|
|
|
{ deep: true },
|
|
{ deep: true },
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
-const onPhotoSelected = (event) => {
|
|
|
|
|
|
|
+const onPhotoSelected = async (event) => {
|
|
|
const file = event.target.files?.[0];
|
|
const file = event.target.files?.[0];
|
|
|
event.target.value = "";
|
|
event.target.value = "";
|
|
|
if (!file) return;
|
|
if (!file) return;
|
|
|
|
|
|
|
|
- photoFile.value = file;
|
|
|
|
|
- photoPreview.value = URL.createObjectURL(file);
|
|
|
|
|
|
|
+ const photo = await compressImage(file);
|
|
|
|
|
+
|
|
|
|
|
+ if (photo.size > MAX_PHOTO_SIZE_BYTES) {
|
|
|
|
|
+ const message = t("auth.first_access.photo_too_large", {
|
|
|
|
|
+ size: (photo.size / 1024 / 1024).toFixed(1),
|
|
|
|
|
+ max: MAX_PHOTO_SIZE_MB,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ photoError.value = message;
|
|
|
|
|
+ $q.notify({ type: "negative", message, timeout: 8000 });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ photoFile.value = photo;
|
|
|
|
|
+ photoPreview.value = URL.createObjectURL(photo);
|
|
|
photoError.value = null;
|
|
photoError.value = null;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -284,7 +342,10 @@ const onSubmit = async () => {
|
|
|
$q.notify({ type: "positive", message: t("auth.first_access.success") });
|
|
$q.notify({ type: "positive", message: t("auth.first_access.success") });
|
|
|
router.push({ name: "CarteirinhaPage" });
|
|
router.push({ name: "CarteirinhaPage" });
|
|
|
} catch {
|
|
} catch {
|
|
|
- $q.notify({ type: "positive", message: t("auth.first_access.success_login") });
|
|
|
|
|
|
|
+ $q.notify({
|
|
|
|
|
+ type: "positive",
|
|
|
|
|
+ message: t("auth.first_access.success_login"),
|
|
|
|
|
+ });
|
|
|
router.push({ name: "LoginPage" });
|
|
router.push({ name: "LoginPage" });
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|