Ver Fonte

ajustes banner pagamento + version 2.7 + ajuste notificacao

Gustavo Zanatta há 3 dias atrás
pai
commit
b90039f7b3

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
 {
   "name": "diarista-prestador-app",
   "name": "diarista-prestador-app",
-  "version": "2.5",
+  "version": "2.7",
   "lockfileVersion": 3,
   "lockfileVersion": 3,
   "requires": true,
   "requires": true,
   "packages": {
   "packages": {
     "": {
     "": {
       "name": "diarista-prestador-app",
       "name": "diarista-prestador-app",
-      "version": "2.5",
+      "version": "2.7",
       "dependencies": {
       "dependencies": {
         "@bufbuild/protobuf": "^2.5.1",
         "@bufbuild/protobuf": "^2.5.1",
         "@capacitor/browser": "^7.0.5",
         "@capacitor/browser": "^7.0.5",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "diarista-prestador-app",
   "name": "diarista-prestador-app",
-  "version": "2.5",
+  "version": "2.7",
   "description": "Aplicativo para o prestador do Diaria",
   "description": "Aplicativo para o prestador do Diaria",
   "productName": "Diaria Profissional App",
   "productName": "Diaria Profissional App",
   "author": "zntt <zanattagg@gmail.com>",
   "author": "zntt <zanattagg@gmail.com>",

+ 2 - 2
src-capacitor/android/app/build.gradle

@@ -13,8 +13,8 @@ android {
         applicationId "br.com.diarista.provider"
         applicationId "br.com.diarista.provider"
         minSdkVersion rootProject.ext.minSdkVersion
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
-        versionCode 16
-        versionName "2.5"
+        versionCode 18
+        versionName "2.7"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         aaptOptions {
         aaptOptions {
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

+ 12 - 0
src-capacitor/android/app/src/main/java/br/com/diarista/provider/MainActivity.java

@@ -56,10 +56,22 @@ public class MainActivity extends BridgeActivity {
         channel.enableVibration(true);
         channel.enableVibration(true);
         channel.setSound(sound, audioAttributes);
         channel.setSound(sound, audioAttributes);
 
 
+        NotificationChannel defaultChannel = new NotificationChannel(
+                "padrao",
+                "Avisos gerais",
+                NotificationManager.IMPORTANCE_DEFAULT
+        );
+
+        defaultChannel.setDescription("Canal para os demais avisos do aplicativo");
+        defaultChannel.setShowBadge(true);
+        defaultChannel.enableLights(true);
+        defaultChannel.enableVibration(true);
+
         NotificationManager notificationManager =
         NotificationManager notificationManager =
                 getSystemService(NotificationManager.class);
                 getSystemService(NotificationManager.class);
 
 
         notificationManager.createNotificationChannel(channel);
         notificationManager.createNotificationChannel(channel);
+        notificationManager.createNotificationChannel(defaultChannel);
     }
     }
 }
 }
 }
 }

+ 2 - 2
src-capacitor/package-lock.json

@@ -1,12 +1,12 @@
 {
 {
   "name": "diarista-prestador-app",
   "name": "diarista-prestador-app",
-  "version": "2.5",
+  "version": "2.7",
   "lockfileVersion": 3,
   "lockfileVersion": 3,
   "requires": true,
   "requires": true,
   "packages": {
   "packages": {
     "": {
     "": {
       "name": "diarista-prestador-app",
       "name": "diarista-prestador-app",
-      "version": "2.5",
+      "version": "2.7",
       "dependencies": {
       "dependencies": {
         "@capacitor/android": "^7.6.8",
         "@capacitor/android": "^7.6.8",
         "@capacitor/app": "^7.0.0",
         "@capacitor/app": "^7.0.0",

+ 1 - 1
src-capacitor/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "diarista-prestador-app",
   "name": "diarista-prestador-app",
-  "version": "2.5",
+  "version": "2.7",
   "description": "Aplicativo para o prestador do Diaria",
   "description": "Aplicativo para o prestador do Diaria",
   "author": "zntt <zanattagg@gmail.com>",
   "author": "zntt <zanattagg@gmail.com>",
   "private": true,
   "private": true,

+ 51 - 0
src/components/dashboard/DashboardBankAccountIncomplete.vue

@@ -0,0 +1,51 @@
+<template>
+  <div class="incomplete-banner q-mx-md q-mb-md" @click="openBankDataDialog">
+    <div class="row items-center no-wrap q-pa-sm q-px-md">
+      <q-icon name="mdi-alert-outline" size="26px" color="primary" class="q-mr-md" />
+      <div class="col banner-text font12 fontmedium text-primary">
+        {{ $t('provider.dashboard.bank_account_incomplete.title') }}
+      </div>
+      <q-btn
+        unelevated
+        no-caps
+        color="primary"
+        text-color="white"
+        :label="$t('provider.dashboard.bank_account_incomplete.cta')"
+        class="q-ml-sm resolver-btn font9"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useQuasar } from 'quasar';
+import ProfileBankDataDialog from 'src/components/profile/ProfileBankDataDialog.vue';
+
+const $q = useQuasar();
+
+const openBankDataDialog = () => {
+  $q.dialog({ component: ProfileBankDataDialog });
+};
+</script>
+
+<style lang="scss" scoped>
+
+@import "/src/css/quasar.variables.scss";
+
+.incomplete-banner {
+  border-radius: 12px;
+  background: $card-incomplete-bank;
+  cursor: pointer;
+}
+
+.banner-text {
+  line-height: 1.3;
+}
+
+.resolver-btn {
+  border-radius: 20px;
+  padding: 0px 4px;
+  white-space: nowrap;
+  flex-shrink: 0;
+}
+</style>

+ 29 - 0
src/composables/useProviderBankAccount.js

@@ -0,0 +1,29 @@
+import { computed } from "vue";
+import { useProviderApproval } from "src/composables/useProviderApproval";
+import { userStore } from "src/stores/user";
+
+export const useProviderBankAccount = () => {
+  const user = userStore();
+  const { isPendingProvider } = useProviderApproval();
+
+  const hasPrimaryBankAccount = computed(
+    () => user.user?.provider?.has_primary_bank_account === true,
+  );
+
+  const bankAccountStatusKnown = computed(
+    () => typeof user.user?.provider?.has_primary_bank_account === "boolean",
+  );
+
+  const needsBankAccount = computed(
+    () =>
+      bankAccountStatusKnown.value &&
+      !hasPrimaryBankAccount.value &&
+      !isPendingProvider.value,
+  );
+
+  return {
+    bankAccountStatusKnown,
+    hasPrimaryBankAccount,
+    needsBankAccount,
+  };
+};

+ 3 - 0
src/css/quasar.variables.scss

@@ -119,6 +119,9 @@ $status-bg-finished:  #F3F4F6;
 $status-bg-cancelled: #FCE7F3;
 $status-bg-cancelled: #FCE7F3;
 $status-color-finished: #9CA3AF;
 $status-color-finished: #9CA3AF;
 
 
+// Banner de pendencia na dashboard (mesmo tom usado no app do cliente)
+$card-incomplete-bank: #FFD3FF;
+
 // Dark Theme Color Overrides
 // Dark Theme Color Overrides
 // $colors-dark: (
 // $colors-dark: (
 //   // Primary Colors and Variants (Purple - adjusted for dark mode)
 //   // Primary Colors and Variants (Purple - adjusted for dark mode)

+ 4 - 0
src/i18n/locales/en.json

@@ -274,6 +274,10 @@
         "come_back_later": "Please come back later.",
         "come_back_later": "Please come back later.",
         "approved": "Registration approved! Welcome to diária app."
         "approved": "Registration approved! Welcome to diária app."
       },
       },
+      "bank_account_incomplete": {
+        "title": "Register your bank account to receive your payments.",
+        "cta": "Register"
+      },
       "summary": {
       "summary": {
         "welcome": "Hello,",
         "welcome": "Hello,",
         "my_schedules": "My schedules"
         "my_schedules": "My schedules"

+ 4 - 0
src/i18n/locales/es.json

@@ -274,6 +274,10 @@
         "come_back_later": "Por favor, vuelve más tarde.",
         "come_back_later": "Por favor, vuelve más tarde.",
         "approved": "¡Registro aprobado! Bienvenido a diária app."
         "approved": "¡Registro aprobado! Bienvenido a diária app."
       },
       },
+      "bank_account_incomplete": {
+        "title": "Registra tu cuenta bancaria para recibir tus pagos.",
+        "cta": "Registrar"
+      },
       "summary": {
       "summary": {
         "welcome": "Hola,",
         "welcome": "Hola,",
         "my_schedules": "Mis citas"
         "my_schedules": "Mis citas"

+ 4 - 0
src/i18n/locales/pt.json

@@ -274,6 +274,10 @@
         "come_back_later": "Por favor, volte mais tarde.",
         "come_back_later": "Por favor, volte mais tarde.",
         "approved": "Cadastro aprovado! Boas-vindas ao diária app."
         "approved": "Cadastro aprovado! Boas-vindas ao diária app."
       },
       },
+      "bank_account_incomplete": {
+        "title": "Cadastre sua conta bancária para receber seus pagamentos.",
+        "cta": "Cadastrar"
+      },
       "summary": {
       "summary": {
         "welcome": "Olá,",
         "welcome": "Olá,",
         "my_schedules": "Minhas diárias"
         "my_schedules": "Minhas diárias"

+ 31 - 14
src/layouts/MainLayout.vue

@@ -57,11 +57,12 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { computed, onMounted, useTemplateRef, watch } from "vue";
+import { computed, useTemplateRef, watch } from "vue";
 import { useI18n } from "vue-i18n";
 import { useI18n } from "vue-i18n";
 import { useQuasar } from "quasar";
 import { useQuasar } from "quasar";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import { useProviderApproval } from "src/composables/useProviderApproval";
 import { useProviderApproval } from "src/composables/useProviderApproval";
+import { useProviderBankAccount } from "src/composables/useProviderBankAccount";
 import { userStore } from "src/stores/user";
 import { userStore } from "src/stores/user";
 import MissingBankDataDialog from "src/components/profile/MissingBankDataDialog.vue";
 import MissingBankDataDialog from "src/components/profile/MissingBankDataDialog.vue";
 import ProfileBankDataDialog from "src/components/profile/ProfileBankDataDialog.vue";
 import ProfileBankDataDialog from "src/components/profile/ProfileBankDataDialog.vue";
@@ -76,10 +77,13 @@ const { t } = useI18n();
 const $q = useQuasar();
 const $q = useQuasar();
 const user = userStore();
 const user = userStore();
 const { isPendingProvider } = useProviderApproval();
 const { isPendingProvider } = useProviderApproval();
+const { bankAccountStatusKnown, hasPrimaryBankAccount, needsBankAccount } =
+  useProviderBankAccount();
 
 
 let oldValue = route.path;
 let oldValue = route.path;
 
 
 let missingBankDataAlertShown = false;
 let missingBankDataAlertShown = false;
+let checkingMissingBankData = false;
 
 
 const navItems = computed(() => [
 const navItems = computed(() => [
   {
   {
@@ -113,26 +117,37 @@ const scrollAreaHeight = computed(() => {
 });
 });
 
 
 const checkMissingBankData = async () => {
 const checkMissingBankData = async () => {
+  if (checkingMissingBankData) {
+    return;
+  }
+
   if (!user.user?.provider && !user.user?.provider_id) {
   if (!user.user?.provider && !user.user?.provider_id) {
     return;
     return;
   }
   }
 
 
-  // Cadastro em análise não edita dados bancários.
-  if (isPendingProvider.value) {
+  if (isPendingProvider.value || hasPrimaryBankAccount.value) {
     return;
     return;
   }
   }
 
 
-  try {
-    await user.fetchUser();
-  } catch (error) {
-    console.error('Erro ao carregar dados do prestador:', error);
+  if (!bankAccountStatusKnown.value) {
+    checkingMissingBankData = true;
+
+    try {
+      await user.fetchUser();
+    } catch (error) {
+      console.error('Erro ao carregar dados do prestador:', error);
+    } finally {
+      checkingMissingBankData = false;
+    }
+  }
+
+  if (!needsBankAccount.value) {
+    return;
   }
   }
 
 
   openMissingBankDataAlert();
   openMissingBankDataAlert();
 };
 };
 
 
-const hasCompleteBankAccount = () => Boolean(user.user?.provider?.has_primary_bank_account);
-
 const isNavItemActive = (item) => route.name === item.name;
 const isNavItemActive = (item) => route.name === item.name;
 
 
 const openBankDataDialog = () => {
 const openBankDataDialog = () => {
@@ -142,7 +157,7 @@ const openBankDataDialog = () => {
 };
 };
 
 
 const openMissingBankDataAlert = () => {
 const openMissingBankDataAlert = () => {
-  if (missingBankDataAlertShown || hasCompleteBankAccount()) {
+  if (missingBankDataAlertShown || hasPrimaryBankAccount.value) {
     return;
     return;
   }
   }
 
 
@@ -153,6 +168,12 @@ const openMissingBankDataAlert = () => {
   }).onOk(openBankDataDialog);
   }).onOk(openBankDataDialog);
 };
 };
 
 
+watch(
+  () => `${isPendingProvider.value}:${hasPrimaryBankAccount.value}`,
+  () => checkMissingBankData(),
+  { immediate: true },
+);
+
 watch(
 watch(
   () => route.path,
   () => route.path,
   (value) => {
   (value) => {
@@ -163,10 +184,6 @@ watch(
     oldValue = value;
     oldValue = value;
   }
   }
 );
 );
-
-onMounted(() => {
-  checkMissingBankData();
-});
 </script>
 </script>
 <style scoped>
 <style scoped>
 .main-layout {
 .main-layout {

+ 5 - 0
src/pages/dashboard/DashboardPage.vue

@@ -18,6 +18,8 @@
         <DashboardPendingApproval v-if="isPendingProvider" />
         <DashboardPendingApproval v-if="isPendingProvider" />
 
 
         <template v-else>
         <template v-else>
+          <DashboardBankAccountIncomplete v-if="needsBankAccount" />
+
           <DashboardPriceSuggest :data="priceSuggestion" />
           <DashboardPriceSuggest :data="priceSuggestion" />
 
 
           <DashboardTodayServices
           <DashboardTodayServices
@@ -65,9 +67,11 @@ import { useQuasar } from "quasar";
 import { useAuth } from "src/composables/useAuth";
 import { useAuth } from "src/composables/useAuth";
 import { REALTIME_EVENT } from "src/realtime/events";
 import { REALTIME_EVENT } from "src/realtime/events";
 import { useProviderApproval } from "src/composables/useProviderApproval";
 import { useProviderApproval } from "src/composables/useProviderApproval";
+import { useProviderBankAccount } from "src/composables/useProviderBankAccount";
 import { useRealtimeSync } from "src/composables/useRealtime";
 import { useRealtimeSync } from "src/composables/useRealtime";
 import { useRoute, useRouter } from "vue-router";
 import { useRoute, useRouter } from "vue-router";
 
 
+import DashboardBankAccountIncomplete from "src/components/dashboard/DashboardBankAccountIncomplete.vue";
 import DashboardHeaderBar from "src/components/dashboard/DashboardHeaderBar.vue";
 import DashboardHeaderBar from "src/components/dashboard/DashboardHeaderBar.vue";
 import DashboardNextSchedules from "src/components/dashboard/DashboardNextSchedules.vue";
 import DashboardNextSchedules from "src/components/dashboard/DashboardNextSchedules.vue";
 import DashboardOpportunities from "src/components/dashboard/DashboardOpportunities.vue";
 import DashboardOpportunities from "src/components/dashboard/DashboardOpportunities.vue";
@@ -90,6 +94,7 @@ const route = useRoute();
 const { t } = useI18n();
 const { t } = useI18n();
 const { refreshApprovalStatus } = useAuth();
 const { refreshApprovalStatus } = useAuth();
 const { isPendingProvider } = useProviderApproval();
 const { isPendingProvider } = useProviderApproval();
+const { needsBankAccount } = useProviderBankAccount();
 
 
 // Enquanto o cadastro está em análise, reconsulta a aprovação periodicamente
 // Enquanto o cadastro está em análise, reconsulta a aprovação periodicamente
 // para liberar a dashboard completa sem exigir novo login.
 // para liberar a dashboard completa sem exigir novo login.