Files
TakeoutSaaS.C-Side-Mini-Pro…/src/pages/trade/checkout/composables/useCheckoutPage.ts

160 lines
4.4 KiB
TypeScript

import { computed, ref } from 'vue'
import { showToast, useDidShow } from '@tarojs/taro'
import { createOrder } from '@/services'
import { pinia, useAppStore, useCartStore, useCustomerStore, useFulfillmentStore } from '@/stores'
import { FulfillmentScenes } from '@/shared'
import { openRoute } from '@/utils/router'
import { createEstimateActions, emptyEstimate } from './checkout-page/estimate-actions'
import { buildCheckoutPayload } from './checkout-page/payload'
import {
resolveSceneHint,
resolveSceneLabel,
resolveSceneSuffix
} from './checkout-page/scene-helpers'
interface InputLikeEvent {
detail?: {
value?: string
}
}
export function useCheckoutPage () {
const appStore = useAppStore(pinia)
const cartStore = useCartStore(pinia)
const customerStore = useCustomerStore(pinia)
const fulfillmentStore = useFulfillmentStore(pinia)
const isEstimating = ref(false)
const submitting = ref(false)
const estimate = ref(emptyEstimate)
const draftName = ref(customerStore.name)
const draftPhone = ref(customerStore.phone)
const remark = ref('')
const itemCount = computed(() => cartStore.itemCount)
const lineList = computed(() => cartStore.lineList)
const sceneLabel = computed(() => resolveSceneLabel(appStore.scene))
const sceneSuffix = computed(() => resolveSceneSuffix(appStore.scene))
const sceneHint = computed(() => resolveSceneHint(appStore.scene))
const { handleEstimate } = createEstimateActions({
appStore,
cartStore,
estimate,
isEstimating
})
function handleNameInput (event: InputLikeEvent) {
draftName.value = event.detail?.value || ''
}
function handlePhoneInput (event: InputLikeEvent) {
draftPhone.value = event.detail?.value || ''
}
function handleRemarkInput (event: InputLikeEvent) {
remark.value = event.detail?.value || ''
}
async function submitOrder () {
if (!cartStore.itemCount) {
await showToast({ title: '请先加购商品', icon: 'none' })
return
}
if (!draftName.value.trim() || !draftPhone.value.trim()) {
await showToast({ title: '请完善顾客信息', icon: 'none' })
return
}
if (appStore.scene === FulfillmentScenes.Delivery && !fulfillmentStore.addressText) {
await showToast({ title: '请先填写配送地址', icon: 'none' })
void openRoute('/pages/address/index')
return
}
if (appStore.scene === FulfillmentScenes.DineIn && !fulfillmentStore.tableNo) {
await showToast({ title: '请先填写桌号', icon: 'none' })
void openRoute('/pages/dinein/confirm/index')
return
}
customerStore.updateProfile({
name: draftName.value,
phone: draftPhone.value
})
submitting.value = true
try {
await handleEstimate()
const order = await createOrder({
...buildCheckoutPayload(appStore, cartStore),
remark: remark.value || (appStore.scene === FulfillmentScenes.Delivery
? fulfillmentStore.addressText
: undefined),
tableNo: appStore.scene === FulfillmentScenes.DineIn
? fulfillmentStore.tableNo
: undefined
})
cartStore.clear()
void openRoute(`/pages/trade/success/index?orderId=${order.orderId}&orderNo=${order.orderNo}`)
} catch (error: unknown) {
await showToast({
title: error instanceof Error ? error.message : '下单失败',
icon: 'none'
})
} finally {
submitting.value = false
}
}
function goSceneContext () {
if (appStore.scene === FulfillmentScenes.Delivery) {
void openRoute('/pages/address/index')
return
}
if (appStore.scene === FulfillmentScenes.DineIn) {
void openRoute('/pages/dinein/confirm/index')
return
}
void showToast({ title: '自提场景无需额外填写', icon: 'none' })
}
function goMenu () {
void openRoute('/pages/menu/index')
}
useDidShow(() => {
draftName.value = customerStore.name
draftPhone.value = customerStore.phone
void appStore.initBootstrap()
void appStore.initStores()
void handleEstimate()
})
return {
appStore,
draftName,
draftPhone,
estimate,
fulfillmentStore,
goMenu,
goSceneContext,
handleEstimate,
handleNameInput,
handlePhoneInput,
handleRemarkInput,
itemCount,
lineList,
remark,
sceneHint,
sceneLabel,
sceneSuffix,
submitOrder,
submitting
}
}