Просмотр исходного кода

ajustes no endereco para ter informacao corretamente sobre todos os campos do endereco

Gustavo Zanatta 1 месяц назад
Родитель
Сommit
28573261a0

+ 62 - 0
src/api/address.js

@@ -0,0 +1,62 @@
+import api from "src/api";
+
+export const getAddresses = async (origin, originId) => {
+  const { data } = await api.get(`/addresses?source=${origin}&source_id=${originId}`);
+  return data.payload;
+};
+
+export const getAddress = async (id) => {
+  const { data } = await api.get(`/addresses/${id}`);
+  return data.payload;
+};
+
+export const createAddress = async (address) => {
+  const { data } = await api.post(`/addresses`, { ...address });
+  return data.payload;
+};
+
+export const updateAddress = async (address, id) => {
+  const { data } = await api.put(`/addresses/${id}`, { ...address });
+  return data.payload;
+};
+
+export const deleteAddress = async (id) => {
+  const { data } = await api.delete(`/addresses/${id}`);
+  return data.payload;
+};
+
+export const searchAddressByCEP = async (cep) => {
+  try {
+    const responseCep = await fetch(`https://viacep.com.br/ws/${cep}/json/`);
+    const data = await responseCep.json();
+
+    if (data.erro) {
+      return null;
+    }
+
+    const response = await api.get('busca-estado-cidade-por-descricao', {
+      params: {
+        stateUf: data.uf,
+        cityName: data.localidade
+      }
+    });
+    
+    return {
+      zip_code: data.cep,
+      address: data.logradouro,
+      district: data.bairro,
+      city_id: response.data.payload.city.value,
+      state_id: response.data.payload.state.value,
+      city: {
+        id: response.data.payload.city.value,
+        name: response.data.payload.city.label
+      },
+      state: {
+        id: response.data.payload.state.value,
+        name: response.data.payload.state.label
+      }
+    };
+  } catch {
+    return null;
+  }
+};

+ 212 - 0
src/components/profile/ProfileAddressDialog.vue

