| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- <template>
- <div class="scroll-wrapper">
- <div class="scroll-track q-pb-md q-px-md">
- <q-card v-for="item in data" :key="item.id" class="proposal-card shadow-card" :flat="false">
- <div class="row no-wrap items-center">
- <q-avatar :style="avatarColors[item.id % avatarColors.length]" class="text-weight-bold q-mx-auto">
- <img v-if="item.provider_photo" :src="item.provider_photo" style="object-fit:cover;border-radius:50%;" />
- <span v-else>{{ item.provider_name?.slice(0, 1) ?? '—' }}</span>
- </q-avatar>
- <!-- LABEL -->
- <div class="type">
- {{ $t('dashboard_client.client_proposals.candidate') }} <span>{{
- $t('dashboard_client.client_proposals.custom') }}</span>
- </div>
- <div class="content">
- <!-- HEADER -->
- <div class="row justify-between items-center text-text ">
- <div>
- <div class="name">
- {{ item.provider_name }}
- <span class="age">{{ $t('dashboard_client.client_proposals.age', { idade: item.idade }) }}</span>
- </div>
- <span class="rating">
- <q-icon name="star" size="11px" />
- {{ item.average_rating }}
- </span>
- </div>
- </div>
- <!-- DATA -->
- <div class="datetime">
- {{ formatDate(item.date) }} <br />
- {{ $t('dashboard_client.next_schedules.from') }} {{ formatTime(item.start_time) }} {{
- $t('dashboard_client.next_schedules.to') }} {{ formatTime(item.end_time) }}
- </div>
- <!-- PREÇO -->
- <div class="price">
- {{ filterCurrency(chooseprice(item.period_type, item.daily_price_8h)) }}
- <span class="text-price-label col-6">
- {{ formatLabelByPeriodType(item.period_type) }}
- </span>
- <span class="distance">
- {{ $t('dashboard_client.client_proposals.distance') }} {{ (item.distance_km ?? '--') + ' km' }}
- </span>
- </div>
- <!-- BOTÕES -->
- <div class="actions">
- <q-btn label="recusar" flat class="btn-reject" @click="() => handleRefuseProposal(item.id)" />
- <q-btn label="aceitar" class="btn-accept" @click="() => handleAcceptProposal(item.id)" />
- </div>
- </div>
- </div>
- </q-card>
- </div>
- </div>
- </template>
- <script setup>
- import { acceptProposal, refuseProposal } from 'src/api/customSchedules'
- import { chooseprice, formatLabelByPeriodType, filterCurrency } from 'src/helpers/utils'
- defineProps({
- data: {
- type: Array,
- default: () => []
- }
- })
- const emit = defineEmits(['refreshData'])
- const avatarColors = [
- { background: '#ffd5df', color: '#932e57' },
- { background: '#d7e8ff', color: '#2158a8' },
- { background: '#dfd', color: '#2a7a3b' },
- { background: '#ffe5cc', color: '#8a4500' },
- ];
- const formatTime = (time) => {
- if (!time) return '';
- const [hour, minute] = time.split(':');
- return `${hour}:${minute}`;
- };
- const formatDate = (date) => {
- if (!date) return '';
- const d = new Date(date);
- const weekday = d.toLocaleDateString('pt-BR', {
- weekday: 'long'
- });
- const day = String(d.getDate()).padStart(2, '0');
- const month = String(d.getMonth() + 1).padStart(2, '0');
- return `${weekday}, ${day}-${month}`;
- };
- const handleRefuseProposal = async (proposalId) => {
- // isLoading.value = true
- try {
- await refuseProposal(proposalId)
-
- // await loadProposals()
- emit('refreshData')
- } catch (error) {
- console.log(error);
- } finally {
- // isLoading.value = false
- }
- }
- const handleAcceptProposal = async (proposalId) => {
- // isLoading.value = true
- try {
- await acceptProposal(proposalId)
- emit('refreshData')
- // onDialogOK()
- } catch (error) {
- console.log(error);
- } finally {
- // isLoading.value = false
- }
- }
- </script>
- <style scoped lang="scss">
- .scroll-wrapper {
- overflow-x: auto;
- scrollbar-width: none;
- }
- .scroll-track {
- display: flex;
- gap: 12px;
- }
- .scroll-wrapper::-webkit-scrollbar {
- display: none;
- }
- .proposal-card {
- position: relative;
- min-width: 330px;
- max-width: 330px;
- min-height: 115px;
- border-radius: 18px;
- padding: 12px;
- background: white;
- flex-shrink: 0;
- }
- /* alinhar topo */
- .proposal-card .row:first-child {
- align-items: flex-start !important;
- }
- .row.justify-between {
- align-items: flex-start !important;
- padding-right: 70px; // espaço pro preço
- }
- .content {
- width: 100%;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- gap: 2px;
- }
- /* nome */
- .name {
- font-size: 14px;
- font-weight: 600;
- color: #5a3eff;
- }
- .age {
- font-size: 11px;
- color: #999;
- font-weight: 400;
- }
- /* rating */
- .rating {
- font-size: 11px;
- color: #444;
- }
- /* distância */
- .distance {
- font-size: 11px;
- color: #777;
- font-weight: 500;
- }
- .price .distance {
- font-size: 9px; // 👈 menor
- color: #777;
- margin-top: 4px; // 👈 desce um pouco
- font-weight: 400;
- }
- /* data */
- .datetime {
- font-size: 10px;
- color: #8f8f8f;
- margin-top: 2px;
- line-height: 1.2;
- }
- /* preço topo direito */
- .price {
- position: absolute;
- top: 12px;
- right: 12px;
- font-size: 15px;
- font-weight: 700;
- color: #6b4eff;
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- }
- .text-price-label {
- font-size: 10px;
- color: #999;
- font-weight: 400;
- }
- .type {
- position: absolute;
- left: 12px;
- top: 72px;
- font-size: 10px;
- color: #6b4eff;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- line-height: 1.1;
- }
- .type span {
- font-weight: 600;
- }
- .type span {
- font-weight: 600;
- }
- /* avatar alinhado */
- .q-avatar {
- margin-left: 0 !important;
- margin-right: 10px !important;
- }
- /* botões */
- .actions {
- display: flex;
- justify-content: flex-end;
- gap: 8px;
- margin-top: auto;
- }
- .btn-reject {
- background: #eee6ff;
- color: #6b4eff;
- border-radius: 20px;
- padding: 3px 12px;
- font-size: 11px;
- }
- .btn-accept {
- background: linear-gradient(90deg, #6b4eff, #9f6bff);
- color: white;
- border-radius: 20px;
- padding: 3px 12px;
- font-size: 11px;
- }
- </style>
|