update rezervasion
This commit is contained in:
@@ -33,6 +33,13 @@ export function serviceHasActiveClassPrices(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isServiceBookableForClass(
|
||||||
|
service: BusinessService,
|
||||||
|
classId: string,
|
||||||
|
): boolean {
|
||||||
|
return service.isActive && !!getClassPriceForService(service, classId);
|
||||||
|
}
|
||||||
|
|
||||||
export function isServiceBookable(
|
export function isServiceBookable(
|
||||||
service: BusinessService,
|
service: BusinessService,
|
||||||
classesEnabled: boolean,
|
classesEnabled: boolean,
|
||||||
@@ -47,7 +54,13 @@ export function servicePriceLabel(
|
|||||||
service: BusinessService,
|
service: BusinessService,
|
||||||
classesEnabled: boolean,
|
classesEnabled: boolean,
|
||||||
classes: BusinessServiceClass[],
|
classes: BusinessServiceClass[],
|
||||||
|
classId?: string | null,
|
||||||
): string {
|
): string {
|
||||||
|
if (classId) {
|
||||||
|
const price = resolvedServicePrice(service, classId);
|
||||||
|
return price ? `${formatPriceToman(price)} تومان` : 'قیمت تعیین نشده';
|
||||||
|
}
|
||||||
|
|
||||||
if (!usesServiceClasses(classesEnabled, classes)) {
|
if (!usesServiceClasses(classesEnabled, classes)) {
|
||||||
return `${formatPriceToman(service.price)} تومان`;
|
return `${formatPriceToman(service.price)} تومان`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,88 +60,140 @@
|
|||||||
>
|
>
|
||||||
{{ servicesError }}
|
{{ servicesError }}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<template v-else>
|
||||||
v-else-if="!bookableServices.length"
|
<div
|
||||||
class="rounded-xl border border-dashed border-border p-4 text-center text-sm text-muted"
|
v-if="requiresServiceClass && canBook"
|
||||||
>
|
class="mb-4 space-y-2 rounded-2xl border border-border bg-surface-2 p-4"
|
||||||
{{
|
|
||||||
services.length
|
|
||||||
? 'خدمات این کسبوکار هنوز برای رزرو آماده نیست.'
|
|
||||||
: 'هنوز خدمتی برای این کسبوکار ثبت نشده است.'
|
|
||||||
}}
|
|
||||||
<span v-if="auth.isBusinessOwner" class="mt-2 block">
|
|
||||||
از بخش «کسبوکار» در منو، خدمات و قیمت را اضافه کنید.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p v-else-if="canBook" class="mb-3 text-xs text-muted">
|
|
||||||
خدمات مورد نظر را انتخاب کنید، سپس زمان مراجعه را تعیین کنید.
|
|
||||||
</p>
|
|
||||||
<ul v-if="bookableServices.length" class="grid grid-cols-2 gap-3">
|
|
||||||
<li
|
|
||||||
v-for="svc in bookableServices"
|
|
||||||
:key="svc.id"
|
|
||||||
class="flex flex-col items-center rounded-2xl border p-3 text-center transition"
|
|
||||||
:class="
|
|
||||||
canBook && isServiceSelected(svc.id)
|
|
||||||
? 'border-brand-500 bg-brand-500/10'
|
|
||||||
: 'border-border bg-surface-2'
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<label
|
<p class="text-sm font-medium text-text">۱. کلاس خودرو را انتخاب کنید</p>
|
||||||
v-if="canBook"
|
<p class="text-xs text-muted">
|
||||||
class="flex w-full cursor-pointer flex-col items-center"
|
قیمت و مدت هر خدمت بر اساس کلاس انتخابشده نمایش داده میشود.
|
||||||
>
|
</p>
|
||||||
<input
|
<div class="grid grid-cols-2 gap-2">
|
||||||
type="checkbox"
|
<button
|
||||||
class="sr-only"
|
v-for="cls in activeClasses"
|
||||||
:checked="isServiceSelected(svc.id)"
|
:key="cls.id"
|
||||||
@change="toggleService(svc.id)"
|
type="button"
|
||||||
/>
|
class="rounded-xl border px-3 py-3 text-center text-sm transition"
|
||||||
<span
|
|
||||||
class="mb-2 flex h-5 w-5 items-center justify-center rounded-md border text-xs"
|
|
||||||
:class="
|
:class="
|
||||||
isServiceSelected(svc.id)
|
selectedClassId === cls.id
|
||||||
? 'border-brand-500 bg-brand-500 text-white'
|
? 'border-brand-500 bg-brand-500/15 text-brand-700 dark:text-brand-500'
|
||||||
: 'border-border bg-surface'
|
: 'border-border bg-surface text-text hover:border-brand-500/40'
|
||||||
|
"
|
||||||
|
@click="selectClass(cls.id)"
|
||||||
|
>
|
||||||
|
<span class="font-medium">{{ cls.title }}</span>
|
||||||
|
<span v-if="cls.description" class="mt-1 block text-xs text-muted">
|
||||||
|
{{ cls.description }}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!bookableServices.length"
|
||||||
|
class="rounded-xl border border-dashed border-border p-4 text-center text-sm text-muted"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
services.length
|
||||||
|
? 'خدمات این کسبوکار هنوز برای رزرو آماده نیست.'
|
||||||
|
: 'هنوز خدمتی برای این کسبوکار ثبت نشده است.'
|
||||||
|
}}
|
||||||
|
<span v-if="auth.isBusinessOwner" class="mt-2 block">
|
||||||
|
از بخش «کسبوکار» در منو، خدمات و قیمت را اضافه کنید.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
v-else-if="requiresServiceClass && canBook && !selectedClassId"
|
||||||
|
class="rounded-xl border border-dashed border-border p-4 text-center text-sm text-muted"
|
||||||
|
>
|
||||||
|
برای دیدن خدمات و قیمتها، ابتدا کلاس خودرو را انتخاب کنید.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-else-if="requiresServiceClass && selectedClassId && !displayedServices.length"
|
||||||
|
class="rounded-xl border border-dashed border-border p-4 text-center text-sm text-muted"
|
||||||
|
>
|
||||||
|
برای این کلاس هنوز خدمتی با قیمت ثبت نشده است.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-else-if="displayedServices.length">
|
||||||
|
<p v-if="canBook" class="mb-3 text-xs text-muted">
|
||||||
|
{{
|
||||||
|
requiresServiceClass
|
||||||
|
? '۲. خدمات مورد نظر را انتخاب کنید، سپس زمان مراجعه را تعیین کنید.'
|
||||||
|
: 'خدمات مورد نظر را انتخاب کنید، سپس زمان مراجعه را تعیین کنید.'
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<ul class="grid grid-cols-2 gap-3">
|
||||||
|
<li
|
||||||
|
v-for="svc in displayedServices"
|
||||||
|
:key="svc.id"
|
||||||
|
class="flex flex-col items-center rounded-2xl border p-3 text-center transition"
|
||||||
|
:class="
|
||||||
|
canBook && isServiceSelected(svc.id)
|
||||||
|
? 'border-brand-500 bg-brand-500/10'
|
||||||
|
: 'border-border bg-surface-2'
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ isServiceSelected(svc.id) ? '✓' : '' }}
|
<label
|
||||||
</span>
|
v-if="canBook"
|
||||||
<p class="font-medium text-text">
|
class="flex w-full cursor-pointer flex-col items-center"
|
||||||
{{ svc.serviceTemplate?.title ?? 'خدمت' }}
|
>
|
||||||
</p>
|
<input
|
||||||
<p
|
type="checkbox"
|
||||||
v-if="svc.serviceTemplate?.description"
|
class="sr-only"
|
||||||
class="mt-1 line-clamp-2 text-xs text-muted"
|
:checked="isServiceSelected(svc.id)"
|
||||||
>
|
@change="toggleService(svc.id)"
|
||||||
{{ svc.serviceTemplate.description }}
|
/>
|
||||||
</p>
|
<span
|
||||||
<div class="mt-auto space-y-0.5 pt-2 text-xs text-muted">
|
class="mb-2 flex h-5 w-5 items-center justify-center rounded-md border text-xs"
|
||||||
<p>{{ servicePriceLabel(svc, classesEnabled, serviceClasses) }}</p>
|
:class="
|
||||||
<p>{{ serviceDurationLabel(svc, classesEnabled, serviceClasses) }}</p>
|
isServiceSelected(svc.id)
|
||||||
</div>
|
? 'border-brand-500 bg-brand-500 text-white'
|
||||||
</label>
|
: 'border-border bg-surface'
|
||||||
<template v-else>
|
"
|
||||||
<p class="font-medium text-text">
|
>
|
||||||
{{ svc.serviceTemplate?.title ?? 'خدمت' }}
|
{{ isServiceSelected(svc.id) ? '✓' : '' }}
|
||||||
</p>
|
</span>
|
||||||
<p
|
<p class="font-medium text-text">
|
||||||
v-if="svc.serviceTemplate?.description"
|
{{ svc.serviceTemplate?.title ?? 'خدمت' }}
|
||||||
class="mt-1 line-clamp-2 text-xs text-muted"
|
</p>
|
||||||
>
|
<p
|
||||||
{{ svc.serviceTemplate.description }}
|
v-if="svc.serviceTemplate?.description"
|
||||||
</p>
|
class="mt-1 line-clamp-2 text-xs text-muted"
|
||||||
<div class="mt-auto space-y-0.5 pt-2 text-xs text-muted">
|
>
|
||||||
<p>{{ servicePriceLabel(svc, classesEnabled, serviceClasses) }}</p>
|
{{ svc.serviceTemplate.description }}
|
||||||
<p>{{ serviceDurationLabel(svc, classesEnabled, serviceClasses) }}</p>
|
</p>
|
||||||
</div>
|
<div class="mt-auto space-y-0.5 pt-2 text-xs text-muted">
|
||||||
</template>
|
<p>{{ servicePriceLabel(svc, classesEnabled, serviceClasses, selectedClassId || null) }}</p>
|
||||||
</li>
|
<p>{{ serviceDurationLabel(svc, classesEnabled, serviceClasses, selectedClassId || null) }}</p>
|
||||||
</ul>
|
</div>
|
||||||
|
</label>
|
||||||
|
<template v-else>
|
||||||
|
<p class="font-medium text-text">
|
||||||
|
{{ svc.serviceTemplate?.title ?? 'خدمت' }}
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
v-if="svc.serviceTemplate?.description"
|
||||||
|
class="mt-1 line-clamp-2 text-xs text-muted"
|
||||||
|
>
|
||||||
|
{{ svc.serviceTemplate.description }}
|
||||||
|
</p>
|
||||||
|
<div class="mt-auto space-y-0.5 pt-2 text-xs text-muted">
|
||||||
|
<p>{{ servicePriceLabel(svc, classesEnabled, serviceClasses, selectedClassId || null) }}</p>
|
||||||
|
<p>{{ serviceDurationLabel(svc, classesEnabled, serviceClasses, selectedClassId || null) }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="canBook && selectedServices.length"
|
v-if="canBook && selectedServices.length && canProceedToBooking"
|
||||||
class="sticky bottom-2 z-10 rounded-2xl border border-brand-500/40 bg-surface/95 p-4 shadow-lg backdrop-blur"
|
class="sticky bottom-2 z-10 rounded-2xl border border-brand-500/40 bg-surface/95 p-4 shadow-lg backdrop-blur"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-between gap-3">
|
<div class="flex items-center justify-between gap-3">
|
||||||
@@ -177,6 +229,8 @@
|
|||||||
<div class="rounded-xl border border-border bg-surface-2 p-3 text-sm">
|
<div class="rounded-xl border border-border bg-surface-2 p-3 text-sm">
|
||||||
<p class="text-muted">کسبوکار</p>
|
<p class="text-muted">کسبوکار</p>
|
||||||
<p class="font-medium text-text">{{ business.title }}</p>
|
<p class="font-medium text-text">{{ business.title }}</p>
|
||||||
|
<p v-if="selectedClass" class="mt-2 text-muted">کلاس</p>
|
||||||
|
<p v-if="selectedClass" class="font-medium text-text">{{ selectedClass.title }}</p>
|
||||||
<ul class="mt-3 space-y-2 border-t border-border pt-3">
|
<ul class="mt-3 space-y-2 border-t border-border pt-3">
|
||||||
<li
|
<li
|
||||||
v-for="svc in selectedServices"
|
v-for="svc in selectedServices"
|
||||||
@@ -186,8 +240,8 @@
|
|||||||
<span class="text-text">{{ svc.serviceTemplate?.title ?? 'خدمت' }}</span>
|
<span class="text-text">{{ svc.serviceTemplate?.title ?? 'خدمت' }}</span>
|
||||||
<span class="shrink-0 text-muted">
|
<span class="shrink-0 text-muted">
|
||||||
{{
|
{{
|
||||||
requiresServiceClass && bookingForm.serviceClassId
|
requiresServiceClass && selectedClassId
|
||||||
? `${formatPriceToman(resolvedServicePrice(svc, bookingForm.serviceClassId) ?? svc.price)} تومان`
|
? `${formatPriceToman(resolvedServicePrice(svc, selectedClassId) ?? svc.price)} تومان`
|
||||||
: `${formatPriceToman(svc.price)} تومان`
|
: `${formatPriceToman(svc.price)} تومان`
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
@@ -199,43 +253,13 @@
|
|||||||
<p class="font-medium text-text">{{ totalDurationLabel }}</p>
|
<p class="font-medium text-text">{{ totalDurationLabel }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="requiresServiceClass" class="space-y-1.5">
|
|
||||||
<label for="bookingClass" class="block text-sm font-medium text-muted">
|
|
||||||
کلاس خودرو / دسته
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
id="bookingClass"
|
|
||||||
v-model="bookingForm.serviceClassId"
|
|
||||||
required
|
|
||||||
class="w-full rounded-xl border border-border bg-surface-2 px-4 py-3 text-sm text-text outline-none focus:border-brand-500"
|
|
||||||
@change="bookingForm.scheduledAt = ''"
|
|
||||||
>
|
|
||||||
<option value="" disabled>انتخاب کنید</option>
|
|
||||||
<option
|
|
||||||
v-for="cls in activeClasses"
|
|
||||||
:key="cls.id"
|
|
||||||
:value="cls.id"
|
|
||||||
:disabled="!selectedServices.every((svc) => getClassPriceForService(svc, cls.id))"
|
|
||||||
>
|
|
||||||
{{ cls.title }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<BookingSlotPicker
|
<BookingSlotPicker
|
||||||
v-if="!requiresServiceClass || bookingForm.serviceClassId"
|
|
||||||
v-model="bookingForm.scheduledAt"
|
v-model="bookingForm.scheduledAt"
|
||||||
label="تاریخ و ساعت مراجعه (شمسی)"
|
label="تاریخ و ساعت مراجعه (شمسی)"
|
||||||
:business-id="business.id"
|
:business-id="business.id"
|
||||||
:business-service-ids="selectedServiceIds"
|
:business-service-ids="selectedServiceIds"
|
||||||
:service-class-id="bookingForm.serviceClassId || null"
|
:service-class-id="selectedClassId || null"
|
||||||
/>
|
/>
|
||||||
<p
|
|
||||||
v-else
|
|
||||||
class="rounded-xl border border-dashed border-border px-4 py-3 text-center text-sm text-muted"
|
|
||||||
>
|
|
||||||
ابتدا کلاس خودرو را انتخاب کنید.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="space-y-1.5">
|
<div class="space-y-1.5">
|
||||||
<label for="bookingNote" class="block text-sm font-medium text-muted">
|
<label for="bookingNote" class="block text-sm font-medium text-muted">
|
||||||
@@ -276,8 +300,8 @@ import { useAuthStore } from '@/stores/auth';
|
|||||||
import { formatPriceToman } from '@/utils/format';
|
import { formatPriceToman } from '@/utils/format';
|
||||||
import {
|
import {
|
||||||
activeServiceClasses,
|
activeServiceClasses,
|
||||||
getClassPriceForService,
|
|
||||||
isServiceBookable,
|
isServiceBookable,
|
||||||
|
isServiceBookableForClass,
|
||||||
resolvedServicePrice,
|
resolvedServicePrice,
|
||||||
serviceDurationLabel,
|
serviceDurationLabel,
|
||||||
servicePriceLabel,
|
servicePriceLabel,
|
||||||
@@ -299,11 +323,11 @@ const error = ref('');
|
|||||||
const servicesError = ref('');
|
const servicesError = ref('');
|
||||||
|
|
||||||
const bookingOpen = ref(false);
|
const bookingOpen = ref(false);
|
||||||
|
const selectedClassId = ref('');
|
||||||
const selectedServiceIds = ref<string[]>([]);
|
const selectedServiceIds = ref<string[]>([]);
|
||||||
const bookingSaving = ref(false);
|
const bookingSaving = ref(false);
|
||||||
const bookingError = ref('');
|
const bookingError = ref('');
|
||||||
const bookingForm = ref({
|
const bookingForm = ref({
|
||||||
serviceClassId: '',
|
|
||||||
scheduledAt: '',
|
scheduledAt: '',
|
||||||
note: '',
|
note: '',
|
||||||
});
|
});
|
||||||
@@ -321,8 +345,28 @@ const bookableServices = computed(() =>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const displayedServices = computed(() => {
|
||||||
|
if (!requiresServiceClass.value) {
|
||||||
|
return bookableServices.value;
|
||||||
|
}
|
||||||
|
if (!selectedClassId.value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return bookableServices.value.filter((svc) =>
|
||||||
|
isServiceBookableForClass(svc, selectedClassId.value),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectedClass = computed(() =>
|
||||||
|
activeClasses.value.find((cls) => cls.id === selectedClassId.value) ?? null,
|
||||||
|
);
|
||||||
|
|
||||||
|
const canProceedToBooking = computed(
|
||||||
|
() => !requiresServiceClass.value || !!selectedClassId.value,
|
||||||
|
);
|
||||||
|
|
||||||
const selectedServices = computed(() =>
|
const selectedServices = computed(() =>
|
||||||
bookableServices.value.filter((svc) => selectedServiceIds.value.includes(svc.id)),
|
displayedServices.value.filter((svc) => selectedServiceIds.value.includes(svc.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalDurationLabel = computed(() => {
|
const totalDurationLabel = computed(() => {
|
||||||
@@ -330,21 +374,18 @@ const totalDurationLabel = computed(() => {
|
|||||||
selectedServices.value,
|
selectedServices.value,
|
||||||
classesEnabled.value,
|
classesEnabled.value,
|
||||||
serviceClasses.value,
|
serviceClasses.value,
|
||||||
bookingForm.value.serviceClassId || null,
|
selectedClassId.value || null,
|
||||||
);
|
);
|
||||||
return `${minutes} دقیقه`;
|
return `${minutes} دقیقه`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const bookingPriceLabel = computed(() => {
|
const bookingPriceLabel = computed(() => {
|
||||||
if (!selectedServices.value.length) return '—';
|
if (!selectedServices.value.length) return '—';
|
||||||
if (requiresServiceClass.value && !bookingForm.value.serviceClassId) {
|
|
||||||
return 'کلاس را انتخاب کنید';
|
|
||||||
}
|
|
||||||
const total = totalPriceForServices(
|
const total = totalPriceForServices(
|
||||||
selectedServices.value,
|
selectedServices.value,
|
||||||
classesEnabled.value,
|
classesEnabled.value,
|
||||||
serviceClasses.value,
|
serviceClasses.value,
|
||||||
bookingForm.value.serviceClassId || null,
|
selectedClassId.value || null,
|
||||||
);
|
);
|
||||||
return total != null ? `${formatPriceToman(String(total))} تومان` : '—';
|
return total != null ? `${formatPriceToman(String(total))} تومان` : '—';
|
||||||
});
|
});
|
||||||
@@ -363,7 +404,18 @@ function isServiceSelected(id: string): boolean {
|
|||||||
return selectedServiceIds.value.includes(id);
|
return selectedServiceIds.value.includes(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectClass(classId: string) {
|
||||||
|
if (selectedClassId.value === classId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedClassId.value = classId;
|
||||||
|
selectedServiceIds.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
function toggleService(id: string) {
|
function toggleService(id: string) {
|
||||||
|
if (requiresServiceClass.value && !selectedClassId.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (isServiceSelected(id)) {
|
if (isServiceSelected(id)) {
|
||||||
selectedServiceIds.value = selectedServiceIds.value.filter((item) => item !== id);
|
selectedServiceIds.value = selectedServiceIds.value.filter((item) => item !== id);
|
||||||
} else {
|
} else {
|
||||||
@@ -372,9 +424,8 @@ function toggleService(id: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openBooking() {
|
function openBooking() {
|
||||||
if (!auth.user || !selectedServices.value.length) return;
|
if (!auth.user || !selectedServices.value.length || !canProceedToBooking.value) return;
|
||||||
bookingForm.value = {
|
bookingForm.value = {
|
||||||
serviceClassId: '',
|
|
||||||
scheduledAt: '',
|
scheduledAt: '',
|
||||||
note: '',
|
note: '',
|
||||||
};
|
};
|
||||||
@@ -442,7 +493,7 @@ async function onSubmitBooking() {
|
|||||||
bookingError.value = 'لطفاً یک ساعت از لیست انتخاب کنید.';
|
bookingError.value = 'لطفاً یک ساعت از لیست انتخاب کنید.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (requiresServiceClass.value && !bookingForm.value.serviceClassId) {
|
if (requiresServiceClass.value && !selectedClassId.value) {
|
||||||
bookingError.value = 'لطفاً کلاس خودرو را انتخاب کنید.';
|
bookingError.value = 'لطفاً کلاس خودرو را انتخاب کنید.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -456,11 +507,12 @@ async function onSubmitBooking() {
|
|||||||
items: selectedServices.value.map((svc) => ({
|
items: selectedServices.value.map((svc) => ({
|
||||||
businessServiceId: svc.id,
|
businessServiceId: svc.id,
|
||||||
})),
|
})),
|
||||||
serviceClassId: bookingForm.value.serviceClassId || null,
|
serviceClassId: selectedClassId.value || null,
|
||||||
scheduledAt: scheduled.toISOString(),
|
scheduledAt: scheduled.toISOString(),
|
||||||
note: bookingForm.value.note.trim() || null,
|
note: bookingForm.value.note.trim() || null,
|
||||||
});
|
});
|
||||||
selectedServiceIds.value = [];
|
selectedServiceIds.value = [];
|
||||||
|
selectedClassId.value = '';
|
||||||
closeBooking();
|
closeBooking();
|
||||||
router.push({ name: 'app-bookings' });
|
router.push({ name: 'app-bookings' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user