|
|
@@ -15,7 +15,7 @@
|
|
|
</div>
|
|
|
|
|
|
<q-card flat class="info-banner">
|
|
|
- <q-icon name="mdi-auto-fix" size="22px" class="banner-icon" />
|
|
|
+ <q-icon name="mdi-auto-fix" size="22px" />
|
|
|
<div class="banner-text">
|
|
|
{{ $t('provider.dashboard.opportunities.banner_text') }}
|
|
|
</div>
|
|
|
@@ -29,80 +29,79 @@
|
|
|
v-else-if="!opportunities.length"
|
|
|
class="text-center q-pa-md text-grey"
|
|
|
>
|
|
|
+ {{ $t('provider.dashboard.opportunities.empty') }}
|
|
|
</div>
|
|
|
|
|
|
-<div v-else class="opportunity-list">
|
|
|
- <q-card
|
|
|
- v-for="item in opportunities"
|
|
|
- :key="item.id"
|
|
|
- flat
|
|
|
- class="opportunity-card"
|
|
|
- >
|
|
|
- <!-- coluna avatar -->
|
|
|
- <div class="avatar-column">
|
|
|
- <img :src="item.avatar" class="client-avatar" />
|
|
|
-
|
|
|
- <div class="service-type">
|
|
|
- {{ item.serviceType }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- conteúdo central -->
|
|
|
- <div class="center-content">
|
|
|
- <div class="client-name-row">
|
|
|
- <span class="client-name">{{ item.clientName }}</span>
|
|
|
-
|
|
|
- <span class="rating">
|
|
|
- <q-icon name="star" size="11px" />
|
|
|
- {{ item.rating }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="service-date">
|
|
|
- {{ item.date }}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="service-hour">
|
|
|
- {{ item.hour }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- lado direito -->
|
|
|
- <div class="right-content">
|
|
|
- <div class="price">
|
|
|
- {{ `R$${item.price}` }}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="service-address">
|
|
|
- {{ item.address }}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="distance">
|
|
|
- {{ item.distance }}
|
|
|
- </div>
|
|
|
-
|
|
|
- <q-btn
|
|
|
- unelevated
|
|
|
- rounded
|
|
|
- no-caps
|
|
|
- color="secondary"
|
|
|
- label="ver detalhes"
|
|
|
- class="details-btn"
|
|
|
- @click="goToOpportunityDetails(item)"
|
|
|
- />
|
|
|
+ <div v-else class="opportunity-list">
|
|
|
+ <q-card
|
|
|
+ v-for="item in opportunities"
|
|
|
+ :key="item.id"
|
|
|
+ flat
|
|
|
+ class="opportunity-card"
|
|
|
+ >
|
|
|
+ <div class="avatar-column">
|
|
|
+ <img :src="item.avatar" class="client-avatar" />
|
|
|
+ <div class="service-type">
|
|
|
+ {{ item.serviceType }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="center-content">
|
|
|
+ <div class="client-name-row">
|
|
|
+ <span class="client-name">{{ item.clientName }}</span>
|
|
|
+
|
|
|
+ <span class="rating">
|
|
|
+ <q-icon name="star" size="11px" />
|
|
|
+ {{ item.rating }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="service-date">
|
|
|
+ {{ item.date }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="service-hour">
|
|
|
+ {{ item.hour }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="right-content">
|
|
|
+ <div class="price">
|
|
|
+ {{ $t('provider.dashboard.opportunities.currency', { value: item.price }) }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="service-address">
|
|
|
+ {{ item.address }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="distance">
|
|
|
+ {{ $t('provider.dashboard.opportunities.distance_km', { distance: item.distance }) }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="secondary"
|
|
|
+ :label="$t('provider.dashboard.opportunities.details')"
|
|
|
+ class="details-btn"
|
|
|
+ @click="goToOpportunityDetails(item)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </q-card>
|
|
|
</div>
|
|
|
- </q-card>
|
|
|
-</div>
|
|
|
</q-page>
|
|
|
</template>
|
|
|
-
|
|
|
<script setup>
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
+
|
|
|
import { getProviderOpportunities } from 'src/api/opportunities'
|
|
|
import { userStore } from 'src/stores/user'
|
|
|
|
|
|
const router = useRouter()
|
|
|
+const { t } = useI18n()
|
|
|
const user = userStore()
|
|
|
|
|
|
const opportunities = ref([])
|
|
|
@@ -111,65 +110,58 @@ const loading = ref(false)
|
|
|
const formatHour = (time) =>
|
|
|
time ? time.slice(0, 5).replace(':', 'h') : ''
|
|
|
|
|
|
+
|
|
|
const normalizeOpportunity = (item) => ({
|
|
|
id: item.id,
|
|
|
|
|
|
avatar: item.client?.user?.photo || '/icons/avatar.svg',
|
|
|
|
|
|
clientName:
|
|
|
- item.client?.user?.name || 'Cliente',
|
|
|
-
|
|
|
- rating:
|
|
|
- item.client?.average_rating || 5.0,
|
|
|
+ item.client?.user?.name ||
|
|
|
+ t('provider.dashboard.opportunities.client_default'),
|
|
|
|
|
|
- date: new Date(
|
|
|
- item.custom_schedule?.created_at ||
|
|
|
- item.created_at
|
|
|
-).toLocaleDateString('pt-BR'),
|
|
|
+ rating: item.client?.average_rating || 5.0,
|
|
|
|
|
|
-hour: `Das ${formatHour(
|
|
|
- item.start_time
|
|
|
-)} às ${formatHour(
|
|
|
- item.end_time
|
|
|
-)}`,
|
|
|
+ date: new Date(
|
|
|
+ item.custom_schedule?.created_at || item.created_at
|
|
|
+ ).toLocaleDateString(),
|
|
|
|
|
|
+ hour: `${t('common.from')} ${formatHour(item.start_time)} ${t('common.to')} ${formatHour(item.end_time)}`,
|
|
|
|
|
|
address:
|
|
|
- item.address?.address || 'Endereço não informado',
|
|
|
+ item.address?.address ||
|
|
|
+ t('provider.dashboard.opportunities.address_not_found'),
|
|
|
|
|
|
serviceType:
|
|
|
- item.custom_schedule?.service_type?.name || 'Serviço',
|
|
|
+ item.custom_schedule?.service_type?.descritpion ||
|
|
|
+ t('provider.dashboard.opportunities.client_default'),
|
|
|
|
|
|
price: Number(
|
|
|
item.custom_schedule?.max_price || 0
|
|
|
).toFixed(2),
|
|
|
|
|
|
- distance: '0 km'
|
|
|
+ distance: 0
|
|
|
})
|
|
|
|
|
|
const goToOpportunityDetails = (item) => {
|
|
|
router.push({
|
|
|
name: 'OpportunityDetailsPage',
|
|
|
- params: {
|
|
|
- id: item.id
|
|
|
- }
|
|
|
+ params: { id: item.id }
|
|
|
})
|
|
|
}
|
|
|
|
|
|
const loadOpportunities = async () => {
|
|
|
loading.value = true
|
|
|
+
|
|
|
try {
|
|
|
const response = await getProviderOpportunities(
|
|
|
user.user.provider.id
|
|
|
)
|
|
|
- console.log('DETALHE DA OPORTUNIDADE', response)
|
|
|
|
|
|
- console.log('Oportunidades recebidas:', response)
|
|
|
opportunities.value = (response || []).map(normalizeOpportunity)
|
|
|
} catch (error) {
|
|
|
console.error('Erro ao buscar oportunidades:', error)
|
|
|
opportunities.value = []
|
|
|
-
|
|
|
} finally {
|
|
|
loading.value = false
|
|
|
}
|