| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- <template>
- <div class="q-mx-md q-mb-md">
- <div class="section-title gradient-diarista q-mb-sm">{{ $t('provider.dashboard.next_schedules.title') }}</div>
- <div class="scroll-wrapper">
- <div class="scroll-track">
- <q-card
- v-for="item in data"
- :key="item.id"
- class="schedule-card card-border shadow-card bg-surface"
- :flat="false"
- >
- <q-card-section class="q-pa-sm">
- <div class="row no-wrap items-center q-gutter-x-sm">
- <q-avatar size="48px">
- <img v-if="item.customer_photo" :src="item.customer_photo" style="object-fit:cover" />
- <span v-else class="text-weight-bold full-width full-height flex flex-center" :style="avatarColors[item.id % avatarColors.length]" style="font-size:14px;border-radius:50%">{{ (item.customer_name ?? item.client_name)?.slice(0,2).toUpperCase() ?? '??' }}</span>
- </q-avatar>
- <div class="column flex-1">
- <div class="row items-center q-gutter-x-xs">
- <span class="text-name ellipsis">{{ item.customer_name ?? item.client_name }}</span>
- <div v-if="item.customer_rating" class="row items-center">
- <q-icon name="mdi-star" color="warning" size="14px" />
- <span class="text-rating text-text">{{ item.customer_rating }}</span>
- </div>
- </div>
- <div class="row items-center no-wrap">
- <span class="text-schedule-date-bold">{{ formatWeekday(item.date) }}</span>
- <span class="text-schedule-date-regular">{{ ', ' + formatDayMonth(item.date) }}</span>
- </div>
- <div class="text-schedule-date-regular">
- {{ $t('common.from') }}
- <span class="text-schedule-date-bold">{{ item.start_time?.slice(0, 5) }}</span>
- {{ $t('common.to') }}
- <span class="text-schedule-date-bold">{{ item.end_time?.slice(0, 5) }}</span>
- </div>
- </div>
- <div class="column items-end text-text">
- <div class="text-price">{{ formatCurrency(item.total_amount) }}</div>
- <div class="text-type">{{ t(labelsPeriodTypes.find(label => label.value == item.period_type)?.label) }}</div>
- <div class="text-distance">{{ item.distance_km ?? 0 }}{{ $t('common.km') }}</div>
- </div>
- </div>
- <div class="row q-mt-md items-center text-text text-caption q-px-xs">
- <div class="col ellipsis text-grey-7">
- {{ formatAddress(item.address) || 'N/A' }}
- </div>
- <q-icon name="mdi-content-copy" color="primary" size="16px" class="q-ml-xs" @click="copyAddress(item.address)"/>
- </div>
- <div class="row q-mt-sm items-center">
- <q-btn
- flat
- no-caps
- color="primary"
- size="sm"
- class="col-auto q-px-none btn-details"
- :label="$t('provider.dashboard.next_schedules.details')"
- @click="emit('view-details', item)"
- />
- <q-space />
- <div class="row items-center q-gutter-x-xs text-grey-7" style="font-size: 11px;">
- <q-icon
- :name="item.offers_meal ? 'mdi-silverware' : 'mdi-close-outline'"
- :color="item.offers_meal ? 'secondary' : 'grey-5'"
- size="14px"
- />
- <span :class="item.offers_meal ? 'text-weight-medium' : ''">
- {{ item.offers_meal ? $t('provider.dashboard.next_schedules.offers_meal') : $t('provider.dashboard.next_schedules.no_meal') }}
- </span>
- </div>
- </div>
- </q-card-section>
- </q-card>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { useI18n } from 'vue-i18n';
- import { formatCurrency } from 'src/helpers/utils';
- import { labelsPeriodTypes } from 'src/helpers/arraysOptions/labelsPeriodTypes.js';
- import { useQuasar } from 'quasar';
- import { formatAddress } from 'src/helpers/utils';
- defineProps({ data: { type: Array, default: () => [] } });
- const emit = defineEmits(['view-details']);
- const t = useI18n().t;
- const $q = useQuasar();
- const avatarColors = [
- { background: '#ffd5df', color: '#932e57' },
- { background: '#d7e8ff', color: '#2158a8' },
- { background: '#dfd', color: '#2a7a3b' },
- { background: '#ffe5cc', color: '#8a4500' },
- ];
- const formatWeekday = (iso) => {
- if (!iso) return '';
- const d = new Date(iso);
- const w = d.toLocaleDateString('pt-BR', { weekday: 'long' });
- return w.charAt(0).toUpperCase() + w.slice(1);
- };
- const formatDayMonth = (iso) => {
- if (!iso) return '';
- return new Date(iso).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' });
- };
- const copyAddress = (address) => {
- const formatted = formatAddress(address);
- if (formatted) {
- navigator.clipboard.writeText(formatted);
- }
- $q.notify({ message: t('provider.dashboard.next_schedules.address_copied'), color: 'positive' });
- };
- </script>
- <style scoped lang="scss">
- .scroll-wrapper { overflow: hidden; }
- .scroll-track {
- display: flex;
- flex-direction: row;
- gap: 12px;
- overflow-x: auto;
- overscroll-behavior-x: contain;
- scroll-snap-type: x proximity;
- padding-bottom: 8px;
- &::-webkit-scrollbar { display: none; }
- &::after { content: ''; flex: 0 0 1px; }
- }
- .schedule-card {
- min-width: 85vw;
- border-radius: 12px;
- }
- .text-name {
- font-weight: 700;
- color: #3a3a4a;
- }
- .text-rating {
- font-size: 12px;
- font-weight: 600;
- }
- .text-schedule-date-bold {
- font-family: "Inter", sans-serif;
- font-size: 11px;
- font-weight: 700;
- color: #3a3a4a;
- }
- .text-schedule-date-regular {
- font-family: "Inter", sans-serif;
- font-size: 11px;
- font-weight: 400;
- color: #666;
- }
- .text-date, .text-time, .text-type, .text-region, .text-distance {
- font-size: 11px;
- color: #666;
- }
- .text-price {
- font-weight: 700;
- color: #3a3a4a;
- font-size: 14px;
- }
- .btn-details {
- font-weight: 700;
- font-size: 13px;
- }
- .flex-1 {
- flex: 1;
- min-width: 0;
- }
- </style>
|