Преглед изворни кода

feat: :sparkles: feat (informacoes agendamento) adicionada informacoes do prestador no agendamento

ao realizar um agendamento, adicionada informacoes no dialog do prestador, exibindo idade, genero e tipos de servico

fase:dev | origin:escopo
Gustavo Zanatta пре 1 дан
родитељ
комит
90e0ae7732

+ 5 - 0
src/api/dashboard.js

@@ -16,4 +16,9 @@ export const buscaPrestadores = async ({ name = '', date = '' } = {}) => {
   if (date) params.date = date;
   const { data } = await api.get('/prestadores-busca', { params });
   return data.payload;
+}
+
+export const getPerfilPrestador = async (providerId) => {
+  const { data } = await api.get(`/prestador-perfil/${providerId}`);
+  return data.payload;
 }

+ 118 - 54
src/components/profile/ProfileInfoDialog.vue

@@ -3,28 +3,28 @@
     ref="dialogRef"
     @hide="onDialogHide"
   >
-    <q-card class="provider-dialog">
+    <q-card class="provider-dialog card-border shadow-card bg-surface text-text">
 
       <q-btn
-        flat
-        round
+        class="close-btn"
+        color="grey-7"
         dense
+        flat
         icon="close"
-        class="close-btn"
+        round
         @click="closeDialog"
       />
 
       <q-card-section class="provider-header">
 
         <q-avatar
-          size="72px"
-          color="primary"
-          text-color="white"
           class="provider-avatar"
+          size="72px"
+          :style="avatarColors[(info.provider_id ?? 0) % avatarColors.length]"
         >
           <img
-            v-if="props.provider.provider_photo"
-            :src="props.provider.provider_photo"
+            v-if="photoUrl"
+            :src="photoUrl"
           >
 
           <span
@@ -37,45 +37,55 @@
 
         <div class="provider-info">
 
-          <div class="text-h6 text-weight-bold">
-            {{ props.provider.provider_name }}
+          <div class="font16 fontbold text-text">
+            {{ firstName }}
           </div>
 
-          <div v-if="props.provider.age" class="text-grey-6 text-body2">
-            {{ `${props.provider.age}` }}
-            </div>
+          <div class="font10 fontmedium text-grey-7">
+            {{ info.district ?? "—" }}
+          </div>
+
+          <div
+            v-if="info.age"
+            class="font10 fontmedium text-grey-7"
+          >
+            <span>
+              {{ $t("scheduling_page.provider_info.age", { value: info.age }) }}
+            </span>
 
-          <div class="text-grey-6">
-            {{ props.provider.district }}
+            <span class="q-ml-md">
+              {{ $t("scheduling_page.provider_info.gender", { value: genderLabel }) }}
+            </span>
           </div>
 
+
           <div class="provider-stats">
 
             <div class="row items-center">
               <q-icon
-                color="amber"
+                color="warning"
                 name="mdi-star"
-                size="18px"
+                size="16px"
               />
 
-              <span class="q-ml-xs">
-                {{ props.provider.average_rating }}
+              <span class="font10 fontmedium q-ml-xs">
+                {{ ratingLabel }}
               </span>
 
-              <span class="text-grey q-ml-xs">
-                {{ `(${props.provider.total_reviews})` }}
+              <span class="font10 fontmedium text-grey-7 q-ml-xs">
+                {{ `(${info.total_reviews ?? 0})` }}
               </span>
             </div>
 
             <div class="row items-center">
               <q-icon
-                color="deep-purple"
+                color="secondary"
                 name="mdi-broom"
-                size="18px"
+                size="16px"
               />
 
-              <span class="q-ml-xs">
-                {{ `(${props.provider.total_services})` }}
+              <span class="font10 fontmedium q-ml-xs">
+                {{ `(${info.total_services ?? 0})` }}
               </span>
             </div>
 
@@ -87,36 +97,57 @@
 
       <q-separator />
 
-      <!-- Especialidades -->
+      <div
+        v-if="loading"
+        class="row items-center justify-center q-py-md"
+      >
+        <q-spinner-dots
+          color="primary"
+          size="32px"
+        />
+      </div>
+
       <q-list
-        v-if="props.provider.specialities?.length"
-        dense
+        v-else-if="serviceTypes.length"
         class="q-pa-sm"
+        dense
       >
         <q-item
-          v-for="speciality in props.provider.specialities"
-          :key="speciality.id"
+          v-for="serviceType in serviceTypes"
+          :key="serviceType.id"
         >
           <q-item-section avatar>
             <q-icon
-              name="mdi-check-circle"
-              color="positive"
+              color="primary"
+              name="mdi-check"
             />
           </q-item-section>
 
-          <q-item-section>
-            {{ speciality.description }}
+          <q-item-section class="font12 fontmedium text-text">
+            {{ serviceType.description }}
           </q-item-section>
         </q-item>
       </q-list>
 
