| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- <template>
- <q-page class="address-completion-page bg-surface">
- <div class="address-completion-inner">
- <q-btn
- class="address-completion-back"
- color="primary"
- dense
- flat
- icon="mdi-arrow-left"
- round
- @click="router.back()"
- />
- <q-form
- ref="addressForm"
- class="address-completion-content"
- >
- <div class="text-text">
- <span class="font14 fontbold">{{ $t("common.terms.document") }}</span>
- </div>
- <q-input
- v-model="form.document"
- class="bg-surface q-mt-sm q-mb-md"
- hide-bottom-space
- input-class="text-text"
- lazy-rules
- no-error-icon
- outlined
- rounded
- :placeholder="$t('common.terms.document')"
- :rules="[inputRules.cpfOrCnpj]"
- />
- <div class="text-text">
- <span class="font14 fontbold">{{ $t("common.terms.phone") }}</span>
- </div>
- <q-input
- v-model="form.phone"
- class="bg-surface q-mt-sm q-mb-md"
- hide-bottom-space
- input-class="text-text"
- lazy-rules
- mask="(##) #####-####"
- no-error-icon
- outlined
- rounded
- :placeholder="$t('common.terms.phone')"
- :rules="[inputRules.required, inputRules.phone]"
- />
- <div class="text-text">
- <span class="font14 fontbold">{{ $t("common.terms.address") }}</span>
- </div>
- <q-input
- :model-value="flowStore.confirmedAddress"
- class="bg-surface q-mt-sm q-mb-md"
- input-class="text-text"
- outlined
- readonly
- rounded
- />
- <div class="row q-col-gutter-sm">
- <div class="col-4">
- <div class="text-text">
- <span class="font14 fontbold">{{
- $t("common.terms.address_number")
- }}</span>
- </div>
- <q-input
- v-model="form.number"
- class="bg-surface q-mt-sm q-mb-md"
- hide-bottom-space
- input-class="text-text"
- lazy-rules
- no-error-icon
- outlined
- placeholder="0000"
- rounded
- :rules="[inputRules.required]"
- />
- </div>
- <div class="col-8">
- <div class="text-text">
- <span class="font14 fontbold">{{
- $t("common.terms.district")
- }}</span>
- </div>
- <q-input
- :model-value="flowStore.confirmedDistrict"
- :rules="[inputRules.required]"
- class="bg-surface q-mt-sm q-mb-md"
- hide-bottom-space
- input-class="text-text"
- lazy-rules
- no-error-icon
- outlined
- readonly
- rounded
- />
- </div>
- </div>
- <div class="row q-col-gutter-sm">
- <div class="col-8">
- <div class="text-text">
- <span class="font14 fontbold">{{ $t("common.terms.city") }}</span>
- </div>
- <q-input
- :model-value="flowStore.confirmedCity"
- :rules="[inputRules.required]"
- class="bg-surface q-mt-sm q-mb-md"
- hide-bottom-space
- input-class="text-text"
- lazy-rules
- no-error-icon
- outlined
- readonly
- rounded
- />
- </div>
- <div class="col-4">
- <div class="text-text">
- <span class="font14 fontbold">
- {{ $t("common.terms.state") }}
- </span>
- </div>
- <q-input
- :model-value="flowStore.confirmedState"
- :rules="[inputRules.required]"
- class="bg-surface q-mt-sm q-mb-md"
- hide-bottom-space
- input-class="text-text"
- lazy-rules
- no-error-icon
- outlined
- readonly
- rounded
- />
- </div>
- </div>
- <q-checkbox
- v-model="form.no_complement"
- class="q-mb-md text-text"
- color="primary"
- keep-color
- :label="$t('auth.no_complement')"
- />
- <template v-if="!form.no_complement">
- <div class="text-text">
- <span class="font14 fontbold">{{ $t("auth.complement") }}</span>
- </div>
- <q-input
- v-model="form.complement"
- class="bg-surface q-mt-sm q-mb-md"
- input-class="text-text"
- outlined
- rounded
- :placeholder="$t('auth.complement_placeholder')"
- />
- </template>
- <div class="text-text">
- <span class="font14 fontbold">{{ $t("auth.address_nickname") }}</span>
- </div>
- <q-input
- v-model="form.nickname"
- class="bg-surface q-mt-sm q-mb-md"
- input-class="text-text"
- outlined
- rounded
- :placeholder="$t('auth.address_nickname_placeholder')"
- />
- <div class="text-text">
- <span class="font14 fontbold">
- {{ $t("auth.address_instructions") }}
- </span>
- </div>
- <q-input
- v-model="form.instructions"
- autogrow
- class="bg-surface q-mt-sm q-mb-md"
- input-class="text-text"
- outlined
- rounded
- rows="3"
- type="textarea"
- />
- <div class="row q-gutter-sm q-mt-xs q-mb-xl">
- <q-chip
- v-for="type in addressTypes"
- :key="type.value"
- :icon="type.icon"
- :icon-selected="type.icon"
- :outline="form.address_type !== type.value"
- :selected="form.address_type === type.value"
- clickable
- color="primary"
- text-color="surface"
- @click="form.address_type = type.value"
- >
- {{ type.label }}
- </q-chip>
- </div>
- </q-form>
- <div class="address-completion-footer">
- <q-btn
- class="full-width"
- color="primary-button"
- padding="14px 16px"
- rounded
- :label="$t('auth.confirm_address')"
- :loading="submitting"
- @click="handleConfirm"
- />
- </div>
- </div>
- </q-page>
- </template>
- <script setup>
- import { computed, onMounted, ref } from "vue";
- import { createUserAndClient } from "src/api/user";
- import { useAuth } from "src/composables/useAuth";
- import { useI18n } from "vue-i18n";
- import { useInputRules } from "src/composables/useInputRules";
- import { useQuasar } from "quasar";
- import { useRegistrationFlowStore } from "src/stores/registrationFlow";
- import { useRouter } from "vue-router";
- const { t } = useI18n();
- const router = useRouter();
- const $q = useQuasar();
- const { setAuthDataFromPayload } = useAuth();
- const { inputRules } = useInputRules();
- const flowStore = useRegistrationFlowStore();
- const addressForm = ref(null);
- const submitting = ref(false);
- const form = ref({
- document: flowStore.document || "",
- number: "",
- no_complement: false,
- complement: "",
- nickname: "",
- instructions: "",
- address_type: "home",
- phone: flowStore.phone || "",
- });
- const addressTypes = computed(() => [
- {
- value: "home",
- label: t("auth.address_type_home"),
- icon: "mdi-home-outline",
- },
- {
- value: "commercial",
- label: t("auth.address_type_commercial"),
- icon: "mdi-office-building-outline",
- },
- {
- value: "other",
- label: t("auth.address_type_other"),
- icon: "mdi-map-marker-outline",
- },
- ]);
- const handleConfirm = async () => {
- const isValid = await addressForm.value?.validate();
- if (!isValid) return;
- if (!form.value.no_complement && !form.value.complement?.trim()) {
- $q.notify({ type: "warning", message: t("auth.complement_required") });
- return;
- }
- submitting.value = true;
- try {
- const payload = {
- email: flowStore.email || undefined,
- phone: form.value.phone,
- document: form.value.document,
- name: flowStore.name || undefined,
- code: flowStore.code,
- zip_code: flowStore.confirmedZipCode || undefined,
- address: flowStore.confirmedAddress || undefined,
- number: form.value.number || undefined,
- district: flowStore.confirmedDistrict || undefined,
- city: flowStore.confirmedCity || undefined,
- state: flowStore.confirmedState || undefined,
- latitude: flowStore.confirmedLat,
- longitude: flowStore.confirmedLng,
- has_complement: !form.value.no_complement,
- complement: form.value.no_complement
- ? null
- : form.value.complement || null,
- nickname: form.value.nickname || null,
- instructions: form.value.instructions || null,
- address_type: form.value.address_type,
- };
- const response = await createUserAndClient(payload);
- if (response.status >= 200 && response.status < 300) {
- await setAuthDataFromPayload(response.data.payload);
- flowStore.clear();
- router.push({ name: "DashboardPage" });
- }
- } catch {
- $q.notify({ type: "negative", message: t("auth.register_error") });
- } finally {
- submitting.value = false;
- }
- };
- onMounted(() => {
- if (!flowStore.hasConfirmedLocation() || !flowStore.hasCredentials()) {
- router.replace({ name: "LoginPage" });
- return;
- }
- form.value.number = flowStore.confirmedNumber || "";
- });
- </script>
- <style lang="scss" scoped>
- .address-completion-page {
- min-height: 100dvh;
- display: flex;
- justify-content: center;
- }
- .address-completion-inner {
- width: 100%;
- max-width: 500px;
- min-height: 100dvh;
- display: flex;
- flex-direction: column;
- padding: 16px 20px;
- }
- .address-completion-back {
- align-self: flex-start;
- margin-bottom: 12px;
- margin-top: env(safe-area-inset-top);
- }
- .address-completion-content {
- flex: 1;
- }
- .address-type-row {
- display: flex;
- gap: 10px;
- flex-wrap: wrap;
- }
- .address-completion-footer {
- padding: 16px 0 calc(12px + env(safe-area-inset-bottom));
- }
- </style>
|