@@ -0,0 +1,212 @@
+<template>
+  <q-dialog ref="dialogRef" persistent maximized transition-show="slide-left" transition-hide="slide-right">
+    <div class="bg-page full-height no-shadow">
+      <div class="row items-center q-px-md q-pt-md q-pb-sm bg-white shadow-profile bg-surface">
+        <q-btn v-close-popup icon="mdi-chevron-left" flat round dense color="primary" />
+        <q-space />
+        <span class="text-subtitle1 text-weight-bold text-primary">{{ $t('profile.address.title') }}</span>
+        <q-space />
+        <div style="width: 32px"></div>
+      </div>
+
+      <q-card-section class="col" >
+        <div class="q-px-md q-pt-lg text-text">
+          <div class="text-h6 text-weight-bold gradient-diarista">{{ $t('profile.address.address_subtitle') }}</div>
+          <div class="text-caption text-grey-7 q-mb-lg">{{ $t('profile.address.address_description') }}</div>
+
+          <q-card class="q-pa-lg bg-white shadow-card" style="border-radius: 25px;" :flat="false">
+            <q-input
+              v-model="search"
+              outlined
+              dense
+              class="q-mb-md bg-white card-border"
+              input-class="text-text"
+              :placeholder="$t('profile.address.search_placeholder')"
+            >
+              <template #append>
+                <q-icon name="mdi-magnify" color="grey-7"/>
+              </template>
+            </q-input>
+
+            <div class="text-weight-bold text-text q-mb-xs">{{ $t('profile.address.cep') }}</div>
+            <q-input
+              v-model="form.zip_code"
+              input-class="text-text"
+              outlined
+              dense
+              mask="#####-###"
+              unmasked-value
+              placeholder="00000-000"
+              class="q-mb-md"
+              @update:model-value="onCepChange"
+            >
+              <template #append>
+                <q-spinner v-if="loadingCep" size="xs" color="primary" />
+              </template>
+            </q-input>
+
+            <div class="text-weight-bold q-mb-xs text-text">{{ $t('profile.address.address_label') }}</div>
+            <q-input 
+              v-model="form.address" 
+              outlined 
+              dense 
+              class="q-mb-md" 
+              input-class="text-text" 
+              :placeholder="$t('profile.address.address_placeholder')"
+            />
+
+            <div class="row q-col-gutter-sm q-mb-md">
+              <div class="col-4">
+                <div class="text-weight-bold q-mb-xs text-text">{{ $t('profile.address.number') }}</div>
+                <q-input v-model="form.number" outlined dense input-class="text-text" placeholder="0000"/>
+              </div>
+              <div class="col-8">
+                <div class="text-weight-bold q-mb-xs text-text">{{ $t('profile.address.complement') }}</div>
+                <q-input v-model="form.complement" outlined dense input-class="text-text" :placeholder="$t('profile.address.complement_placeholder')"/>
+              </div>
+            </div>
+
+            <div class="text-weight-bold q-mb-xs text-text">{{ $t('profile.address.district_label') }}</div>
+            <q-input v-model="form.district" outlined dense class="q-mb-md" input-class="text-text"/>
+
+            <div class="row q-col-gutter-sm q-mb-lg">
+              <div class="col-8">
+                <div class="text-weight-bold q-mb-xs text-text">{{ $t('profile.address.city_label') }}</div>
+                <q-input :model-value="form.city?.name" readonly outlined dense input-class="text-text"/>
+              </div>
+              <div class="col-4">
+                <div class="text-weight-bold q-mb-xs text-text">{{ $t('profile.address.state_label') }}</div>
+                <q-input :model-value="form.state?.name" readonly outlined dense input-class="text-text"/>
+              </div>
+            </div>
+
+            <q-btn
+              unelevated
+              rounded
+              no-caps
+              color="primary"
+              class="full-width q-py-md text-weight-bold"
+              padding="8px 16px"
+              style="font-size: 1.1rem;"
+              :label="$t('profile.address.update_address')"
+              :loading="saving"
+              :disable="!hasUpdatedFields"
+              @click="save"
+            />
+          </q-card>
+        </div>
+        <div class="q-pb-xl"></div>
+      </q-card-section>
+    </div>
+  </q-dialog>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue';
+import { useDialogPluginComponent, useQuasar } from 'quasar';
+import { searchAddressByCEP, updateAddress, createAddress, getAddresses } from 'src/api/address';
+import { userStore } from 'src/stores/user';
+import { useFormUpdateTracker } from 'src/composables/useFormUpdateTracker';
+
+defineEmits([...useDialogPluginComponent.emits]);
+
+const { dialogRef, onDialogOK } = useDialogPluginComponent();
+const $q = useQuasar();
+const user = userStore();
+
+const {
+  form,
+  hasUpdatedFields,
+  getUpdatedFields,
+  setUpdateFormAsOriginal,
+} = useFormUpdateTracker({
+  zip_code: '',
+  address: '',
+  number: '',
+  complement: '',
+  district: '',
+  city_id: null,
+  state_id: null,
+  city: null,
+  state: null,
+  source: 'provider',
+  source_id: user.user.id,
+  address_type: 'home',
+});
+
+const search = ref('');
+const loadingCep = ref(false);
+const saving = ref(false);
+const addressId = ref(null);
+
+const onCepChange = async (val) => {
+  if (val?.length === 8) {
+    loadingCep.value = true;
+    try {
+      const data = await searchAddressByCEP(val);
+      if (data) {
+        form.address = data.address;
+        form.district = data.district;
+        form.city_id = data.city_id;
+        form.state_id = data.state_id;
+        form.city = data.city;
+        form.state = data.state;
+      } else {
+        $q.notify({ type: 'negative', message: 'CEP não encontrado' });
+      }
+    } finally {
+      loadingCep.value = false;
+    }
+  }
+};
+
+const save = async () => {
+  saving.value = true;
+  try {
+    let response;
+    if (addressId.value) {
+      response = await updateAddress(getUpdatedFields.value, addressId.value);
+    } else {
+      response = await createAddress({ ...form });
+    }
+
+    if (response) {
+      setUpdateFormAsOriginal();
+      onDialogOK(response);
+    }
+  } catch (error) {
+    console.error('Erro ao salvar endereço:', error);
+  } finally {
+    saving.value = false;
+  }
+};
+
+onMounted(async () => {
+  const providersAddresses = await getAddresses('provider', user.user.id);
+  if (providersAddresses && providersAddresses.length > 0) {
+    const current = providersAddresses[0];
+    addressId.value = current.id;
+
+    const initialData = {
+      zip_code: current.zip_code || '',
+      address: current.address || '',
+      number: current.number || '',
+      complement: current.complement || '',
+      district: current.district || '',
+      city_id: current.city_id || null,
+      state_id: current.state_id || null,
+      city: current.city || null,
+      state: current.state || null,
+      source: 'provider',
+      source_id: user.user.id,
+      address_type: current.address_type || 'home',
+    };
+
+    Object.assign(form, initialData);
+    setUpdateFormAsOriginal();
+  }
+});
+</script>
+
+<style scoped>
+</style>

