| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- <template>
- <q-page class="login-page bg-surface-dark">
- <Transition name="fade-slide" mode="out-in">
- <div v-if="!clicked" key="splash" class="splash-screen" @click="clicked = true">
- <img :src="BackgroundLogin" class="splash-layer splash-layer--bg" />
- <img :src="FotoDiarista" class="splash-layer splash-layer--photo" />
- <img :src="LogoLogin" class="splash-layer splash-layer--logo" />
- </div>
- <div v-else-if="steps === 4" key="step4" class="splash-screen">
- <img :src="BackgroundLogin" class="splash-layer splash-layer--bg" />
- <img :src="FotoDiarista" class="splash-layer splash-layer--photo" />
- <img :src="LogoLogin" class="splash-layer splash-layer--logo-small" />
- <div class="step4-card-wrapper">
- <LoginStepFourPanel
- @back="steps = 3"
- @cep-resolved="onCepResolved"
- @device-location="onDeviceLocation"
- />
- </div>
- </div>
- <div v-else key="flow" class="flow-screen">
- <div class="flow-header">
- <q-btn
- v-if="steps === 3"
- flat
- dense
- color="primary"
- :label="$t('auth.register_later')"
- icon-right="mdi-chevron-right-circle-outline"
- class="text-caption"
- @click="steps = 4"
- />
- </div>
- <div class="flow-logo">
- <q-img :src="LogoDiariaCampos" style="max-width: 180px;" />
- </div>
- <q-form
- ref="loginForm"
- class="flow-form"
- autocorrect="off"
- autocapitalize="off"
- autocomplete="off"
- spellcheck="false"
- @submit="onSubmit"
- >
- <div class="flow-content" :class="{ 'flow-content--centered': steps < 3 }">
- <LoginStepOnePanel v-if="steps === 1" v-model:email="email" v-model:phone="phone" />
- <LoginStepTwoPanel v-else-if="steps === 2" v-model:code="code" />
- <LoginStepThreePanel v-else-if="steps === 3" v-model="stepThreeForm" />
- </div>
- <div class="flow-footer">
- <q-btn
- color="primary-button"
- :label="$t('auth.continue')"
- rounded
- padding="14px 16px"
- type="submit"
- class="full-width"
- :loading="submitting"
- >
- <template #loading>
- <q-spinner />
- </template>
- </q-btn>
- </div>
- </q-form>
- </div>
- </Transition>
- </q-page>
- </template>
- <script setup>
- import { ref } from 'vue';
- import { createUserAndClient, sendCode, validateCode } from 'src/api/user';
- import { useAuth } from 'src/composables/useAuth';
- import { useRouter } from 'vue-router';
- import { useRegistrationFlowStore } from 'src/stores/registrationFlow';
- import BackgroundLogin from 'src/assets/background-login.svg';
- import FotoDiarista from 'src/assets/foto_diarista_login.svg';
- import LogoLogin from 'src/assets/logo_diaria_login.svg';
- import LogoDiariaCampos from 'src/assets/logo_diaria_campos_login.svg';
- import LoginStepOnePanel from 'src/components/login/LoginStepOnePanel.vue';
- import LoginStepTwoPanel from 'src/components/login/LoginStepTwoPanel.vue';
- import LoginStepThreePanel from 'src/components/login/LoginStepThreePanel.vue';
- import LoginStepFourPanel from 'src/components/login/LoginStepFourPanel.vue';
- const router = useRouter();
- const { setAuthDataFromPayload } = useAuth();
- const flowStore = useRegistrationFlowStore();
- const email = ref('');
- const phone = ref('');
- const code = ref('');
- const stepThreeForm = ref({
- name: '',
- document: '',
- zip_code: '',
- address: '',
- complement: '',
- nickname: '',
- instructions: '',
- address_type: 'home',
- no_complement: false,
- city: '',
- state: '',
- });
- const steps = ref(1); // 1 = credentials | 2 = code | 3 = user fields | 4 = cep only
- const clicked = ref(false);
- const submitting = ref(false);
- const loginForm = ref(null);
- const isLogin = ref(false);
- const sendValidationCode = async () => {
- const response = await sendCode(email.value, phone.value);
- if (response.status === 201) {
- steps.value = 2;
- } else {
- console.error('Failed to send validation code');
- }
- return response;
- };
- const validateCodeInput = async () => {
- const response = await validateCode(email.value, phone.value, code.value, isLogin.value);
- if (response.status === 200) {
- if(isLogin.value == true) {
- await setAuthDataFromPayload(response.data.payload);
- router.push({ name: 'DashboardPage' });
- } else {
- steps.value = 3;
- }
- } else {
- console.error('Invalid validation code');
- }
- };
- const registerUserAndClient = async () => {
- const payload = {
- ...stepThreeForm.value,
- email: email.value,
- phone: phone.value,
- code: code.value,
- has_complement: !stepThreeForm.value.no_complement,
- };
- // delete payload.no_complement;
- const response = await createUserAndClient(payload);
- if (response.status === 200) {
- await setAuthDataFromPayload(response.data.payload);
- router.push({ name: 'DashboardPage' });
- } else {
- console.error('Failed to create user and client');
- }
- };
- const navigateToMap = (lat, lng) => {
- flowStore.setCredentials(email.value, phone.value, code.value);
- flowStore.setInitialLocation(lat, lng);
- router.push({ name: 'LocationMapPage' });
- };
- const onCepResolved = (geoData) => {
- navigateToMap(geoData.lat, geoData.lng);
- };
- const onDeviceLocation = ({ lat, lng }) => {
- navigateToMap(lat, lng);
- };
- const onSubmit = async () => {
- switch (steps.value) {
- case 1:
- {
- let response = await sendValidationCode();
- isLogin.value = response.data.payload.isLogin;
- break;
- }
- case 2: await validateCodeInput(); break;
- case 3: await registerUserAndClient(); break;
- default: break;
- }
- };
- </script>
- <style lang="scss" scoped>
- .fade-slide-enter-active,
- .fade-slide-leave-active {
- transition: opacity 0.35s ease, transform 0.35s ease;
- }
- .fade-slide-enter-from { opacity: 0; transform: translateY(6px); }
- .fade-slide-leave-to { opacity: 0; transform: translateY(-6px); }
- .login-page {
- min-height: 100vh;
- display: flex;
- justify-content: center;
- background: var(--q-surface-dark);
- }
- .splash-screen {
- position: relative;
- width: 100vw;
- min-height: 100vh;
- overflow: hidden;
- cursor: pointer;
- .splash-layer {
- position: absolute;
- &--bg {
- inset: 0;
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- &--photo {
- inset: 0;
- width: 100%;
- height: 100%;
- object-fit: cover;
- opacity: 0.15;
- mix-blend-mode: multiply;
- }
- &--logo {
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 180px;
- z-index: 1;
- }
- &--logo-small {
- top: 18%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 100px;
- z-index: 1;
- }
- }
- }
- .step4-card-wrapper {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -30%);
- z-index: 2;
- width: 90%;
- max-width: 360px;
- }
- .flow-screen {
- display: flex;
- flex-direction: column;
- width: 100%;
- max-width: 500px;
- min-height: 100vh;
- padding: 16px 20px;
- background: var(--q-surface-dark);
- }
- .flow-header {
- min-height: 36px;
- display: flex;
- align-items: center;
- justify-content: flex-end;
- }
- .flow-logo {
- display: flex;
- justify-content: center;
- padding: 12px 0 24px;
- }
- .flow-form {
- flex: 1;
- display: flex;
- flex-direction: column;
- }
- .flow-content {
- flex: 1;
- &--centered {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- .flow-footer {
- padding: 20px 0 12px;
- }
- </style>
|