|
|
@@ -132,7 +132,7 @@ import { getProviderWorkingDays, getProviderBlockedDays } from 'src/api/provider
|
|
|
import { getProviderReceivedReviews } from 'src/api/review';
|
|
|
import ServiceSelectionSheet from './ServiceSelectionSheet.vue';
|
|
|
import ServiceTimeSelectionDialog from './ServiceTimeSelectionDialog.vue';
|
|
|
-import OrderSummaryDialog from './OrderSummaryDialog.vue';
|
|
|
+import OrderSummaryDialog from './OrderSummaryDialog.vue'
|
|
|
|
|
|
const props = defineProps({
|
|
|
provider: {
|
|
|
@@ -146,89 +146,160 @@ defineEmits([...useDialogPluginComponent.emits]);
|
|
|
const { dialogRef } = useDialogPluginComponent();
|
|
|
const $q = useQuasar();
|
|
|
|
|
|
+const selectedDate = ref(null);
|
|
|
+const workingDays = ref([]);
|
|
|
+const blockedDays = ref([]);
|
|
|
+const loadingAvailability = ref(true);
|
|
|
+
|
|
|
+const reviews = ref([]);
|
|
|
+const loadingReviews = ref(true);
|
|
|
+
|
|
|
+
|
|
|
+const bookings = ref([]);
|
|
|
+
|
|
|
+
|
|
|
+const availableWeekDays = computed(() =>
|
|
|
+ [...new Set(workingDays.value.map((wd) => wd.day))]
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+const blockedDateSet = computed(() =>
|
|
|
+ new Set(
|
|
|
+ blockedDays.value
|
|
|
+ .filter((bd) => bd.period === 'all')
|
|
|
+ .map((bd) => bd.date)
|
|
|
+ )
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+const getWeekRange = (dateStr) => {
|
|
|
+ const d = new Date(`${dateStr}T12:00:00`)
|
|
|
+ const day = d.getDay()
|
|
|
+
|
|
|
+ const start = new Date(d)
|
|
|
+ start.setDate(d.getDate() - day)
|
|
|
+
|
|
|
+ const end = new Date(start)
|
|
|
+ end.setDate(start.getDate() + 6)
|
|
|
+
|
|
|
+ return {
|
|
|
+ start: start.toISOString().split('T')[0],
|
|
|
+ end: end.toISOString().split('T')[0]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const wouldExceedWeekLimit = (selectedDate) => {
|
|
|
+ const { start, end } = getWeekRange(selectedDate)
|
|
|
+
|
|
|
+ const count = bookings.value.filter(b => {
|
|
|
+ if (!b.date) return false
|
|
|
+
|
|
|
+ const normalizedDate = b.date.replace(/\//g, '-')
|
|
|
+
|
|
|
+ return normalizedDate >= start && normalizedDate <= end
|
|
|
+ }).length
|
|
|
+
|
|
|
+ return count >= 2
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const dateOptions = (d) => {
|
|
|
+ const today = date.formatDate(new Date(), 'YYYY/MM/DD');
|
|
|
+ if (d < today) return false;
|
|
|
+
|
|
|
+ const raw = d.replace(/\//g, '-');
|
|
|
+ const parsed = new Date(`${raw}T12:00:00`);
|
|
|
+ const dayOfWeek = parsed.getDay();
|
|
|
+
|
|
|
+ const isWorkingDay = availableWeekDays.value.includes(dayOfWeek);
|
|
|
+ const isBlocked = blockedDateSet.value.has(raw);
|
|
|
+
|
|
|
+ if (!isWorkingDay || isBlocked) return false;
|
|
|
+
|
|
|
+if (wouldExceedWeekLimit(raw)) return false;
|
|
|
+
|
|
|
+return true;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
const onDateSelected = (val) => {
|
|
|
if (!val) return;
|
|
|
+
|
|
|
selectedDate.value = null;
|
|
|
const valFormatted = val.replace(/\//g, '-');
|
|
|
|
|
|
+
|
|
|
const blocksOfDate = blockedDays.value.filter(
|
|
|
(bd) => bd.date === valFormatted && bd.period !== 'all'
|
|
|
);
|
|
|
|
|
|
+
|
|
|
const dayOfWeek = new Date(`${valFormatted}T12:00:00`).getDay();
|
|
|
+
|
|
|
const dayPeriods = workingDays.value
|
|
|
.filter((wd) => wd.day === dayOfWeek)
|
|
|
.map((wd) => wd.period);
|
|
|
|
|
|
const workingDayBlocks = [];
|
|
|
+
|
|
|
if (!dayPeriods.includes('afternoon')) {
|
|
|
workingDayBlocks.push({ init_hour: '14:00:00', end_hour: '20:00:00' });
|
|
|
}
|
|
|
+
|
|
|
if (!dayPeriods.includes('morning')) {
|
|
|
- workingDayBlocks.push({ init_hour: '7:00:00', end_hour: '13:00:00' });
|
|
|
+ workingDayBlocks.push({ init_hour: '07:00:00', end_hour: '13:00:00' });
|
|
|
}
|
|
|
|
|
|
- const partialBlocks = [...blocksOfDate, ...workingDayBlocks];
|
|
|
+
|
|
|
+ const existingBookingBlocks = bookings.value
|
|
|
+ .filter(b => b.date.replace(/\//g, '-') === valFormatted)
|
|
|
+ .map(b => ({
|
|
|
+ init_hour: `${b.slot.startHour}:00:00`,
|
|
|
+ end_hour: `${b.slot.endHour}:00:00`
|
|
|
+ }));
|
|
|
+
|
|
|
+
|
|
|
+ const partialBlocks = [
|
|
|
+ ...blocksOfDate,
|
|
|
+ ...workingDayBlocks,
|
|
|
+ ...existingBookingBlocks
|
|
|
+ ];
|
|
|
+
|
|
|
+ // fluxo
|
|
|
+ $q.dialog({
|
|
|
+ component: ServiceSelectionSheet,
|
|
|
+ componentProps: {
|
|
|
+ provider: props.provider,
|
|
|
+ selectedDate: val,
|
|
|
+ partialBlocks
|
|
|
+ },
|
|
|
+}).onOk(({ serviceType, date: date_, provider: prov }) => {
|
|
|
|
|
|
$q.dialog({
|
|
|
- component: ServiceSelectionSheet,
|
|
|
- componentProps: { provider: props.provider, selectedDate: val, partialBlocks },
|
|
|
- }).onOk(({ serviceType, date: date_, provider: prov }) => {
|
|
|
- $q.dialog({
|
|
|
- component: ServiceTimeSelectionDialog,
|
|
|
- componentProps: { serviceType, selectedDate: date_, provider: prov, partialBlocks },
|
|
|
- }).onOk((booking) => {
|
|
|
- $q.dialog({
|
|
|
- component: OrderSummaryDialog,
|
|
|
- componentProps: { provider: props.provider, initialBooking: booking },
|
|
|
- });
|
|
|
- });
|
|
|
- });
|
|
|
-};
|
|
|
+ component: ServiceTimeSelectionDialog,
|
|
|
+ componentProps: {
|
|
|
+ serviceType,
|
|
|
+ selectedDate: date_,
|
|
|
+ provider: prov,
|
|
|
+ partialBlocks
|
|
|
+ },
|
|
|
+ }).onOk((booking) => {
|
|
|
|
|
|
-const selectedDate = ref(null);
|
|
|
-const workingDays = ref([]);
|
|
|
-const blockedDays = ref([]);
|
|
|
-const loadingAvailability = ref(true);
|
|
|
+ bookings.value.push(booking);
|
|
|
|
|
|
-const reviews = ref([]);
|
|
|
-const loadingReviews = ref(true);
|
|
|
+ $q.dialog({
|
|
|
+ component: OrderSummaryDialog,
|
|
|
+ componentProps: {
|
|
|
+ provider: props.provider,
|
|
|
+ initialBooking: booking
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
-const avatarColors = [
|
|
|
- { background: '#ffd5df', color: '#932e57' },
|
|
|
- { background: '#d7e8ff', color: '#2158a8' },
|
|
|
- { background: '#dfd', color: '#2a7a3b' },
|
|
|
- { background: '#ffe5cc', color: '#8a4500' },
|
|
|
-];
|
|
|
+ });
|
|
|
|
|
|
-const avatarStyle = computed(() => {
|
|
|
- const idx = (props.provider?.provider_id ?? 0) % avatarColors.length;
|
|
|
- return avatarColors[idx];
|
|
|
});
|
|
|
-
|
|
|
-const clientAvatarStyle = (review) => {
|
|
|
- const idx = (review.id ?? 0) % avatarColors.length;
|
|
|
- return avatarColors[idx];
|
|
|
};
|
|
|
|
|
|
-const availableWeekDays = computed(() =>
|
|
|
- [...new Set(workingDays.value.map((wd) => wd.day))]
|
|
|
-);
|
|
|
-
|
|
|
-const blockedDateSet = computed(() =>
|
|
|
- new Set(blockedDays.value.map((bd) => bd.date && bd.period == 'all'))
|
|
|
-);
|
|
|
-
|
|
|
-const dateOptions = (d) => {
|
|
|
- const today = date.formatDate(new Date(), 'YYYY/MM/DD');
|
|
|
- if (d < today) return false;
|
|
|
- const raw = d.replace(/\//g, '-');
|
|
|
- const parsed = new Date(`${raw}T12:00:00`);
|
|
|
- const dayOfWeek = parsed.getDay();
|
|
|
- const isWorkingDay = availableWeekDays.value.includes(dayOfWeek);
|
|
|
- const isBlocked = blockedDateSet.value.has(raw);
|
|
|
- return isWorkingDay && !isBlocked;
|
|
|
-};
|
|
|
|
|
|
const loadAvailability = async () => {
|
|
|
loadingAvailability.value = true;
|
|
|
@@ -236,6 +307,7 @@ const loadAvailability = async () => {
|
|
|
const [wd, bd] = await Promise.all([
|
|
|
getProviderWorkingDays(props.provider.provider_id),
|
|
|
getProviderBlockedDays(props.provider.provider_id),
|
|
|
+ // getProviderWeekDatesBlocks(props.provider_id, provider.client_id)
|
|
|
]);
|
|
|
workingDays.value = wd ?? [];
|
|
|
blockedDays.value = bd ?? [];
|
|
|
@@ -247,6 +319,7 @@ const loadAvailability = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+
|
|
|
const loadReviews = async () => {
|
|
|
loadingReviews.value = true;
|
|
|
try {
|
|
|
@@ -260,7 +333,8 @@ const loadReviews = async () => {
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
- Promise.all([loadAvailability(), loadReviews()]);
|
|
|
+ loadAvailability();
|
|
|
+ loadReviews();
|
|
|
});
|
|
|
</script>
|
|
|
|