+ 4 - 0
src/css/app.scss

@@ -139,4 +139,8 @@ box-shadow: 1px 4px 4px 0px rgba(0,0,0,0.2);
 .section-title {
 .section-title {
   font-size: 18px;
   font-size: 18px;
   font-weight: 700;
   font-weight: 700;
+}
+
+.shadow-profile {
+  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.05);
 }
 }

+ 125 - 55
src/i18n/locales/en.json

@@ -165,41 +165,41 @@
           "rg": "RG"
           "rg": "RG"
         },
         },
         "step_4": {
         "step_4": {
-            "document_front": "Side 1 (Front)",
-            "document_front_desc": "Photo of the front of your document (ID or Driver License).",
-            "document_back": "Side 2 (Back)",
-            "document_back_desc": "Photo of the back of your document (ID or Driver License).",
-            "selfie": "Selfie with document",
-            "selfie_desc": "Take a selfie holding your document near your face.",
-            "photo_captured": "Photo captured!",
-            "action": "send documents"
+          "document_front": "Side 1 (Front)",
+          "document_front_desc": "Photo of the front of your document (ID or Driver License).",
+          "document_back": "Side 2 (Back)",
+          "document_back_desc": "Photo of the back of your document (ID or Driver License).",
+          "selfie": "Selfie with document",
+          "selfie_desc": "Take a selfie holding your document near your face.",
+          "photo_captured": "Photo captured!",
+          "action": "send documents"
         },
         },
         "step_5": {
         "step_5": {
-            "daily_price_title": "What is the value of your daily rate for up to 8 hours?",
-            "daily_price_min_max": "Minimum value $ 100.00. Maximum value $ 500.00.",
-            "dont_worry": "Don't worry!",
-            "change_anytime": "You can change your daily rate value whenever you want ;)",
-            "shorter_services": "Based on the value above, the values for shorter services will be:",
-            "up_to_6h": "up to 6 hours",
-            "up_to_4h": "up to 4 hours",
-            "up_to_2h": "up to 2 hours",
-            "other_services": "Besides basic cleaning, what other services do you also perform?",
-            "change_in_profile": "(can be changed in profile)",
-            "no_services": "No service types available at the moment.",
-            "search_visibility": "This information will appear to those searching for your profile in the search.",
-            "action": "continue"
+          "daily_price_title": "What is the value of your daily rate for up to 8 hours?",
+          "daily_price_min_max": "Minimum value $ 100.00. Maximum value $ 500.00.",
+          "dont_worry": "Don't worry!",
+          "change_anytime": "You can change your daily rate value whenever you want ;)",
+          "shorter_services": "Based on the value above, the values for shorter services will be:",
+          "up_to_6h": "up to 6 hours",
+          "up_to_4h": "up to 4 hours",
+          "up_to_2h": "up to 2 hours",
+          "other_services": "Besides basic cleaning, what other services do you also perform?",
+          "change_in_profile": "(can be changed in profile)",
+          "no_services": "No service types available at the moment.",
+          "search_visibility": "This information will appear to those searching for your profile in the search.",
+          "action": "continue"
         },
         },
         "step_6": {
         "step_6": {
-            "title": "Now let's choose the best times for you to receive service requests!",
-            "lock_hint": "Tap and block days or periods",
-            "lock_description": "if you do not wish to receive service requests in this period.",
-            "morning": "morning",
-            "afternoon": "afternoon",
-            "instruction": "To block individual days, click on the day, to block only periods, click on morning or afternoon.",
-            "dont_worry": "Don't worry!",
-            "change_anytime": "Afterwards you can change the availability of your preference at any time in the app ;)",
-            "select_at_least_one": "Select at least one work period.",
-            "action": "finish registration"
+          "title": "Now let's choose the best times for you to receive service requests!",
+          "lock_hint": "Tap and block days or periods",
+          "lock_description": "if you do not wish to receive service requests in this period.",
+          "morning": "morning",
+          "afternoon": "afternoon",
+          "instruction": "To block individual days, click on the day, to block only periods, click on morning or afternoon.",
+          "dont_worry": "Don't worry!",
+          "change_anytime": "Afterwards you can change the availability of your preference at any time in the app ;)",
+          "select_at_least_one": "Select at least one work period.",
+          "action": "finish registration"
         }
         }
       }
       }
     },
     },
