| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- <template>
- <q-dialog
- ref="dialogRef"
- position="bottom"
- @hide="onDialogHide"
- >
- <q-card class="bg-surface text-text full-width sheet-card">
- <q-card-section class="row items-center q-pb-none">
- <q-space />
- <q-btn
- color="grey-6"
- dense
- flat
- icon="mdi-close-circle-outline"
- round
- @click="onDialogCancel"
- />
- </q-card-section>
- <q-separator class="q-mt-sm" />
- <q-card-section class="q-pt-sm q-pb-md">
- <div v-if="availableServiceTypes.length === 0" class="text-center text-grey-6 text-body2 q-py-md">
- {{ $t('scheduling_page.no_slots_available') }}
- </div>
- <div
- v-for="type in availableServiceTypes"
- :key="type.key"
- class="row items-center no-wrap q-py-sm"
- >
- <div class="col">
- <div class="row items-center no-wrap q-gutter-x-xs">
- <span class="font14 fontbold text-text">
- {{ type.label }}
- </span>
- <q-btn
- color="primary"
- dense
- flat
- icon="mdi-information-outline"
- size="xs"
- @click="openInfo(type)"
- />
- </div>
- <div class="font12 fontmedium text-grey-6">
- {{ type.hours }}
- </div>
- </div>
- <div class="font16 fontbold text-text q-mx-md" style="white-space: nowrap;">
- {{ type.price != null ? formatPrice(type.price) : $t('scheduling_page.no_price') }}
- </div>
- <div class="row no-wrap q-gutter-x-xs">
- <q-btn
- color="secondary"
- no-caps
- padding="2px 12px"
- rounded
- size="md"
- unelevated
- :disable="type.price == null"
- :label="$t('scheduling_page.book')"
- @click="onDialogOK({ action: 'book', serviceType: type, date: selectedDate, provider })"
- />
- <q-btn
- color="primary"
- icon="mdi-cart-plus"
- outline
- round
- size="md"
- :disable="type.price == null"
- @click="onDialogOK({ action: 'cart', serviceType: type, date: selectedDate, provider })"
- >
- <q-tooltip>
- {{ $t('schedule_cart.add_to_cart') }}
- </q-tooltip>
- </q-btn>
- </div>
- </div>
- </q-card-section>
- </q-card>
- </q-dialog>
- </template>
- <script setup>
- import { computed } from 'vue';
- import { useDialogPluginComponent, useQuasar } from 'quasar';
- import { useI18n } from 'vue-i18n';
- import ServiceTypeInfoDialog from './ServiceTypeInfoDialog.vue';
- const props = defineProps({
- partialBlocks: { type: Array, required: false, default: () => [] },
- provider: { type: Object, required: true },
- selectedDate: { type: String, required: true },
- });
- defineEmits([...useDialogPluginComponent.emits]);
- const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent();
- const $q = useQuasar();
- const { t } = useI18n();
- const availableServiceTypes = computed(() =>
- [
- {
- description: t('scheduling_page.service_types.integral.description'),
- hours: t('scheduling_page.service_types.integral.hours'),
- hoursCount: 8,
- key: 'integral',
- label: t('scheduling_page.service_types.integral.label'),
- price: props.provider?.daily_price_8h ?? null,
- },
- {
- description: t('scheduling_page.service_types.padrao.description'),
- hours: t('scheduling_page.service_types.padrao.hours'),
- hoursCount: 6,
- key: 'padrao',
- label: t('scheduling_page.service_types.padrao.label'),
- price: props.provider?.daily_price_6h ?? null,
- },
- {
- description: t('scheduling_page.service_types.meio_periodo.description'),
- hours: t('scheduling_page.service_types.meio_periodo.hours'),
- hoursCount: 4,
- key: 'meio_periodo',
- label: t('scheduling_page.service_types.meio_periodo.label'),
- price: props.provider?.daily_price_4h ?? null,
- },
- {
- description: t('scheduling_page.service_types.diaria_rapida.description'),
- hours: t('scheduling_page.service_types.diaria_rapida.hours'),
- hoursCount: 2,
- key: 'diaria_rapida',
- label: t('scheduling_page.service_types.diaria_rapida.label'),
- price: props.provider?.daily_price_2h ?? null,
- },
- ].filter(type => hasValidSlots(type.hoursCount))
- );
- const formatPrice = (value) =>
- Number(value).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
- const hasValidSlots = (hoursCount) => {
- for (let s = 7; s + hoursCount <= 20; s++) {
- if (!slotConflicts(s, s + hoursCount, props.partialBlocks)) return true;
- }
- return false;
- };
- const openInfo = (type) => {
- $q.dialog({ component: ServiceTypeInfoDialog, componentProps: { serviceType: type } });
- };
- const slotConflicts = (slotStart, slotEnd, blocks) =>
- blocks.some(b => {
- const blockEnd = parseInt(b.end_hour);
- const blockStart = parseInt(b.init_hour);
- return slotEnd >= blockStart && slotStart <= blockEnd;
- });
- </script>
- <style scoped lang="scss">
- .sheet-card {
- border-radius: 20px 20px 0 0;
- }
- </style>
|