+      <div
+        v-else
+        class="text-center text-grey-6 font10 fontmedium q-pa-md"
+      >
+        {{ $t("scheduling_page.provider_info.no_service_types") }}
+      </div>
+
     </q-card>
   </q-dialog>
 </template>
 
 <script setup>
-import { computed } from "vue";
+import { computed, onMounted, ref } from "vue";
 import { useDialogPluginComponent } from "quasar";
+import { avatarColors } from "src/helpers/avatarColors";
+import { getFirstName } from "src/helpers/utils";
+import { getPerfilPrestador } from "src/api/dashboard";
+import { getProfileMediaUrl } from "src/helpers/profileMedia";
+import { useI18n } from "vue-i18n";
 
 const props = defineProps({
   provider: {
@@ -132,21 +163,57 @@ const {
   onDialogHide,
 } = useDialogPluginComponent();
 
+const { t } = useI18n();
+
+const loading = ref(false);
+const info = ref({ ...props.provider });
+
 const closeDialog = () => {
   dialogRef.value.hide();
 };
 
-const initials = computed(() => {
-  if (!props.provider.provider_name) {
-    return "?";
-  }
+const firstName = computed(
+  () => getFirstName(info.value.provider_name) || "—"
+);
+
+const photoUrl = computed(() => getProfileMediaUrl(info.value));
+
+const serviceTypes = computed(() => info.value.service_types ?? []);
+
+const ratingLabel = computed(
+  () => Number(info.value.average_rating ?? 0).toFixed(1)
+);
+
+const genderLabel = computed(() => {
+  if (info.value.gender_label) return info.value.gender_label;
+
+  const gender = info.value.gender;
+  if (!gender) return null;
 
-  return props.provider.provider_name
-    .trim()
-    .split(" ")
-    .slice(0, 2)
-    .map(name => name[0].toUpperCase())
-    .join("");
+  const key = `genders.${gender}`;
+  const label = t(key);
+
+  return label === key ? null : label;
+});
+
+const initials = computed(
+  () => firstName.value.slice(0, 2).toUpperCase() || "?"
+);
+
+onMounted(async () => {
+  const providerId = props.provider?.provider_id ?? props.provider?.id;
+  if (!providerId) return;
+
+  loading.value = true;
+
+  try {
+    const payload = await getPerfilPrestador(providerId);
+    info.value = { ...props.provider, ...payload };
+  } catch (error) {
+    console.error(error);
+  } finally {
+    loading.value = false;
+  }
 });
 </script>
 
@@ -154,7 +221,6 @@ const initials = computed(() => {
 .provider-dialog {
   width: 380px;
   max-width: 95vw;
-  border-radius: 14px;
   overflow: hidden;
 }
 
@@ -162,7 +228,9 @@ const initials = computed(() => {
   display: flex;
   align-items: center;
   gap: 18px;
-  padding: 20px;
+  padding-top: 20px;
+  padding-right: 20px;
+  padding-left: 20px;
 }
 
 .provider-avatar {
@@ -179,14 +247,10 @@ const initials = computed(() => {
   flex: 1;
 }
 
-.provider-info .text-h6 {
-  line-height: 1.2;
-}
-
 .provider-stats {
   display: flex;
   align-items: center;
-  gap: 6px;
+  gap: 10px;
   margin-top: 8px;
 }
 
@@ -200,4 +264,4 @@ const initials = computed(() => {
 .q-list .q-item {
   min-height: 38px;
 }
-</style>
+</style>

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

@@ -748,6 +748,11 @@
   "scheduling_page": {
     "title": "Scheduling",
     "about_provider": "About the professional",
+    "provider_info": {
+      "age": "{value} years old",
+      "gender": "Gender: {value}",
+      "no_service_types": "No service types informed."
+    },
     "schedule_service": "Schedule a service",
     "favorite_added": "Professional added to favorites!",
     "favorite_removed": "Professional removed from favorites.",

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

@@ -745,6 +745,11 @@
   "scheduling_page": {
     "title": "Agendamiento",
     "about_provider": "Sobre el profesional",
+    "provider_info": {
+      "age": "{value} años",
+      "gender": "Género: {value}",
+      "no_service_types": "Ningún tipo de servicio informado."
+    },
     "schedule_service": "Agendar un servicio",
     "favorite_added": "¡Profesional agregado a favoritos!",
     "favorite_removed": "Profesional eliminado de favoritos.",

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

@@ -756,6 +756,11 @@
   "scheduling_page": {
     "title": "Agendamento",
     "about_provider": "Sobre o profissional",
+    "provider_info": {
+      "age": "{value} anos",
+      "gender": "Gênero: {value}",
+      "no_service_types": "Nenhum tipo de serviço informado."
+    },
     "schedule_service": "Agende um serviço",
     "favorite_added": "Diarista adicionado aos favoritos!",
     "favorite_removed": "Diarista removido dos favoritos.",