@@ -208,6 +208,10 @@
         "welcome": "Hello,",
         "welcome": "Hello,",
         "my_schedules": "My schedules"
         "my_schedules": "My schedules"
       },
       },
+      "price_suggest": {
+        "region_label": "Suggested daily rate in the region",
+        "my_price_label": "My daily rate"
+      },
       "solicitations": {
       "solicitations": {
         "title": "Requests for you",
         "title": "Requests for you",
         "until_8h": "Full day (up to 8h)",
         "until_8h": "Full day (up to 8h)",
@@ -215,6 +219,9 @@
         "until_4h": "Medium (up to 4h)",
         "until_4h": "Medium (up to 4h)",
         "until_2h": "Quick (up to 2h)"
         "until_2h": "Quick (up to 2h)"
       },
       },
+      "opportunities": {
+        "title": "Opportunities"
+      },
       "favorites": {
       "favorites": {
         "title": "Your favorites",
         "title": "Your favorites",
         "view_schedule": "View schedule"
         "view_schedule": "View schedule"
@@ -230,6 +237,8 @@
         "tag_custom": "Custom",
         "tag_custom": "Custom",
         "tag_default": "Default",
         "tag_default": "Default",
         "details": "View details",
         "details": "View details",
+        "offers_meal": "Offers meal",
+        "no_meal": "Does not offer meal",
         "place_home": "Residential",
         "place_home": "Residential",
         "place_apartment": "Apartment",
         "place_apartment": "Apartment",
         "place_unknown": "Address"
         "place_unknown": "Address"
@@ -253,6 +262,58 @@
     "opportunities": "Opportunities",
     "opportunities": "Opportunities",
     "plans": "Plans"
     "plans": "Plans"
   },
   },
+  "profile": {
+    "title": "Profile",
+    "edit_profile": "Edit profile",
+    "edit_data": "My data",
+    "change_photo": "Request photo change",
+    "full_name": "Full Name",
+    "email": "E-mail",
+    "phone": "Phone",
+    "update": "Update",
+    "update_success": "Profile updated successfully!",
+    "update_error": "Error updating profile",
+    "placeholder_name": "Enter your name",
+    "placeholder_email": "Enter your e-mail",
+    "placeholder_phone": "Enter your phone",
+    "bank_data": {
+      "title": "Bank data",
+      "description": "Pix, agency and account"
+    },
+    "availability": {
+      "title": "Availability",
+      "description": "Days I am available"
+    },
+    "service_data": {
+      "title": "Service data",
+      "description": "Rates and services"
+    },
+    "address": {
+      "title": "Address",
+      "description": "Location for services",
+      "address_subtitle": "Change address",
+      "address_description": "Keep your address updated so that bookings appear.",
+      "cep": "ZIP Code",
+      "address_label": "Address",
+      "address_placeholder": "Street -----, Neighborhood",
+      "number": "Number",
+      "complement": "Complement",
+      "complement_placeholder": "House, apt, block, etc",
+      "district_label": "District",
+      "city_label": "City",
+      "state_label": "State",
+      "update_address": "Change address",
+      "search_placeholder": "Search"
+    },
+    "help": {
+      "title": "Help",
+      "description": "Questions and support"
+    },
+    "logout": {
+      "title": "Logout",
+      "description": "Disconnect from your account"
+    }
+  },
   "validation": {
   "validation": {
     "rules": {
     "rules": {
       "required": "This field is required",
       "required": "This field is required",
@@ -409,31 +470,40 @@
       "detractors": "Detractors"
       "detractors": "Detractors"
     }
     }
   },
   },
