|
|
@@ -0,0 +1,270 @@
|
|
|
+<template>
|
|
|
+ <q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
+ <q-card class="solicitation-dialog-card bg-surface shadow-card" :flat="false">
|
|
|
+
|
|
|
+ <template v-if="view === 'details'">
|
|
|
+ <div class="row justify-end q-pt-sm q-pr-sm">
|
|
|
+ <q-btn flat round dense icon="close" color="grey-6" size="sm" @click="onDialogCancel" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <q-card-section class="column items-center q-pt-sm q-pb-sm">
|
|
|
+ <q-avatar size="72px" class="q-mb-sm">
|
|
|
+ <img :src="solicitation.customer_photo || 'https://cdn.quasar.dev/img/avatar.png'" />
|
|
|
+ </q-avatar>
|
|
|
+
|
|
|
+ <div class="text-subtitle1 text-weight-bold text-text">{{ solicitation.client_name }}</div>
|
|
|
+
|
|
|
+ <div class="text-price q-mt-xs">{{ formatCurrency(solicitation.total_amount) }}</div>
|
|
|
+ <div class="text-caption text-grey-6">{{ periodLabel }}</div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="column items-center q-pt-none q-pb-sm text-text">
|
|
|
+ <div class="text-body2 text-center">
|
|
|
+ <span class="text-weight-bold">{{ weekdayLabel + ' ,' + dayMonthLabel }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="text-body2 text-center">
|
|
|
+ {{ $t('common.from') }} <strong>{{ solicitation.start_time?.slice(0, 5) }}</strong>
|
|
|
+ {{ $t('common.to') }} <strong>{{ solicitation.end_time?.slice(0, 5) }}</strong>
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="column items-center q-pt-none q-pb-xs">
|
|
|
+ <div class="row items-center q-gutter-x-xs">
|
|
|
+ <q-icon
|
|
|
+ :name="solicitation.offers_meal ? 'mdi-food' : 'mdi-food-off'"
|
|
|
+ :color="solicitation.offers_meal ? 'positive' : 'grey-5'"
|
|
|
+ size="18px"
|
|
|
+ />
|
|
|
+ <span class="text-body2 text-grey-7">
|
|
|
+ {{ solicitation.offers_meal
|
|
|
+ ? $t('provider.dashboard.solicitations.offers_meal')
|
|
|
+ : $t('provider.dashboard.solicitations.not_offers_meal') }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="column items-center q-pt-xs q-pb-sm text-text">
|
|
|
+ <div class="row items-center q-gutter-x-xs">
|
|
|
+ <q-icon name="mdi-map-marker" color="secondary" size="20px" />
|
|
|
+ <span class="text-body1 text-weight-bold">{{ solicitation.address?.district || 'N/A' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="text-caption text-grey-6 text-center q-mt-xs">
|
|
|
+ {{ $t('provider.dashboard.solicitations.distance_prefix') }}
|
|
|
+ <strong>{{ (solicitation.distance || 0) + ' km' }}</strong>
|
|
|
+ {{ $t('provider.dashboard.solicitations.distance_suffix') }}
|
|
|
+ </div>
|
|
|
+ <div class="q-mt-xs">
|
|
|
+ <span class="text-caption text-grey-6">{{ $t('provider.dashboard.solicitations.via_agenda_text') }} </span>
|
|
|
+ <span class="text-caption text-secondary text-weight-bold">{{ $t('provider.dashboard.solicitations.via_agenda') }}</span>
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-separator />
|
|
|
+
|
|
|
+ <q-card-section class="q-py-sm">
|
|
|
+ <div class="row justify-center q-gutter-x-md">
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ class="btn-action bg-grey-3 text-grey-8"
|
|
|
+ :label="$t('common.refuse')"
|
|
|
+ @click="view = 'confirm-reject'"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="secondary"
|
|
|
+ class="btn-action"
|
|
|
+ :label="$t('common.accept')"
|
|
|
+ @click="view = 'confirm-accept'"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="row justify-center q-mt-xs">
|
|
|
+ <q-btn flat no-caps color="grey-7" size="sm" :label="$t('common.actions.back')" @click="onDialogCancel" />
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <div class="q-pa-md">
|
|
|
+ <span class="text-caption text-warning text-weight-bold">{{ $t('provider.dashboard.solicitations.same_day_warning_label') }} </span>
|
|
|
+ <span class="text-caption text-grey-8">{{ $t('provider.dashboard.solicitations.same_day_warning') }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-else-if="view === 'confirm-accept'">
|
|
|
+ <q-card-section class="column items-center q-pt-xl q-pb-lg text-center">
|
|
|
+ <div class="confirm-title text-secondary text-weight-bold">
|
|
|
+ {{ $t('provider.dashboard.solicitations.confirm_accept') }}
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="q-pt-none q-pb-xl">
|
|
|
+ <div class="row justify-center q-gutter-x-md">
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="purple-5"
|
|
|
+ class="btn-action"
|
|
|
+ :label="$t('common.actions.back')"
|
|
|
+ @click="backFromConfirm"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="secondary"
|
|
|
+ class="btn-action"
|
|
|
+ :loading="loading"
|
|
|
+ :label="$t('common.accept')"
|
|
|
+ @click="confirmAccept"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-else-if="view === 'confirm-reject'">
|
|
|
+ <q-card-section class="column items-center q-pt-xl q-pb-md text-center">
|
|
|
+ <div class="confirm-title text-secondary text-weight-bold">
|
|
|
+ {{ $t('provider.dashboard.solicitations.confirm_reject') }}
|
|
|
+ </div>
|
|
|
+ <div class="q-mt-md text-body2 text-grey-7 confirm-tip">
|
|
|
+ <strong>{{ $t('provider.dashboard.solicitations.tip_label') }} </strong>
|
|
|
+ {{ $t('provider.dashboard.solicitations.reject_tip') }}
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="q-pt-none q-pb-xl">
|
|
|
+ <div class="row justify-center q-gutter-x-md">
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="purple-5"
|
|
|
+ class="btn-action"
|
|
|
+ :label="$t('common.actions.back')"
|
|
|
+ @click="backFromConfirm"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="secondary"
|
|
|
+ class="btn-action"
|
|
|
+ :loading="loading"
|
|
|
+ :label="$t('common.refuse')"
|
|
|
+ @click="confirmReject"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ </q-card>
|
|
|
+ </q-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed } from 'vue'
|
|
|
+import { useDialogPluginComponent } from 'quasar'
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
+import { formatCurrency } from 'src/helpers/utils'
|
|
|
+import { labelsPeriodTypes } from 'src/helpers/arraysOptions/labelsPeriodTypes.js'
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ solicitation: {
|
|
|
+ type: Object,
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ initialView: {
|
|
|
+ type: String,
|
|
|
+ default: 'details',
|
|
|
+ validator: (v) => ['details', 'confirm-accept', 'confirm-reject'].includes(v)
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const { t } = useI18n()
|
|
|
+const { dialogRef, onDialogHide, onDialogCancel, onDialogOK } = useDialogPluginComponent()
|
|
|
+
|
|
|
+const view = ref(props.initialView)
|
|
|
+const loading = ref(false)
|
|
|
+
|
|
|
+const periodLabel = computed(() => {
|
|
|
+ const found = labelsPeriodTypes.find(l => l.value == props.solicitation.period_type)
|
|
|
+ return found ? t(found.label) : ''
|
|
|
+})
|
|
|
+
|
|
|
+const parseLocalDate = (dateStr) => {
|
|
|
+ if (!dateStr) return null
|
|
|
+ const s = String(dateStr)
|
|
|
+ const iso = s.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
|
|
+ if (iso) return new Date(+iso[1], +iso[2] - 1, +iso[3])
|
|
|
+ const dmy = s.match(/^(\d{2})\/(\d{2})\/(\d{4})/)
|
|
|
+ if (dmy) return new Date(+dmy[3], +dmy[2] - 1, +dmy[1])
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
+const weekdayLabel = computed(() => {
|
|
|
+ const d = parseLocalDate(props.solicitation.date)
|
|
|
+ if (!d) return ''
|
|
|
+ const w = d.toLocaleDateString('pt-BR', { weekday: 'long' })
|
|
|
+ return w.charAt(0).toUpperCase() + w.slice(1)
|
|
|
+})
|
|
|
+
|
|
|
+const dayMonthLabel = computed(() => {
|
|
|
+ const d = parseLocalDate(props.solicitation.date)
|
|
|
+ if (!d) return ''
|
|
|
+ return d.toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' })
|
|
|
+})
|
|
|
+
|
|
|
+const backFromConfirm = () => {
|
|
|
+ if (props.initialView !== 'details') {
|
|
|
+ onDialogCancel()
|
|
|
+ } else {
|
|
|
+ view.value = 'details'
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const confirmAccept = () => {
|
|
|
+ loading.value = true
|
|
|
+ onDialogOK({ action: 'accept', id: props.solicitation.id })
|
|
|
+}
|
|
|
+
|
|
|
+const confirmReject = () => {
|
|
|
+ loading.value = true
|
|
|
+ onDialogOK({ action: 'reject', id: props.solicitation.id })
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.solicitation-dialog-card {
|
|
|
+ width: 320px;
|
|
|
+ max-width: 92vw;
|
|
|
+ border-radius: 20px !important;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.text-price {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: var(--q-secondary);
|
|
|
+}
|
|
|
+
|
|
|
+.btn-action {
|
|
|
+ min-width: 110px;
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+
|
|
|
+.confirm-title {
|
|
|
+ font-size: 20px;
|
|
|
+ line-height: 1.35;
|
|
|
+ padding: 0 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.confirm-tip {
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 1.5;
|
|
|
+ padding: 0 8px;
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|