Sfoglia il codice sorgente

feat: :sparkles: feat(agendamento-sob-medida) Foi feito o ajuste de algumas paginas da dashboard e oportunidades

Foi realizado um ajuste na pagina dashboard para fazer a exibição do modal, tambem foi feito alterações na parte de oportunidades tranformando o details em um modal para que não gerasse carregamento da pagina 2 vezes

fase:dev | origin:escopo
kayo henrique 1 mese fa
parent
commit
7ae03a32fa

+ 17 - 12
src/pages/dashboard/DashboardPage.vue

@@ -20,7 +20,6 @@
       />
       <DashboardNextSchedules v-if="nextSchedules?.length > 0" :data="nextSchedules" @view-details="(item) => openNextScheduleDialog(item)" />
       <DashboardOpportunities v-if="opportunities?.length > 0" :data="opportunities"/>
-      <router-view />
     </template>
   </div>
 </template>
@@ -37,19 +36,18 @@ import DashboardOpportunities from 'src/components/dashboard/DashboardOpportunit
 import SolicitationDetailsDialog from 'src/components/dashboard/SolicitationDetailsDialog.vue';
 import NextSchedulesDetailsDialog from 'src/components/dashboard/NextSchedulesDetailsDialog.vue';
 import ScheduleRatingDialog from 'src/components/dashboard/ScheduleRatingDialog.vue';
+import OpportunityDialog from 'src/pages/opportunities/components/OpportunityDialog.vue';
 import { onMounted, ref } from 'vue';
 import { useQuasar } from 'quasar';
 import { dadosDashboard } from 'src/api/dashboard';
 import { updateScheduleStatus } from 'src/api/schedule';
-import { useRoute, useRouter } from 'vue-router';
+import { useRouter } from 'vue-router';
 
 
 
 
 
 const router = useRouter();
-const route = useRoute();
-const showDialog = ref(false);
 
 const headerBar = ref({});
 const summaryInfos = ref({});
@@ -59,6 +57,8 @@ const todayServices = ref([]);
 const nextSchedules = ref([]);
 const opportunities = ref([]);
 
+const showSuccessModal = ref(router.currentRoute.value.fullPath.includes('showSuccessModal') || 'true');
+
 const $q = useQuasar();
 
 const loading = ref(true);
@@ -74,7 +74,19 @@ const loadDashboard = async () => {
     nextSchedules.value = response.nextSchedules ?? [];
     opportunities.value = response.opportunities ?? [];
   }