-  "profile": {
-    "title": "Profile",
-    "edit_profile": "Edit profile",
-    "edit_data": "My data",
-    "change_photo": "Request photo change",
-    "full_name": "Full Name",
-    "email": "E-mail",
-    "phone": "Phone",
-    "update": "Update",
-    "update_success": "Profile updated successfully!",
-    "update_error": "Error updating profile",
-    "placeholder_name": "Enter your name",
-    "placeholder_email": "Enter your e-mail",
-    "placeholder_phone": "Enter your phone",
-    "bank_data": {
-      "title": "Bank data",
-      "description": "Pix, agency and account"
-    },
-    "availability": {
-      "title": "Availability",
-      "description": "Days I am available"
+  "dashboard": {
+    "currency_format": "$ {value}",
+    "cards": {
+      "total_earnings": "Total Earnings",
+      "tickets_sold": "Tickets Sold",
+      "registrations": "Registrations"
     },
     },
-    "service_data": {
-      "title": "Service data",
-      "description": "My specialties"
+    "charts": {
+      "tickets_by_type": {
+        "title": "Total tickets by type",
+        "labels": {
+          "vip": "VIP",
+          "track": "Track",
+          "box": "Box",
+          "courtesy": "Courtesy"
+        }
+      },
+      "participants_by_document": {
+        "title": "Percentage of CNPJ and CPF in registrations"
+      },
+      "sales_over_time": {
+        "title": "Sales Over Period",
+        "y_label": "Value ({currency})"
+      },
+      "registration_source": {
+        "title": "Registration Source",
+        "source": "Source",
+        "sources": {
+          "instagram": "Instagram",
+          "facebook": "Facebook",
+          "google": "Google",
+          "referral": "Referral"
+        }
+      }
     }
     }
   }
   }
 }
 }

+ 95 - 61
src/i18n/locales/es.json

@@ -3,7 +3,7 @@
     "see_all": "ver todo",
     "see_all": "ver todo",
     "details": "ver detalles",
     "details": "ver detalles",
     "accept": "aceptar",
     "accept": "aceptar",
-    "refuse": "recusar",
+    "refuse": "rechazar",
     "from": "De",
     "from": "De",
     "to": "A",
     "to": "A",
     "alter": "alterar",
     "alter": "alterar",
