|
@@ -1,20 +1,27 @@
|
|
|
<template>
|
|
<template>
|
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
- <q-card class="card-border bg-surface text-text time-card">
|
|
|
|
|
|
|
+ <q-card class="card-border bg-surface text-text time-card relative-position">
|
|
|
|
|
|
|
|
<q-btn
|
|
<q-btn
|
|
|
- flat round dense
|
|
|
|
|
- icon="mdi-close-circle-outline"
|
|
|
|
|
|
|
+ class="absolute-top-right close-button q-mt-sm q-mr-sm"
|
|
|
color="grey-5"
|
|
color="grey-5"
|
|
|
- class="absolute-top-right q-mt-sm q-mr-sm"
|
|
|
|
|
- @click="onDialogCancel"
|
|
|
|
|
|
|
+ dense
|
|
|
|
|
+ flat
|
|
|
|
|
+ icon="mdi-close-circle-outline"
|
|
|
|
|
+ round
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ @click.stop="handleClose"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
<q-card-section class="text-center q-pt-lg q-pb-xs">
|
|
<q-card-section class="text-center q-pt-lg q-pb-xs">
|
|
|
<div class="font16 fontbold text-text">
|
|
<div class="font16 fontbold text-text">
|
|
|
{{ serviceType.label }}
|
|
{{ serviceType.label }}
|
|
|
- <span class="text-grey-6">{{ '(' + serviceType.hoursCount + 'h)' }}</span>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <span class="text-grey-6">
|
|
|
|
|
+ {{ '(' + serviceType.hoursCount + 'h)' }}
|
|
|
|
|
+ </span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
<div class="font14 fontmedium text-grey-6 q-mt-xs">
|
|
<div class="font14 fontmedium text-grey-6 q-mt-xs">
|
|
|
{{ $t('scheduling_page.time_selection.subtitle') }}
|
|
{{ $t('scheduling_page.time_selection.subtitle') }}
|
|
|
</div>
|
|
</div>
|
|
@@ -29,12 +36,12 @@
|
|
|
>
|
|
>
|
|
|
<q-radio
|
|
<q-radio
|
|
|
v-model="selectedSlot"
|
|
v-model="selectedSlot"
|
|
|
- :val="slot.value"
|
|
|
|
|
- :label="slot.label"
|
|
|
|
|
- color="primary"
|
|
|
|
|
class="font12 fontbold text-primary"
|
|
class="font12 fontbold text-primary"
|
|
|
- keep-color
|
|
|
|
|
|
|
+ color="primary"
|
|
|
dense
|
|
dense
|
|
|
|
|
+ keep-color
|
|
|
|
|
+ :label="slot.label"
|
|
|
|
|
+ :val="slot.value"
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -42,28 +49,31 @@
|
|
|
|
|
|
|
|
<template v-if="hasMealSection">
|
|
<template v-if="hasMealSection">
|
|
|
<q-separator class="q-mx-md" />
|
|
<q-separator class="q-mx-md" />
|
|
|
|
|
+
|
|
|
<q-card-section class="q-py-sm">
|
|
<q-card-section class="q-py-sm">
|
|
|
<div class="font14 fontbold text-text q-mb-sm text-center">
|
|
<div class="font14 fontbold text-text q-mb-sm text-center">
|
|
|
{{ $t('scheduling_page.time_selection.meal_section') }}
|
|
{{ $t('scheduling_page.time_selection.meal_section') }}
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="column">
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <div class="meal-options column items-start">
|
|
|
<q-radio
|
|
<q-radio
|
|
|
v-model="selectedMeal"
|
|
v-model="selectedMeal"
|
|
|
- val="offer"
|
|
|
|
|
- :label="$t('scheduling_page.time_selection.meal_offer')"
|
|
|
|
|
- class="font12 fontbold text-primary q-mx-auto q-pb-sm"
|
|
|
|
|
|
|
+ class="font12 fontbold text-primary q-pb-sm"
|
|
|
color="primary"
|
|
color="primary"
|
|
|
- keep-color
|
|
|
|
|
dense
|
|
dense
|
|
|
|
|
+ keep-color
|
|
|
|
|
+ val="offer"
|
|
|
|
|
+ :label="$t('scheduling_page.time_selection.meal_offer')"
|
|
|
/>
|
|
/>
|
|
|
|
|
+
|
|
|
<q-radio
|
|
<q-radio
|
|
|
v-model="selectedMeal"
|
|
v-model="selectedMeal"
|
|
|
- val="no_offer"
|
|
|
|
|
- :label="$t('scheduling_page.time_selection.meal_no_offer')"
|
|
|
|
|
- class="font12 fontbold text-primary q-mx-auto q-pt-sm"
|
|
|
|
|
|
|
+ class="font12 fontbold text-primary q-pt-sm"
|
|
|
color="primary"
|
|
color="primary"
|
|
|
- keep-color
|
|
|
|
|
dense
|
|
dense
|
|
|
|
|
+ keep-color
|
|
|
|
|
+ val="no_offer"
|
|
|
|
|
+ :label="$t('scheduling_page.time_selection.meal_no_offer')"
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
</q-card-section>
|
|
</q-card-section>
|
|
@@ -71,14 +81,14 @@
|
|
|
|
|
|
|
|
<q-card-actions class="q-px-md q-pb-xs q-pt-sm">
|
|
<q-card-actions class="q-px-md q-pb-xs q-pt-sm">
|
|
|
<q-btn
|
|
<q-btn
|
|
|
- unelevated
|
|
|
|
|
- rounded
|
|
|
|
|
- no-caps
|
|
|
|
|
- :label="$t('scheduling_page.time_selection.continue')"
|
|
|
|
|
- :disable="!selectedSlot"
|
|
|
|
|
|
|
+ class="full-width"
|
|
|
color="secondary"
|
|
color="secondary"
|
|
|
|
|
+ no-caps
|
|
|
padding="4px 8px"
|
|
padding="4px 8px"
|
|
|
- class="full-width"
|
|
|
|
|
|
|
+ rounded
|
|
|
|
|
+ unelevated
|
|
|
|
|
+ :disable="!selectedSlot"
|
|
|
|
|
+ :label="$t('scheduling_page.time_selection.continue')"
|
|
|
@click="handleContinue"
|
|
@click="handleContinue"
|
|
|
/>
|
|
/>
|
|
|
</q-card-actions>
|
|
</q-card-actions>
|
|
@@ -86,33 +96,38 @@
|
|
|
<div v-if="pauseNote" class="text-center font12 fontmedium text-primary q-pb-md">
|
|
<div v-if="pauseNote" class="text-center font12 fontmedium text-primary q-pb-md">
|
|
|
{{ pauseNote }}
|
|
{{ pauseNote }}
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
</q-card>
|
|
</q-card>
|
|
|
</q-dialog>
|
|
</q-dialog>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref, computed } from 'vue';
|
|
|
|
|
import { useDialogPluginComponent } from 'quasar';
|
|
import { useDialogPluginComponent } from 'quasar';
|
|
|
|
|
+import { computed, ref } from 'vue';
|
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
|
- serviceType: { type: Object, required: true },
|
|
|
|
|
- provider: { type: Object, required: true },
|
|
|
|
|
- selectedDate: { type: String, required: true },
|
|
|
|
|
- partialBlocks: { type: Array, required: false, default: () => [] },
|
|
|
|
|
|
|
+ partialBlocks: { default: () => [], required: false, type: Array },
|
|
|
|
|
+ provider: { required: true, type: Object },
|
|
|
|
|
+ selectedDate: { required: true, type: String },
|
|
|
|
|
+ serviceType: { required: true, type: Object },
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
defineEmits([...useDialogPluginComponent.emits]);
|
|
defineEmits([...useDialogPluginComponent.emits]);
|
|
|
|
|
|
|
|
-const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent();
|
|
|
|
|
|
|
+const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
|
|
|
|
|
+
|
|
|
const { t } = useI18n();
|
|
const { t } = useI18n();
|
|
|
|
|
|
|
|
-const selectedSlot = ref(null);
|
|
|
|
|
const selectedMeal = ref(null);
|
|
const selectedMeal = ref(null);
|
|
|
|
|
+const selectedSlot = ref(null);
|
|
|
|
|
+
|
|
|
|
|
+const handleClose = () => {
|
|
|
|
|
+ dialogRef.value?.hide();
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
const handleContinue = () => {
|
|
const handleContinue = () => {
|
|
|
const slotObj = timeSlots.value.find(s => s.value === selectedSlot.value);
|
|
const slotObj = timeSlots.value.find(s => s.value === selectedSlot.value);
|
|
|
|
|
+
|
|
|
onDialogOK({
|
|
onDialogOK({
|
|
|
serviceType: props.serviceType,
|
|
serviceType: props.serviceType,
|
|
|
date: props.selectedDate,
|
|
date: props.selectedDate,
|
|
@@ -121,41 +136,56 @@ const handleContinue = () => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const hasMealSection = computed(() =>
|
|
|
|
|
+ props.serviceType.hoursCount >= 6
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+const pauseNote = computed(() => {
|
|
|
|
|
+ const map = { 8: t('scheduling_page.time_selection.pause_note_8h'), 6: t('scheduling_page.time_selection.pause_note_6h'), 4: t('scheduling_page.time_selection.pause_note_4h') };
|
|
|
|
|
+
|
|
|
|
|
+ return map[props.serviceType.hoursCount] ?? null;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
const slotConflicts = (slotStart, slotEnd, blocks) =>
|
|
const slotConflicts = (slotStart, slotEnd, blocks) =>
|
|
|
blocks.some(b => {
|
|
blocks.some(b => {
|
|
|
const blockStart = parseInt(b.init_hour);
|
|
const blockStart = parseInt(b.init_hour);
|
|
|
- const blockEnd = parseInt(b.end_hour);
|
|
|
|
|
|
|
+ const blockEnd = parseInt(b.end_hour);
|
|
|
return slotEnd >= blockStart && slotStart <= blockEnd;
|
|
return slotEnd >= blockStart && slotStart <= blockEnd;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const timeSlots = computed(() => {
|
|
const timeSlots = computed(() => {
|
|
|
const h = props.serviceType.hoursCount;
|
|
const h = props.serviceType.hoursCount;
|
|
|
|
|
+
|
|
|
const slots = [];
|
|
const slots = [];
|
|
|
|
|
+
|
|
|
for (let start = 7; start + h <= 20; start++) {
|
|
for (let start = 7; start + h <= 20; start++) {
|
|
|
const end = start + h;
|
|
const end = start + h;
|
|
|
|
|
+
|
|
|
if (slotConflicts(start, end, props.partialBlocks)) continue;
|
|
if (slotConflicts(start, end, props.partialBlocks)) continue;
|
|
|
|
|
+
|
|
|
slots.push({
|
|
slots.push({
|
|
|
- value: `${start}-${end}`,
|
|
|
|
|
- startHour: start,
|
|
|
|
|
endHour: end,
|
|
endHour: end,
|
|
|
label: `${start}h às ${end}h`,
|
|
label: `${start}h às ${end}h`,
|
|
|
|
|
+ startHour: start,
|
|
|
|
|
+ value: `${start}-${end}`,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
return slots;
|
|
return slots;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const hasMealSection = computed(() =>
|
|
|
|
|
- props.serviceType.hoursCount >= 6
|
|
|
|
|
-);
|
|
|
|
|
-
|
|
|
|
|
-const pauseNote = computed(() => {
|
|
|
|
|
- const map = { 8: t('scheduling_page.time_selection.pause_note_8h'), 6: t('scheduling_page.time_selection.pause_note_6h'), 4: t('scheduling_page.time_selection.pause_note_4h') };
|
|
|
|
|
- return map[props.serviceType.hoursCount] ?? null;
|
|
|
|
|
-});
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
|
|
|
+.close-button {
|
|
|
|
|
+ z-index: 2;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.time-card {
|
|
.time-card {
|
|
|
width: min(88vw, 360px);
|
|
width: min(88vw, 360px);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+.meal-options {
|
|
|
|
|
+ margin-inline: auto;
|
|
|
|
|
+ width: fit-content;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|