-};
+
+  if( showSuccessModal.value ) {
+    $q.dialog({
+       component: OpportunityDialog   
+       })
+
+    showSuccessModal.value = false;
+    router.replace({ path: router.currentRoute.value.path, query: {} });
+  }
+
+  
+}
+
 
 const handleScheduleAction = async (id, status) => {
   try {
@@ -116,13 +128,6 @@ const openRatingDialog = (schedule) => {
 
 onMounted(async () => {
   await loadDashboard();
-
-   if (route.query.dialog === 'success') {
-    showDialog.value = true;
-
-    
-    router.replace({ query: {} });
-  }
   loading.value = false;
 });
 </script>

+ 15 - 25
src/pages/opportunities/OpportunitiesPage.vue

@@ -57,11 +57,7 @@
           </div>
 
           <div class="service-address">
-            {{ neighborhood(item.address?.address) }}
-          </div>
-
-          <div class="district">
-             {{ item.address?.district }}
+            {{ item.address?.district }}
           </div>
 
 
@@ -79,31 +75,31 @@
 </template>
 <script setup>
 import { ref, onMounted } from 'vue'
-import { useRouter } from 'vue-router'
-import { chooseprice,filterCurrency } from 'src/helpers/utils'
+import { useQuasar } from 'quasar'
+import { chooseprice, filterCurrency } from 'src/helpers/utils'
 import { getProviderOpportunities } from 'src/api/opportunities'
 import { userStore } from 'src/stores/user'
+import OpportunityDetailsDialog from './components/OpportunityDetailsDialog.vue'
+
+const $q = useQuasar()
 
-const router = useRouter()
 const user = userStore()
 
 const opportunities = ref([])
 const loading = ref(false)
 
-
 const goToOpportunityDetails = (item) => {
 
   const id = item.custom_schedule?.id || item.id
 
-  router.push({
-    name: 'OpportunityDetailsPage',
-    params: { id },
-    state: { opportunity: item }
+  $q.dialog({
+    component: OpportunityDetailsDialog,
+    componentProps: {
+      opportunityId: id
+    }
   })
 }
 
-
-
 // formatando a data
 const formatDate = (date) => {
   if (!date) return ''
@@ -118,19 +114,10 @@ const formatDate = (date) => {
 // formatando hora para exibir só HH:mm
 const formatHour = (time) => {
   if (!time) return ''
-  return time.slice(0, 5) 
+  return time.slice(0, 5)
 }
 
 
-const neighborhood = (address) => {
-  if(!address) return '';
-
-  return address
-  .split(',')[1]
-  ?.split('-')[0]
-  ?.trim();
-};
-
 const loadOpportunities = async () => {
   loading.value = true
 
@@ -140,9 +127,12 @@ const loadOpportunities = async () => {
     )
 
     opportunities.value = (response || [])
+
   } catch (error) {
     console.error('Erro ao buscar oportunidades:', error)
+
     opportunities.value = []
+
   } finally {
     loading.value = false
   }

+ 455 - 0
src/pages/opportunities/components/OpportunityDetailsDialog.vue

@@ -0,0 +1,455 @@
+<template>
+  <q-dialog
+    ref="dialogRef"
+    maximized
+    transition-show="slide-up"
+    transition-hide="slide-down"
+  >
+    <div v-if="details" class="details-page">
+
+      <!-- HEADER -->
+      <div class="page-header">
+        <q-btn
+          flat
+          round
+          dense
+          icon="chevron_left"
+          class="back-btn"
+          @click="goBack"
+        />
+
+        <div class="page-title">
+          {{ $t('provider.dashboard.opportunity_details.title') }}
+        </div>
+      </div>
+
+      <!-- CLIENTE -->
+      <div class="client-section">
+        <img :src="details.avatar" class="client-avatar" />
+
+        <div class="client-name">
+          {{ details.schedule?.client_name }}
+          <span class="rating">
+            {{ details.schedule?.rating }}
+          </span>
+        </div>
+
+        <div class="client-price">
+          {{
+            $t('provider.dashboard.opportunities.currency', {
+              value: chooseprice(details.schedule?.period_type)
+            })
+          }}
+        </div>
+
+        <div class="date">
+          {{ formatDate(details.schedule?.date) }}
+        </div>
+
+        <div class="hour">
+          {{ formatHour(details.schedule?.start_time) }}
+          {{ formatHour(details.schedule?.end_time) }}
+        </div>
+      </div>
+
+      <!-- ENDEREÇO -->
+      <div class="address">
+        <q-icon name="place" size="16px" />
+
+        {{ details.schedule?.address?.district }}
+      </div>
+
+      <div class="distance">
+        {{
+          $t(
+            'provider.dashboard.opportunity_details.distance_text',
+            { distance: details.schedule?.distance }
+          )
+        }}
+      </div>
+
+      <!-- TAGS -->
+      <div v-if="details.tags?.length" class="tags-row">
+        <q-chip
+          v-for="(tag, index) in details.tags"
+          :key="index"
+          outline
+          class="chip"
+        >
+          {{ tag }}
+        </q-chip>
+      </div>
+
+      <!-- INFO -->
+      <div class="service-type">
+        {{ $t('provider.dashboard.opportunity_details.sob_medida') }}
+
+        <span>
+          {{
+            $t(
+              'provider.dashboard.opportunity_details.sob_medida_highlight'
+            )
+          }}
+        </span>
+
+        <br />
+
+        {{ $t('provider.dashboard.opportunity_details.para') }}
+
+        <strong class="highlight-service">
+          {{ details.service_type_name }}
+        </strong>
+      </div>
+
+      <div class="address-type">
+        <span class="chip-type">
+          {{ details.address_type }}
+        </span>
+
+        <span
+          v-if="details.offers_meal"
+          class="chip-type"
+        >
+          {{ $t('provider.dashboard.opportunity_details.offers_meal') }}
+        </span>
+      </div>
+
+      <!-- INFO TITLE -->
+      <div
+        v-if="details.description"
+        class="service-type gradient-diarista"
+      >
+        {{ $t('provider.dashboard.opportunity_details.info_title') }}
+      </div>
+
+      <!-- DESCRIÇÃO -->
+      <div class="description-box">
+        {{ details.description }}
+      </div>
+
+      <!-- BOTÃO -->
+      <q-btn
+        unelevated
+        rounded
+        no-caps
+        class="accept-btn"
+        :label="$t('provider.dashboard.opportunity_details.button_accept')"
+        @click="goToProposalFlow"
+      />
+
+      <!-- ALERTA -->
+      <div class="alert-box">
+        <q-icon
+          name="warning"
+          size="18px"
+          class="alert-icon"
+        />
+
+        <span class="alert-text">
+          {{ $t('provider.dashboard.opportunity_details.alert_text') }}
+        </span>
+      </div>
+
+    </div>
+  </q-dialog>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { useRouter } from 'vue-router'
+import { useDialogPluginComponent } from 'quasar'
+import { userStore } from 'src/stores/user'
+import {
+  getOpportunityById,
+  proposalOpportunity
+} from 'src/api/opportunities'
+
+const props = defineProps({
+  opportunityId: {
+    type: Number,
+    required: true
+  }
+})
+
+defineEmits([
+  ...useDialogPluginComponent.emits
+])
+
+const {
+  dialogRef,
+  onDialogOK
+} = useDialogPluginComponent()
+
+const router = useRouter()
+
+const user = userStore()
+const details = ref(null)
+const loading = ref(true)
+
+const chooseprice = (periodType) => {
+  switch (periodType) {
+    case "8":
+      return user.user.provider_daily_price_8h
+    case "6":
+      return user.user.provider_daily_price_6h
+    case "4":
+      return user.user.provider_daily_price_4h
+    case "2":
+      return user.user.provider_daily_price_2h
+    default:
+      return 0
+  }
+}
+
+// formatando a data
+const formatDate = (date) => {
+  if (!date) return ''
+
+  const [day, month, year] = date.split('/')
+
+  const parsedDate = new Date(`${year}-${month}-${day}`)
+
+  const formatted = parsedDate.toLocaleDateString('pt-BR', {
+    weekday: 'long',
+    day: '2-digit',
+    month: '2-digit'
+  })
+
+  return formatted.charAt(0).toUpperCase() + formatted.slice(1)
+}
+
+// formatando hora para exibir só HH:mm
+const formatHour = (time) => {
+  if (!time) return ''
+  return time.slice(0, 5)
+}
+
+const goBack = () => {
+  onDialogOK()
+}
+
+const goToProposalFlow = async () => {
+
+  await proposalOpportunity(
+    details.value.schedule_id,
+    user.user.provider.id
+  )
+
+  await router.push({
+    name: 'DashboardPage',
+    query: { showSuccessModal: 'true' }
+  })
+
+  onDialogOK()
+}
+
+onMounted(async () => {
+  try {
+    const response = await getOpportunityById(
+      props.opportunityId
+    )
+
+    if (response) {
+      details.value = response
+    } else {
+      console.warn('Nenhum dado retornado')
+    }
+
+  } catch (error) {
+    console.error('Erro ao carregar detalhes:', error)
+
+  } finally {
+    loading.value = false
+  }
+})
+</script>
+
+<style scoped lang="scss">
+.details-page {
+  padding: 24px 16px;
+  background: #f4f5f7;
+  min-height: 100vh;
+}
+
+/* HEADER */
+.page-header {
+  display: flex;
+  align-items: center;      
+  justify-content: center;
+  position: relative;
+
+  height: 56px;            
+  padding: 0 16px;
+
+  background: #fff;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  border-radius: 0 0 16px 16px;
+
+  margin-bottom: 20px;
+}
+
+.back-btn {
+  position: absolute;
+  left: 8px;
+  top: 50%;
+  transform: translateY(-50%); 
+  color: #7c5cff;
+}
+
+.page-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: #7c5cff;
+}
+
+/* CLIENTE */
+.client-section {
+  text-align: center;
+  margin-top: 10px;
+}
+
+.client-avatar {
+  width: 90px;
+  height: 90px;
+  border-radius: 50%;
+  object-fit: cover;
+  margin-bottom: 10px;
+}
+
+.client-name {
+  font-size: 16px;
+  font-weight: 600;
+  color: #444;
+}
+
+.rating {
+  color: #ffb800;
+  font-size: 12px;
+  margin-left: 4px;
+}
+
+.client-price {
+  margin-top: 10px;
+  font-size: 26px;
+  font-weight: 700;
+  color: #7c5cff;
+}
+
+/* DATA */
+.date {
+  margin-top: 10px;
+  font-size: 13px;
+  font-weight: 600;
+  color: #555;
+}
+
+.hour {
+  font-size: 13px;
+  color: #777;
+  margin-bottom: 10px;
+}
+
+/* ENDEREÇO */
+.address {
+  margin-top: 12px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  gap: 6px;
+  color: #7c5cff;
+  font-size: 14px;
+  font-weight: 600;
+}
+
+.distance {
+  text-align: center;
+  font-size: 12px;
+  color: #888;
+  margin-top: 4px;
+  margin-bottom: 14px;
+}
+
+/* TEXTO SOB MEDIDA */
+.service-type {
+  text-align: center;
+  font-size: 13px;
+  margin-top: 14px;
+  color: #666;
+  line-height: 1.5;
+}
+
+.service-type span {
+  color: #7c5cff;
+  font-weight: 600;
+}
+
+.highlight-service {
+  color: #7c5cff;
+  font-weight: 600;
+}
+
+/* CHIPS */
+.address-type {
+  display: flex;
+  justify-content: center;
+  gap: 10px;
+  margin-top: 14px;
+  margin-bottom: 14px;
+}
+
+.chip-type {
+  border: 1.5px solid #7c5cff;
+  color: #7c5cff;
+  padding: 6px 16px;
+  border-radius: 999px;
+  font-size: 12px;
+  font-weight: 600;
+  background: white;
+}
+
+/* INFO TITLE */
+.gradient-diarista {
+  text-align: center;
+  font-weight: 700;
+  color: #7c5cff;
+  margin-top: 18px;
+  font-size: 14px;
+}
+
+/* DESCRIÇÃO */
+.description-box {
+  text-align: center;
+  font-size: 13px;
+  color: #666;
+  margin: 12px 0 24px;
+  line-height: 1.5;
+  padding: 0 10px;
+}
+
+/* BOTÃO */
+.accept-btn {
+  width: 100%;
+  height: 52px;
+  border-radius: 28px;
+  background: linear-gradient(90deg, #7c5cff, #9f7aea);
+  color: white;
+  font-weight: 600;
+  font-size: 15px;
+}
+
+/* ALERTA */
+.alert-box {
+  margin-top: 14px;
+  background: #e9f0ff;
+  padding: 12px;
+  border-radius: 14px;
+  font-size: 12px;
+  text-align: center;
+  color: #5c6b8a;
+
+  display: flex;
+  gap: 8px;
+  align-items: center;
+  justify-content: center;
+}
+</style>

+ 0 - 359
src/pages/opportunities/components/OpportunityDetailsPage.vue

@@ -1,359 +0,0 @@
-<template>
-  <q-page v-if="details" class="details-page">
-
-    <!-- HEADER -->
-    <div class="page-header">
-      <q-btn flat round dense icon="chevron_left" class="back-btn" @click="router.back()" />
-      <div class="page-title">
-        {{ $t('provider.dashboard.opportunity_details.title') }}
-      </div>
-    </div>
-
-    <!-- CLIENTE -->
-    <div class="client-section">
-      <img :src="details.avatar" class="client-avatar" />
-
-      <div class="client-name">
-        {{ details.schedule?.client_name }}
-        <span class="rating"> {{ details.schedule?.rating }}</span>
-      </div>
-
-      <div class="client-price">{{ $t('provider.dashboard.opportunities.currency', { value: chooseprice(details.schedule?.period_type) }) }}</div>
-
-      <div class="date">  {{ formatDate(details.schedule?.date) }}</div>
-      <div class="hour">{{ formatHour(details.schedule?.start_time ) }} {{ formatHour(details.schedule?.end_time ) }}</div>
-    </div>
-
-    <!-- ENDEREÇO -->
-    <div class="address">
-      <q-icon name="place" size="16px" />
-      {{ details.schedule?.address?.district }}
-    </div>
-
-    <div class="distance">
-      {{ $t('provider.dashboard.opportunity_details.distance_text', { distance: details.schedule?.distance }) }}
-    </div>
-
-    <!-- TAGS -->
-    <div v-if="details.tags?.length" class="tags-row">
-      <q-chip v-for="(tag, index) in details.tags" :key="index" outline class="chip">
-        {{ tag }}
-      </q-chip>
-    </div>
-
-    <!-- INFO -->
-    <div class="service-type">
-  {{ $t('provider.dashboard.opportunity_details.sob_medida') }}
-  <span>
-    {{ $t('provider.dashboard.opportunity_details.sob_medida_highlight') }}
-  </span>
-  <br />
-  {{ $t('provider.dashboard.opportunity_details.para') }}
-  <strong class="highlight-service">
-    {{ details.service_type_name }}
-  </strong>
-</div>
-    
-
-
-    <div class="address-type">
-  <span class="chip-type">
-    {{ (details.address_type) }}
-  </span> 
-  <span v-if="details.offers_meal" class="chip-type">
-    {{ $t('provider.dashboard.opportunity_details.offers_meal') }}
-  </span>    
-</div>
-    
-
-
-     <div v-if="details.description" class="service-type gradient-diarista">
-  {{ $t('provider.dashboard.opportunity_details.info_title') }}
-  </div>
-    <!-- DESCRIÇÃO -->
-    <div class="description-box">
-      {{ details.description }}
-    </div>
-
-    <!-- BOTÃO -->
-    <q-btn unelevated rounded no-caps class="accept-btn" :label="$t('provider.dashboard.opportunity_details.button_accept')" @click="goToProposalFlow" />
-
-    <!-- ALERTA -->
-    <div class="alert-box">
-      <q-icon name="warning" size="18px" class="alert-icon" />
-      <span class="alert-text">
-        {{ $t('provider.dashboard.opportunity_details.alert_text') }}
-      </span>
-    </div>
-
-  </q-page>
-</template>
-
-<script setup>
-import { ref, onMounted } from 'vue'
-import { useRouter, useRoute } from 'vue-router'
-import { userStore } from 'src/stores/user'
-import { getOpportunityById, proposalOpportunity } from 'src/api/opportunities'
-
-
-const router = useRouter()
-const route = useRoute()
-
-const user = userStore()
-const details = ref(null)
-const loading = ref(true)
-
-const chooseprice = (periodType) => {
-  switch (periodType) {
-    case "8":
-      return user.user.provider_daily_price_8h
-    case "6":
-      return user.user.provider_daily_price_6h
-    case "4":
-      return user.user.provider_daily_price_4h
-    case "2":
-      return user.user.provider_daily_price_2h
-    default:
-      return 0
-  }
-}
-
-// formatando a data
-const formatDate = (date) => {
-  if (!date) return ''
-
-  const [day, month, year] = date.split('/')
-
-  const parsedDate = new Date(`${year}-${month}-${day}`)
-
-  const formatted = parsedDate.toLocaleDateString('pt-BR', {
-    weekday: 'long',
-    day: '2-digit',
-    month: '2-digit'
-  })
-
-  return formatted.charAt(0).toUpperCase() + formatted.slice(1)
-}
-
-// formatando hora para exibir só HH:mm
-const formatHour = (time) => {
-  if (!time) return ''
-  return time.slice(0, 5) 
-}
-
-onMounted(async () => {
-  try {
-    const id = route.params.id
-    const response = await getOpportunityById(id)
-
-    if (response) {
-      details.value = response
-    } else {
-      console.warn('Nenhum dado retornado')
-    }
-  } catch (error) {
-    console.error('Erro ao carregar detalhes:', error)
-  } finally {
-    loading.value = false
-  }
-})
-
-const goToProposalFlow = async () => {
-
-  await proposalOpportunity(details.value.schedule_id, user.user.provider.id)
-
-  await router.push({ name: 'DashboardPage'})
-
-   router.push({ name: 'OpportunityDialogPage' })
-}
-</script>
-
-<style scoped lang="scss">
-.details-page {
-  padding: 24px 16px;
-  background: #f4f5f7;
-  min-height: 100vh;
-}
-
-/* HEADER */
-.page-header {
-  display: flex;
-  align-items: center;      
-  justify-content: center;
-  position: relative;
-
-  height: 56px;            
-  padding: 0 16px;
-
-  background: #fff;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  border-radius: 0 0 16px 16px;
-
-  margin-bottom: 20px;
-}
-
-.back-btn {
-  position: absolute;
-  left: 8px;
-  top: 50%;
-  transform: translateY(-50%); 
-  color: #7c5cff;
-}
-
-.page-title {
-  font-size: 16px;
-  font-weight: 600;
-  color: #7c5cff;
-}
-
-/* CLIENTE */
-.client-section {
-  text-align: center;
-  margin-top: 10px;
-}
-
-.client-avatar {
-  width: 90px;
-  height: 90px;
-  border-radius: 50%;
-  object-fit: cover;
-  margin-bottom: 10px;
-}
-
-.client-name {
-  font-size: 16px;
-  font-weight: 600;
-  color: #444;
-}
-
-.rating {
-  color: #ffb800;
-  font-size: 12px;
-  margin-left: 4px;
-}
-
-.client-price {
-  margin-top: 10px;
-  font-size: 26px;
-  font-weight: 700;
-  color: #7c5cff;
-}
-
-/* DATA */
-.date {
-  margin-top: 10px;
-  font-size: 13px;
-  font-weight: 600;
-  color: #555;
-}
-
-.hour {
-  font-size: 13px;
-  color: #777;
-  margin-bottom: 10px;
-}
-
-/* ENDEREÇO */
-.address {
-  margin-top: 12px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  gap: 6px;
-  color: #7c5cff;
-  font-size: 14px;
-  font-weight: 600;
-}
-
-.distance {
-  text-align: center;
-  font-size: 12px;
-  color: #888;
-  margin-top: 4px;
-  margin-bottom: 14px;
-}
-
-/* TEXTO SOB MEDIDA */
-.service-type {
-  text-align: center;
-  font-size: 13px;
-  margin-top: 14px;
-  color: #666;
-  line-height: 1.5;
-}
-
-.service-type span {
-  color: #7c5cff;
-  font-weight: 600;
-}
-
-.highlight-service {
-  color: #7c5cff;
-  font-weight: 600;
-}
-
-/* CHIPS */
-.address-type {
-  display: flex;
-  justify-content: center;
-  gap: 10px;
-  margin-top: 14px;
-  margin-bottom: 14px;
-}
-
-.chip-type {
-  border: 1.5px solid #7c5cff;
-  color: #7c5cff;
-  padding: 6px 16px;
-  border-radius: 999px;
-  font-size: 12px;
-  font-weight: 600;
-  background: white;
-}
-
-/* INFO TITLE */
-.gradient-diarista {
-  text-align: center;
-  font-weight: 700;
-  color: #7c5cff;
-  margin-top: 18px;
-  font-size: 14px;
-}
-
-/* DESCRIÇÃO */
-.description-box {
-  text-align: center;
-  font-size: 13px;
-  color: #666;
-  margin: 12px 0 24px;
-  line-height: 1.5;
-  padding: 0 10px;
-}
-
-/* BOTÃO */
-.accept-btn {
-  width: 100%;
-  height: 52px;
-  border-radius: 28px;
-  background: linear-gradient(90deg, #7c5cff, #9f7aea);
-  color: white;
-  font-weight: 600;
-  font-size: 15px;
-}
-
-/* ALERTA */
-.alert-box {
-  margin-top: 14px;
-  background: #e9f0ff;
-  padding: 12px;
-  border-radius: 14px;
-  font-size: 12px;
-  text-align: center;
-  color: #5c6b8a;
-
-  display: flex;
-  gap: 8px;
-  align-items: center;
-  justify-content: center;
-}
-</style>

+ 26 - 25
src/pages/opportunities/components/OpportunityDialogPage.vue → src/pages/opportunities/components/OpportunityDialog.vue

@@ -1,39 +1,40 @@
 <template>
-  <q-page class="dialog-page">
+ <q-dialog ref="dialogRef" @hide="goBack">
 
-    <div class="overlay">
+  <q-card class="alert-card">
 
-      <div class="alert-card">
+    <!-- ÍCONE -->
+    <q-icon name="warning" size="36px" class="icon" />
 
-        <!-- ÍCONE -->
-        <q-icon name="warning" size="36px" class="icon" />
-
-        <!-- TEXTO -->
-        <div class="text">
-            {{ $t('provider.dashboard.opportunities_dialog.message') }}
-        </div>
+    <!-- TEXTO -->
+    <div class="text">
+      {{ $t('provider.dashboard.opportunities_dialog.message') }}
+    </div>
 
-        <!-- BOTÃO -->
-        <q-btn
-          :label="$t('provider.dashboard.opportunities_dialog.close')"
-          no-caps
-          class="btn"
-          @click="goBack"
-        />
+    <!-- BOTÃO -->
+    <q-btn
+      :label="$t('provider.dashboard.opportunities_dialog.close')"
+      no-caps
+      class="btn"
+      @click="goBack"
+    />
 
-      </div>
+  </q-card>
 
-    </div>
-
-  </q-page>
+</q-dialog>
 </template>
 <script setup>
-import { useRouter } from 'vue-router'
+import { useDialogPluginComponent } from 'quasar'
+
+defineEmits([...useDialogPluginComponent.emits])
 
-const router = useRouter()
+const {
+  dialogRef,
+  onDialogOK
+} = useDialogPluginComponent()
 
-const goBack = () => {
-  router.back()
+function goBack () {
+  onDialogOK()
 }
 </script>
 <style scoped>

+ 0 - 7
src/router/routes.js

@@ -29,13 +29,6 @@ const routes = [
         },
       },
 
-      {
-        path: "opportunity-dialog",
-        name: "OpportunityDialogPage",
-        component: () =>
-          import("src/pages/opportunities/components/OpportunityDialogPage.vue"),
-      },
-
       {
         path: "pagamentos",
         name: "PagamentosPage",