@@ -165,41 +165,41 @@
           "rg": "RG"
           "rg": "RG"
         },
         },
         "step_4": {
         "step_4": {
-            "document_front": "Lado 1 (Frente)",
-            "document_front_desc": "Foto del frente de su documento (RG o Licencia).",
-            "document_back": "Lado 2 (Dorso)",
-            "document_back_desc": "Foto del dorso de su documento (RG o Licencia).",
-            "selfie": "Selfie con documento",
-            "selfie_desc": "Tome una selfie sosteniendo su documento cerca de su rostro.",
-            "photo_captured": "¡Foto capturada!",
-            "action": "enviar documentos"
+          "document_front": "Lado 1 (Frente)",
+          "document_front_desc": "Foto del frente de su documento (RG o Licencia).",
+          "document_back": "Lado 2 (Dorso)",
+          "document_back_desc": "Foto del dorso de su documento (RG o Licencia).",
+          "selfie": "Selfie con documento",
+          "selfie_desc": "Tome una selfie sosteniendo su documento cerca de su rostro.",
+          "photo_captured": "¡Foto capturada!",
+          "action": "enviar documentos"
         },
         },
         "step_5": {
         "step_5": {
-            "daily_price_title": "¿Cuál es el valor de su jornada de hasta 8 horas?",
-            "daily_price_min_max": "Valor mínimo R$ 100,00. Valor máximo R$ 500,00.",
-            "dont_worry": "¡No se preocupe!",
-            "change_anytime": "Puede cambiar el valor de su jornada cuando quiera ;)",
-            "shorter_services": "Basado en el valor anterior, los valores de servicios más cortos serán:",
-            "up_to_6h": "hasta 6 horas",
-            "up_to_4h": "hasta 4 horas",
-            "up_to_2h": "hasta 2 horas",
-            "other_services": "Además de la limpieza básica, ¿qué otros servicios realiza?",
-            "change_in_profile": "(podrá ser cambiado en el perfil)",
-            "no_services": "No hay tipos de servicio disponibles en este momento.",
-            "search_visibility": "Esta información aparecerá para quienes busquen su perfil en la búsqueda.",
-            "action": "continuar"
+          "daily_price_title": "¿Cuál es el valor de su jornada de hasta 8 horas?",
+          "daily_price_min_max": "Valor mínimo R$ 100,00. Valor máximo R$ 500,00.",
+          "dont_worry": "¡No se preocupe!",
+          "change_anytime": "Puede cambiar el valor de su jornada cuando quiera ;)",
+          "shorter_services": "Basado en el valor anterior, los valores de servicios más cortos serán:",
+          "up_to_6h": "hasta 6 horas",
+          "up_to_4h": "hasta 4 horas",
+          "up_to_2h": "hasta 2 horas",
+          "other_services": "Además de la limpieza básica, ¿qué otros servicios realiza?",
+          "change_in_profile": "(podrá ser cambiado en el perfil)",
+          "no_services": "No hay tipos de servicio disponibles en este momento.",
+          "search_visibility": "Esta información aparecerá para quienes busquen su perfil en la búsqueda.",
+          "action": "continuar"
         },
         },
         "step_6": {
         "step_6": {
-            "title": "¡Ahora vamos a elegir qué mejores horarios para que recibas solicitudes de servicios!",
-            "lock_hint": "Toque y bloquee los días o períodos",
-            "lock_description": "si no desea recibir solicitudes de servicios en este período.",
-            "morning": "mañana",
-            "afternoon": "tarde",
-            "instruction": "Para bloquear días individuales, haga clic en el día, para bloquear solo períodos, haga clic en mañana o tarde.",
-            "dont_worry": "¡No se preocupe!",
-            "change_anytime": "Después podrá cambiar la disponibilidad de su preferencia en cualquier momento en la aplicación ;)",
-            "select_at_least_one": "Seleccione al menos un período de trabajo.",
-            "action": "finalizar registro"
+          "title": "¡Ahora vamos a elegir qué mejores horarios para que recibas solicitudes de servicios!",
+          "lock_hint": "Toque y bloquee los días o períodos",
+          "lock_description": "si no desea recibir solicitudes de servicios en este período.",
+          "morning": "mañana",
+          "afternoon": "tarde",
+          "instruction": "Para bloquear días individuales, haga clic en el día, para bloquear solo períodos, haga clic en mañana o tarde.",
+          "dont_worry": "¡No se preocupe!",
+          "change_anytime": "Después podrá cambiar la disponibilidad de su preferencia en cualquier momento en la aplicación ;)",
+          "select_at_least_one": "Seleccione al menos un período de trabajo.",
+          "action": "finalizar registro"
         }
         }
       }
       }
     },
     },
@@ -208,12 +208,19 @@
         "welcome": "Hola,",
         "welcome": "Hola,",
         "my_schedules": "Mis citas"
         "my_schedules": "Mis citas"
       },
       },
