awaiting_payment
This commit is contained in:
@@ -65,9 +65,17 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="canConfirm || canCancel"
|
||||
v-if="canConfirm || canCancel || canPay"
|
||||
class="mt-auto flex flex-wrap gap-2 border-t border-border pt-3"
|
||||
>
|
||||
<AppButton
|
||||
v-if="canPay"
|
||||
class="!w-auto flex-1 px-3"
|
||||
:loading="acting"
|
||||
@click="emit('pay', bookings)"
|
||||
>
|
||||
پرداخت
|
||||
</AppButton>
|
||||
<AppButton
|
||||
v-if="canConfirm"
|
||||
class="!w-auto flex-1 px-3"
|
||||
@@ -106,11 +114,13 @@ const props = defineProps<{
|
||||
showCustomer: boolean;
|
||||
canConfirm: boolean;
|
||||
canCancel: boolean;
|
||||
canPay: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
confirm: [bookings: Booking[]];
|
||||
cancel: [bookings: Booking[]];
|
||||
pay: [bookings: Booking[]];
|
||||
}>();
|
||||
|
||||
const primary = computed(() => props.bookings[0]!);
|
||||
@@ -139,6 +149,9 @@ function statusClassFor(status: BookingStatus | 'mixed') {
|
||||
if (status === 'confirmed' || status === 'completed') {
|
||||
return 'bg-emerald-500/15 text-emerald-700 dark:text-emerald-400';
|
||||
}
|
||||
if (status === 'awaiting_payment') {
|
||||
return 'bg-sky-500/15 text-sky-700 dark:text-sky-400';
|
||||
}
|
||||
if (status === 'pending') {
|
||||
return 'bg-amber-500/15 text-amber-700 dark:text-amber-400';
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-text">رزرو شما با موفقیت ثبت شد!</h2>
|
||||
<h2 class="text-2xl font-bold text-text">{{ title }}</h2>
|
||||
<p class="mt-2 text-sm text-muted">
|
||||
جزئیات رزرو برای شما پیامک و در بخش رزروها ذخیره شد.
|
||||
{{ subtitle }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -61,7 +61,10 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-stretch gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:justify-center sm:gap-3">
|
||||
<AppButton @click="emit('view-bookings')">
|
||||
<AppButton v-if="showPayButton" @click="emit('pay')">
|
||||
پرداخت آنلاین
|
||||
</AppButton>
|
||||
<AppButton :variant="showPayButton ? 'outline' : 'primary'" @click="emit('view-bookings')">
|
||||
مشاهده رزروها
|
||||
</AppButton>
|
||||
<AppButton variant="outline" @click="emit('add-to-calendar')">
|
||||
@@ -81,22 +84,38 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import AppButton from '@/components/ui/AppButton.vue';
|
||||
import AppIcon from '@/components/ui/AppIcon.vue';
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
serviceTitle: string;
|
||||
dateLabel: string;
|
||||
timeLabel: string;
|
||||
durationLabel: string;
|
||||
address?: string | null;
|
||||
bookingRef: string;
|
||||
successMode?: 'pending_approval' | 'awaiting_payment';
|
||||
showPayButton?: boolean;
|
||||
}>();
|
||||
|
||||
const title = computed(() =>
|
||||
props.successMode === 'awaiting_payment'
|
||||
? 'رزرو تأیید شد — آماده پرداخت'
|
||||
: 'درخواست رزرو ثبت شد',
|
||||
);
|
||||
|
||||
const subtitle = computed(() =>
|
||||
props.successMode === 'awaiting_payment'
|
||||
? 'برای نهایی شدن رزرو، پرداخت آنلاین را انجام دهید.'
|
||||
: 'درخواست شما برای صاحب کسبوکار ارسال شد. پس از تأیید، لینک پرداخت در اپ و پیامک برای شما ارسال میشود.',
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
'view-bookings': [];
|
||||
'add-to-calendar': [];
|
||||
'go-home': [];
|
||||
pay: [];
|
||||
}>();
|
||||
|
||||
const confettiDots = [
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
@view-bookings="emit('view-bookings')"
|
||||
@add-to-calendar="downloadCalendar"
|
||||
@go-home="emit('go-home')"
|
||||
@pay="goToPayment"
|
||||
/>
|
||||
|
||||
<template v-else>
|
||||
@@ -123,7 +124,7 @@
|
||||
placeholder="در صورت نیاز توضیحی بنویسید..."
|
||||
/>
|
||||
<p class="mt-4 text-sm text-muted">
|
||||
پرداخت در محل انجام میشود. نیازی به پرداخت آنلاین نیست.
|
||||
{{ paymentInfoText }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -223,6 +224,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { createBooking, createBookingBatch, fetchAvailableSlots } from '@/api/bookings';
|
||||
import { fetchBusinessServiceClasses } from '@/api/business-service-classes';
|
||||
import { ApiError } from '@/api/client';
|
||||
@@ -275,8 +277,13 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const auth = useAuthStore();
|
||||
const router = useRouter();
|
||||
|
||||
const currentStep = ref(1);
|
||||
const paymentInfoText = computed(() =>
|
||||
props.business.autoApproveBookings
|
||||
? 'پس از ثبت نهایی، مستقیماً به صفحه پرداخت آنلاین هدایت میشوید.'
|
||||
: 'پس از ثبت، درخواست شما بررسی میشود. در صورت تأیید صاحب کسبوکار، لینک پرداخت آنلاین برای شما در اپ و پیامک ارسال میشود.',
|
||||
);
|
||||
const phase = ref<'booking' | 'success'>('booking');
|
||||
const selectedClassId = ref('');
|
||||
const selectedServiceIds = ref<string[]>([]);
|
||||
@@ -405,6 +412,11 @@ const successDetails = computed(() => {
|
||||
durationLabel: selectedDurationLabel.value ?? '—',
|
||||
address: props.business.address,
|
||||
bookingRef: createdBooking.value.id.slice(0, 8).toUpperCase(),
|
||||
successMode:
|
||||
createdBooking.value.status === 'awaiting_payment'
|
||||
? 'awaiting_payment'
|
||||
: 'pending_approval',
|
||||
showPayButton: createdBooking.value.status === 'awaiting_payment',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -581,6 +593,17 @@ async function submitBooking() {
|
||||
});
|
||||
createdBooking.value = bookings[0] ?? null;
|
||||
}
|
||||
if (
|
||||
createdBooking.value?.status === 'awaiting_payment' &&
|
||||
createdBooking.value.paymentToken &&
|
||||
props.business.autoApproveBookings
|
||||
) {
|
||||
await router.push({
|
||||
path: '/app/bookings/pay',
|
||||
query: { token: createdBooking.value.paymentToken },
|
||||
});
|
||||
return;
|
||||
}
|
||||
phase.value = 'success';
|
||||
} catch (e) {
|
||||
bookingError.value = e instanceof ApiError ? e.message : 'ثبت رزرو ناموفق بود.';
|
||||
@@ -589,6 +612,15 @@ async function submitBooking() {
|
||||
}
|
||||
}
|
||||
|
||||
function goToPayment() {
|
||||
const token = createdBooking.value?.paymentToken;
|
||||
if (!token) return;
|
||||
void router.push({
|
||||
path: '/app/bookings/pay',
|
||||
query: { token },
|
||||
});
|
||||
}
|
||||
|
||||
function downloadCalendar() {
|
||||
if (!createdBooking.value) return;
|
||||
const start = new Date(createdBooking.value.scheduledAt);
|
||||
|
||||
Reference in New Issue
Block a user