Sfoglia il codice sorgente

feat: add login automatico quando o prestador se registra

Gustavo Mantovani 1 settimana fa
parent
commit
af05b4fb28
4 ha cambiato i file con 167 aggiunte e 51 eliminazioni
  1. 33 4
      src/composables/useAuth.js
  2. 90 29
      src/pages/LoginPage.vue
  3. 32 6
      src/router/index.js
  4. 12 12
      src/stores/user.js

+ 33 - 4
src/composables/useAuth.js

@@ -1,7 +1,7 @@
 import api from "src/api";
 import { permissionStore } from "src/stores/permission";
-import { userStore } from "src/stores/user";
 import { useAuthStorage } from "src/composables/useAuthStorage";
+import { userStore } from "src/stores/user";
 
 let refreshPromise = null;
 
@@ -11,17 +11,38 @@ export const useAuth = () => {
   const clearAuthData = async () => {
     userStore().resetUser();
     permissionStore().resetScopes();
+
     await clearRefreshToken();
   };
 
   const setAuthDataFromPayload = async (tokens) => {
     const { access_token, refresh_token, user } = tokens;
-    userStore().user = user;
-    userStore().accessToken = access_token;
+
+    const store = userStore();
+
+    store.setUser(user);
+    store.accessToken = access_token;
+
     await setRefreshToken(refresh_token);
+
+    if (String(user?.type).toUpperCase() === "PROVIDER" && !user?.provider) {
+      await store.fetchUser();
+    }
+
+    if (
+      String(store.user?.type).toUpperCase() === "PROVIDER" &&
+      store.user?.provider?.approval_status !== "accepted"
+    ) {
+      permissionStore().resetScopes();
+
+      return;
+    }
+
     await permissionStore().fetchScopes();
   };
 
+  //
+
   const login = async (email, password) => {
     try {
       const response = await api.post("/login", {
@@ -32,6 +53,7 @@ export const useAuth = () => {
       if (response.status === 200) {
         await setAuthDataFromPayload(response.data.payload);
       }
+
       return response;
     } catch (error) {
       return Promise.reject(error);
@@ -41,15 +63,19 @@ export const useAuth = () => {
   const logout = async () => {
     try {
       const response = await api.post("/logout");
+
       if (response.status === 200) {
         await clearAuthData();
       }
     } catch (error) {
       console.error(error);
+
       await clearAuthData();
     }
   };
 
+  //
+
   const doRefresh = async () => {
     try {
       const refreshToken = await getRefreshToken();
@@ -65,9 +91,11 @@ export const useAuth = () => {
       if (response.status === 200) {
         await setAuthDataFromPayload(response.data.payload);
       }
+
       return response;
     } catch (error) {
       await clearAuthData();
+
       return Promise.reject(error);
     }
   };
@@ -78,14 +106,15 @@ export const useAuth = () => {
         refreshPromise = null;
       });
     }
+
     return refreshPromise;
   };
 
   return {
-    setAuthDataFromPayload,
     clearAuthData,
     login,
     logout,
     refresh,
+    setAuthDataFromPayload,
   };
 };

+ 90 - 29
src/pages/LoginPage.vue

@@ -8,11 +8,20 @@
         class="splash-screen"
         @click="clicked = true"
       >
-        <img class="splash-layer splash-layer--bg" :src="BackgroundLogin" />
-
-        <img class="splash-layer splash-layer--photo" :src="FotoDiarista" />
-
-        <img class="splash-layer splash-layer--logo" :src="LogoLogin" />
+        <img
+          class="splash-layer splash-layer--bg"
+          :src="BackgroundLogin"
+        />
+
+        <img
+          class="splash-layer splash-layer--photo"
+          :src="FotoDiarista"
+        />
+
+        <img
+          class="splash-layer splash-layer--logo"
+          :src="LogoLogin"
+        />
       </div>
 
       <div v-else key="flow" class="flow-screen">
@@ -23,14 +32,18 @@
             color="primary"
             dense
             flat
-            icon="mdi-arrow-left"
             round
+            :aria-label="registrationCompleted ? t('auth.logout') : undefined"
+            :icon="registrationCompleted ? 'mdi-logout' : 'mdi-arrow-left'"
             @click="goBack"
           />
         </div>
 
         <div v-if="!showSubStep" class="flow-logo q-my-xl">
-          <q-img style="max-width: 180px" :src="LogoDiariaCampos" />
+          <q-img
+            style="max-width: 180px"
+            :src="LogoDiariaCampos"
+          />
         </div>
 
         <q-form
@@ -53,9 +66,15 @@
               v-model:phone="phone"
             />
 
-            <LoginStep2Panel v-else-if="steps === 2" v-model:code="code" />
+            <LoginStep2Panel
+              v-else-if="steps === 2"
+              v-model:code="code"
+            />
 
-            <LoginStep3Panel v-else-if="steps === 3" v-model="stepThreeForm" />
+            <LoginStep3Panel
+              v-else-if="steps === 3"
+              v-model="stepThreeForm"
+            />
 
             <LoginStep4Panel
               v-else-if="steps === 4"
@@ -63,9 +82,15 @@
               @update:show-sub-step="showSubStep = $event"
             />
 
-            <LoginStep5Panel v-else-if="steps === 5" v-model="stepFiveForm" />
+            <LoginStep5Panel
+              v-else-if="steps === 5"
+              v-model="stepFiveForm"
+            />
 
-            <LoginStep6Panel v-else-if="steps === 6" v-model="stepSixForm" />
+            <LoginStep6Panel
+              v-else-if="steps === 6"
+              v-model="stepSixForm"
+            />
           </div>
 
           <div v-if="!showSubStep" class="flow-footer">
@@ -86,19 +111,22 @@
         </q-form>
 
         <div v-else class="registration-complete">
-          <q-icon
-            class="q-mb-md"
-            color="positive"
-            name="mdi-check-circle-outline"
-            size="52px"
-          />
+          <div class="registration-complete__card row no-wrap items-start">
+            <q-icon
+              class="registration-complete__icon"
+              name="mdi-clock-time-four-outline"
+              size="32px"
+            />
 
-          <div class="registration-complete__title text-text fontbold">
-            {{ t("provider.login.registration_complete.title") }}
-          </div>
+            <div class="registration-complete__content">
+              <div class="registration-complete__title fontbold">
+                {{ t("provider.login.registration_complete.title") }}
+              </div>
 
-          <div class="registration-complete__message text-grey-7 font12">
-            {{ t("provider.login.registration_complete.message") }}
+              <div class="registration-complete__message font12">
+                {{ t("provider.login.registration_complete.message") }}
+              </div>
+            </div>
           </div>
         </div>
       </div>
@@ -114,6 +142,7 @@ import { useGeocodingApi } from "src/composables/useGeocodingApi";
 import { useI18n } from "vue-i18n";
 import { useQuasar } from "quasar";
 import { useRouter } from "vue-router";
+import { userStore } from "src/stores/user";
 
 import BackgroundLogin from "src/assets/background-login.svg";
 import FotoDiarista from "src/assets/foto_diarista_login.svg";
@@ -128,7 +157,8 @@ import LoginStep6Panel from "src/components/login/LoginStep6Panel.vue";
 
 const $q = useQuasar();
 const router = useRouter();
-const { clearAuthData, setAuthDataFromPayload } = useAuth();
+const user = userStore();
+const { clearAuthData, logout, setAuthDataFromPayload } = useAuth();
 const { geocodeFullAddress } = useGeocodingApi();
 const { t } = useI18n();
 
@@ -211,6 +241,7 @@ const showBackButton = computed(
 
 const goBack = async () => {
   if (registrationCompleted.value) {
+    await logout();
     await resetToLoginStart();
     router.replace({ name: "LoginPage" });
 
@@ -502,6 +533,7 @@ const registerUserAndProvider = async () => {
   const response = await createUserAndProvider(form);
 
   if (response.status >= 200 && response.status < 300) {
+    await setAuthDataFromPayload(response.data.payload);
     registrationCompleted.value = true;
   }
 };
@@ -580,6 +612,18 @@ const validateCurrentStep = async () => {
 };
 
 onMounted(() => {
+  const isPendingProvider =
+    user.accessToken &&
+    String(user.user?.type).toUpperCase() === "PROVIDER" &&
+    user.user?.provider?.approval_status !== "accepted";
+
+  if (isPendingProvider) {
+    registrationCompleted.value = true;
+    clicked.value = true;
+
+    return;
+  }
+
   setTimeout(() => {
     clicked.value = true;
   }, 1500);
@@ -698,18 +742,35 @@ onMounted(() => {
   flex-direction: column;
   align-items: center;
   justify-content: center;
-  padding: 24px 8px 80px;
-  text-align: center;
+  padding: 24px 0 80px;
+  transform: translateY(-64px);
+
+  &__card {
+    width: 100%;
+    max-width: 420px;
+    gap: 14px;
+    padding: 18px;
+    background: #e3efff;
+    border-radius: 12px;
+    color: #6554d9;
+  }
+
+  &__icon {
+    flex: 0 0 auto;
+  }
+
+  &__content {
+    min-width: 0;
+  }
 
   &__title {
-    font-size: 18px;
+    font-size: 16px;
     line-height: 1.25;
-    margin-bottom: 10px;
+    margin-bottom: 6px;
   }
 
   &__message {
-    max-width: 320px;
-    line-height: 1.45;
+    line-height: 1.35;
   }
 }
 </style>

+ 32 - 6
src/router/index.js

@@ -1,16 +1,19 @@
-import { route } from "quasar/wrappers";
 import {
-  createRouter,
   createMemoryHistory,
+  createRouter,
   createWebHistory,
   createWebHashHistory,
 } from "vue-router";
-import routes from "./routes";
+
+import { i18n } from "src/boot/i18n";
 import { Notify } from "quasar";
 import { permissionStore } from "src/stores/permission";
-import { i18n } from "src/boot/i18n";
-import { userStore } from "src/stores/user";
+import { route } from "quasar/wrappers";
 import { useAuth } from "src/composables/useAuth";
+import { userStore } from "src/stores/user";
+
+import routes from "./routes";
+
 /*
  * If not building with SSR mode, you can
  * directly export the Router instantiation;
@@ -36,32 +39,55 @@ export default route(function (/* { store, ssrContext } */) {
     // quasar.conf.js -> build -> publicPath
     history: createHistory(process.env.VUE_ROUTER_BASE),
   });
+
   let refreshed = false;
+
   Router.beforeEach(async (to, from, next) => {
     if (userStore().accessToken == null && !refreshed) {
       try {
         await useAuth().refresh();
       } catch {
         refreshed = true;
+
+        return next({ name: "LoginPage" });
+      }
+    }
+
+    const user = userStore();
+
+    const isPendingProvider =
+      String(user.user?.type).toUpperCase() === "PROVIDER" &&
+      user.user?.provider?.approval_status !== "accepted";
+
+    if (user.accessToken && isPendingProvider) {
+      if (to.name !== "LoginPage") {
         return next({ name: "LoginPage" });
       }
+
+      return next();
     }
-    if (userStore().accessToken) {
+
+    if (user.accessToken) {
       if (to.name == "LoginPage") {
         return next({ name: "DashboardPage" });
       }
     }
+
     if (to.meta.requiredPermission) {
       const { getAccess } = permissionStore();
+
       const permission = getAccess(to.meta.requiredPermission, "view");
+
       if (!permission) {
         Notify.create({
           message: i18n.global.t("validation.permissions.view"),
           type: "negative",
         });
+
         return next(from);
       }
     }
+
     return next();
   });
 

+ 12 - 12
src/stores/user.js

@@ -1,15 +1,15 @@
 import { defineStore } from "pinia";
-import { ref } from "vue";
 import { getUser } from "src/api/user";
+import { ref } from "vue";
 
 export const userStore = defineStore("user", () => {
-  const user = ref(null);
   const accessToken = ref(null);
   const isAdmin = ref(false);
+  const user = ref(null);
 
-  const setUser = (userData) => {
-    user.value = userData;
-    isAdmin.value = userData.type === "admin";
+  const fetchUser = async () => {
+    const response = await getUser();
+    setUser(response);
   };
 
   const resetUser = () => {
@@ -18,17 +18,17 @@ export const userStore = defineStore("user", () => {
     accessToken.value = false;
   };
 
-  const fetchUser = async () => {
-    const response = await getUser();
-    setUser(response);
+  const setUser = (userData) => {
+    user.value = userData;
+    isAdmin.value = String(userData.type).toUpperCase() === "ADMIN";
   };
 
   return {
-    user,
+    accessToken,
     isAdmin,
-    setUser,
-    resetUser,
+    user,
     fetchUser,
-    accessToken,
+    resetUser,
+    setUser,
   };
 });