+      "price_suggest": {
+        "region_label": "Precio de jornada sugerido en la región",
+        "my_price_label": "Precio de mi jornada"
+      },
       "solicitations": {
       "solicitations": {
         "title": "Solicitudes para ti",
         "title": "Solicitudes para ti",
         "until_8h": "Integral (hasta 8h)",
         "until_8h": "Integral (hasta 8h)",
-        "until_6h": "Padrón (Hasta 6h)",
+        "until_6h": "Estándar (Hasta 6h)",
         "until_4h": "Medio Período (Hasta 4h)",
         "until_4h": "Medio Período (Hasta 4h)",
-        "until_2h": "Diaria Rápida (Hasta 2h)"
+        "until_2h": "Jornada Rápida (Hasta 2h)"
+      },
+      "opportunities": {
+        "title": "Oportunidades"
       },
       },
       "favorites": {
       "favorites": {
         "title": "Tus favoritos",
         "title": "Tus favoritos",
@@ -230,6 +237,8 @@
         "tag_custom": "Personalizado",
         "tag_custom": "Personalizado",
         "tag_default": "Estándar",
         "tag_default": "Estándar",
         "details": "Ver detalles",
         "details": "Ver detalles",
+        "offers_meal": "Ofrece comida",
+        "no_meal": "No ofrece comida",
         "place_home": "Residencial",
         "place_home": "Residencial",
         "place_apartment": "Apartamento",
         "place_apartment": "Apartamento",
         "place_unknown": "Dirección"
         "place_unknown": "Dirección"
@@ -253,6 +262,58 @@
     "opportunities": "Oportunidades",
     "opportunities": "Oportunidades",
     "plans": "Planes"
     "plans": "Planes"
   },
   },
+  "profile": {
+    "title": "Perfil",
+    "edit_profile": "Editar perfil",
+    "edit_data": "Mis datos",
+    "change_photo": "Solicitar cambio de foto",
+    "full_name": "Nombre completo",
+    "email": "Correo electrónico",
+    "phone": "Teléfono",
+    "update": "Actualizar",
+    "update_success": "¡Perfil actualizado con éxito!",
+    "update_error": "Error al actualizar el perfil",
+    "placeholder_name": "Escriba su nombre",
+    "placeholder_email": "Escriba su correo electrónico",
+    "placeholder_phone": "Escriba su teléfono",
+    "bank_data": {
+      "title": "Datos bancarios",
+      "description": "Pix, agencia y cuenta"
+    },
+    "availability": {
+      "title": "Disponibilidad",
+      "description": "Días que estoy disponible"
+    },
+    "service_data": {
+      "title": "Datos de servicio",
+      "description": "Valores y servicios"
+    },
+    "address": {
+      "title": "Dirección",
+      "description": "Ubicación para servicios",
+      "address_subtitle": "Cambiar dirección",
+      "address_description": "Mantenga su dirección actualizada para que aparezcan contrataciones.",
+      "cep": "Código Postal",
+      "address_label": "Dirección",
+      "address_placeholder": "Calle -----, Barrio",
+      "number": "Número",
+      "complement": "Complemento",
+      "complement_placeholder": "Casa, apto, bloque, etc",
+      "district_label": "Barrio",
+      "city_label": "Ciudad",
+      "state_label": "Estado/Provincia",
+      "update_address": "Cambiar dirección",
+      "search_placeholder": "Buscar"
+    },
+    "help": {
+      "title": "Ayuda",
+      "description": "Dudas y soporte"
+    },
+    "logout": {
+      "title": "Salir",
+      "description": "Desconectar de su cuenta"
+    }
+  },
   "validation": {
   "validation": {
     "rules": {
     "rules": {
       "required": "Este campo es obligatorio",
       "required": "Este campo es obligatorio",
@@ -444,32 +505,5 @@
         }
         }
       }
       }
     }
     }
-  },
-  "profile": {
-    "title": "Perfil",
-    "edit_profile": "Editar perfil",
-    "edit_data": "Mis datos",
-    "change_photo": "Solicitar cambio de foto",
-    "full_name": "Nombre completo",
-    "email": "Correo electrónico",
-    "phone": "Teléfono",
-    "update": "Actualizar",
-    "update_success": "¡Perfil actualizado con éxito!",
-    "update_error": "Error al actualizar el perfil",
-    "placeholder_name": "Escriba su nombre",
-    "placeholder_email": "Escriba su correo electrónico",
-    "placeholder_phone": "Escriba su teléfono",
-    "bank_data": {
-      "title": "Datos bancarios",
-      "description": "Pix, agencia y cuenta"
-    },
-    "availability": {
-      "title": "Disponibilidad",
-      "description": "Días que estoy disponible"
-    },
-    "service_data": {
-      "title": "Datos de servicio",
-      "description": "Mis especialidades"
-    }
   }
   }
 }
 }

+ 14 - 1
src/i18n/locales/pt.json

@@ -290,7 +290,20 @@
     },
     },
     "address": {
     "address": {
       "title": "Endereço",
       "title": "Endereço",
-      "description": "Localização para serviços"
+      "description": "Localização para serviços",
+      "address_subtitle": "Alterar endereço",
+      "address_description": "Mantenha seu endereço atualizado para que apareçam contratações.",
+      "cep": "CEP",
+      "address_label": "Endereço",
+      "address_placeholder": "Rua -----, Bairro",
+      "number": "Número",
+      "complement": "Complemento",
+      "complement_placeholder": "Casa, apto, bloco, etc",
+      "district_label": "Bairro",
+      "city_label": "Cidade",
+      "state_label": "Estado",
+      "update_address": "Alterar endereço",
+      "search_placeholder": "Buscar"
     },
     },
     "help": {
     "help": {
       "title": "Ajuda",
       "title": "Ajuda",

+ 1 - 3
src/pages/profile/ProfileEditDialog.vue

@@ -143,9 +143,7 @@ onMounted(async () => {
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
-.shadow-profile {
-  box-shadow: 0px 1px 8px rgba(0, 0, 0, 0.05);
-}
+
 
 
 :deep(.q-field--outlined .q-field__control) {
 :deep(.q-field--outlined .q-field__control) {
   border-radius: 8px;
   border-radius: 8px;

+ 10 - 3
src/pages/profile/ProfilePage.vue

@@ -64,7 +64,7 @@
         <q-icon name="mdi-chevron-right" color="primary" size="md" />
         <q-icon name="mdi-chevron-right" color="primary" size="md" />
       </div>
       </div>
 
 
-      <div class="menu-item row items-center no-wrap cursor-pointer q-py-sm">
+      <div class="menu-item row items-center no-wrap cursor-pointer q-py-sm" @click="openAddressDialog">
         <div class="column">
         <div class="column">
           <span class="menu-title gradient-diarista text-weight-bold">{{ $t('profile.address.title') }}</span>
           <span class="menu-title gradient-diarista text-weight-bold">{{ $t('profile.address.title') }}</span>
           <span class="menu-description text-text">{{ $t('profile.address.description') }}</span>
           <span class="menu-description text-text">{{ $t('profile.address.description') }}</span>
@@ -101,6 +101,7 @@ import { ref, onMounted } from 'vue';
 import { useQuasar } from 'quasar';
 import { useQuasar } from 'quasar';
 import { getUser } from 'src/api/user';
 import { getUser } from 'src/api/user';
 import ProfileEditDialog from './ProfileEditDialog.vue';
 import ProfileEditDialog from './ProfileEditDialog.vue';
+import ProfileAddressDialog from 'src/components/profile/ProfileAddressDialog.vue';
 
 
 const $q = useQuasar();
 const $q = useQuasar();
 
 
@@ -116,8 +117,14 @@ const openEditProfile = () => {
     componentProps: {
     componentProps: {
       userData: user.value
       userData: user.value
     }
     }
-  }).onOk((data) => {
-    user.value = { ...user.value, ...data };
+  }).onOk((updatedUser) => {
+    user.value = { ...user.value, ...updatedUser };
+  });
+};
+
+const openAddressDialog = () => {
+  $q.dialog({
+    component: ProfileAddressDialog
   });
   });
 };
 };