@feedmepos/mf-order-setting 0.0.27 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{KioskDevicesView-AKvyDF3w.js → KioskDevicesView-BgXkmJ7v.js} +1 -1
- package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-Cx8VMyNB.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-DZT0BuUN.js} +2 -2
- package/dist/{KioskSettingView-equ5EIvU.js → KioskSettingView-DyX3Wv_2.js} +1 -1
- package/dist/{KioskView-CsE7BGtA.js → KioskView-Bgff7QPc.js} +4 -4
- package/dist/OrderSettingsView-C63s4uCD.js +74334 -0
- package/dist/{app-D-zQN9_E.js → app-Dp79Gu_F.js} +97 -25
- package/dist/app.js +1 -1
- package/dist/{dayjs.min-CWQSmujV.js → dayjs.min-B2ZkfNUH.js} +278 -267
- package/dist/frontend/mf-order/src/api/business/index.d.ts +5 -0
- package/dist/frontend/mf-order/src/api/effects/index.d.ts +3 -0
- package/dist/frontend/mf-order/src/api/index.d.ts +2 -0
- package/dist/frontend/mf-order/src/app.d.ts +72 -0
- package/dist/frontend/mf-order/src/main.d.ts +72 -0
- package/dist/frontend/mf-order/src/stores/business/index.d.ts +62 -0
- package/dist/frontend/mf-order/src/stores/menu/menu.d.ts +138 -125
- package/dist/frontend/mf-order/src/stores/restaurant/index.d.ts +81 -78
- package/dist/frontend/mf-order/src/views/all-orders/ReflowOrder.vue.d.ts +54 -52
- package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/ExternalSetting.vue.d.ts +4 -0
- package/dist/frontend/mf-order/src/views/order-settings/discount-rule/DiscountRuleSetting.vue.d.ts +2 -0
- package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
- package/dist/{index-BwrMcIf2.js → index-DzQn92Tp.js} +2 -2
- package/dist/package/entity/booking/booking.do.d.ts +596 -551
- package/dist/package/entity/delivery/delivery.dto.d.ts +118 -109
- package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +342 -652
- package/dist/package/entity/incoming-order/incoming-order.do.d.ts +13778 -478
- package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +728 -1227
- package/dist/package/entity/incoming-order/incoming-order.enum.d.ts +1 -1
- package/dist/package/entity/index.d.ts +1 -0
- package/dist/package/entity/kiosk/kiosk.do.d.ts +32 -0
- package/dist/package/entity/kiosk/kiosk.dto.d.ts +14 -14
- package/dist/package/entity/kiosk/marketing/marketing.dto.d.ts +1469 -621
- package/dist/package/entity/member/member.dto.d.ts +14 -7
- package/dist/package/entity/order/effects/effect.dto.d.ts +154 -6
- package/dist/package/entity/order/order-item/order-item.dto.d.ts +87 -34
- package/dist/package/entity/order/order.do.d.ts +177 -572
- package/dist/package/entity/order/order.dto.d.ts +902 -1412
- package/dist/package/entity/order-platform/external/menu/external-menu.dto.d.ts +8 -0
- package/dist/package/entity/order-platform/external/order/external-order.do.d.ts +8 -0
- package/dist/package/entity/order-platform/external/order/external-order.dto.d.ts +22 -3
- package/dist/package/entity/order-platform/external/order/external-order.enum.d.ts +1 -1
- package/dist/package/entity/order-platform/external/setting/external-setting.do.d.ts +5 -0
- package/dist/package/entity/order-platform/external/setting/external-setting.dto.d.ts +5 -0
- package/dist/package/entity/order-platform/external/zus/zus-menu.dto.d.ts +192 -0
- package/dist/package/entity/order-platform/foodpanda/foodpanda-order.do.d.ts +104 -0
- package/dist/package/entity/order-platform/foodpanda/foodpanda-order.dto.d.ts +152 -109
- package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.do.d.ts +3 -0
- package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.dto.d.ts +3 -0
- package/dist/package/entity/order-platform/foodpanda/foodpanda.enum.d.ts +2 -0
- package/dist/package/entity/order-platform/grabfood/grabfood-order.do.d.ts +139 -109
- package/dist/package/entity/order-platform/grabfood/grabfood-settings.do.d.ts +3 -0
- package/dist/package/entity/order-platform/grabfood/grabfood.dto.d.ts +112 -2
- package/dist/package/entity/order-platform/order-platform.dto.d.ts +6 -3
- package/dist/package/entity/order-platform/shopeefood/shopeefood-order.do.d.ts +164 -109
- package/dist/package/entity/order-platform/shopeefood/shopeefood-order.dto.d.ts +22 -0
- package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.do.d.ts +3 -0
- package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.dto.d.ts +3 -0
- package/dist/queue.do-BUtcyDk3.js +125578 -0
- package/package.json +4 -3
- package/src/api/business/index.ts +16 -0
- package/src/api/effects/index.ts +7 -0
- package/src/api/index.ts +9 -1
- package/src/locales/en-US.json +24 -1
- package/src/locales/th-TH.json +24 -1
- package/src/locales/zh-CN.json +27 -1
- package/src/stores/business/index.ts +45 -0
- package/src/stores/restaurant/index.ts +3 -1
- package/src/views/order-settings/OrderSettingsView.vue +17 -5
- package/src/views/order-settings/discount-rule/DiscountRuleSetting.vue +434 -0
- package/dist/OrderSettingsView-BpLXyk_0.js +0 -49013
- package/dist/queue.do-F110q0_J.js +0 -100389
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex flex-col gap-5 mx-5">
|
|
3
|
+
<div class="flex flex-col">
|
|
4
|
+
<div v-if="!isLoading">
|
|
5
|
+
<FmPageHead
|
|
6
|
+
class="flex-grow"
|
|
7
|
+
:title="t('order.discountRule.title')"
|
|
8
|
+
:description="
|
|
9
|
+
t('order.discountRule.description', {
|
|
10
|
+
minPosVersion: Pos.minVersionToUse(F_FEATURE.Enum.calculatorV7)
|
|
11
|
+
})
|
|
12
|
+
"
|
|
13
|
+
/>
|
|
14
|
+
<div class="flex flex-col gap-5 ml-5">
|
|
15
|
+
<!-- Discount Rule Cards -->
|
|
16
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-5">
|
|
17
|
+
<FmCard
|
|
18
|
+
v-for="(group, index) in effectGroups"
|
|
19
|
+
:key="index"
|
|
20
|
+
variant="outlined"
|
|
21
|
+
class="p-5"
|
|
22
|
+
>
|
|
23
|
+
<div class="flex items-center justify-between mb-3">
|
|
24
|
+
<div class="font-bold">{{ t('order.discountRule.title') }} {{ index + 1 }}</div>
|
|
25
|
+
<FmButton
|
|
26
|
+
variant="plain"
|
|
27
|
+
size="md"
|
|
28
|
+
prepend-icon="delete"
|
|
29
|
+
@click="() => deleteRule(index)"
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="flex items-center justify-between">
|
|
33
|
+
<div class="font-semibold my-3">
|
|
34
|
+
{{ t('order.discountRule.effect') }}
|
|
35
|
+
</div>
|
|
36
|
+
<FmButton
|
|
37
|
+
variant="plain"
|
|
38
|
+
:label="
|
|
39
|
+
t('order.discountRule.effectSelected', { count: group.effectIds?.length ?? 0 })
|
|
40
|
+
"
|
|
41
|
+
size="lg"
|
|
42
|
+
:disabled="!hasEffects"
|
|
43
|
+
@click="() => toggleSideSheet(index)"
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
46
|
+
<FmTextField
|
|
47
|
+
v-model="group.maxApplicableEffects"
|
|
48
|
+
:label="t('order.discountRule.maxTotalUses')"
|
|
49
|
+
type="number"
|
|
50
|
+
:rules="maxApplicableEffectsRules"
|
|
51
|
+
:min="1"
|
|
52
|
+
:helper-text="t('order.discountRule.maxTotalUsesSublabel')"
|
|
53
|
+
/>
|
|
54
|
+
</FmCard>
|
|
55
|
+
<FmCard
|
|
56
|
+
variant="outlined"
|
|
57
|
+
class="flex items-center justify-center w-full h-full border-dashed"
|
|
58
|
+
>
|
|
59
|
+
<FmCardSection class="flex items-center justify-center w-full">
|
|
60
|
+
<FmButton
|
|
61
|
+
variant="plain"
|
|
62
|
+
:label="t('order.discountRule.add')"
|
|
63
|
+
icon="add"
|
|
64
|
+
@click="createRule"
|
|
65
|
+
class="border fm-corner-radius-lg border-fm-color-primary"
|
|
66
|
+
/>
|
|
67
|
+
</FmCardSection>
|
|
68
|
+
</FmCard>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="fm-corner-radius-lg flex flex-col">
|
|
71
|
+
<FmButton
|
|
72
|
+
variant="primary"
|
|
73
|
+
:label="t('order.saveSetting')"
|
|
74
|
+
class="mr-auto"
|
|
75
|
+
:disabled="!canSave"
|
|
76
|
+
@click="updateDiscountRule"
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
<!-- Side Sheet for Effect Selection -->
|
|
81
|
+
<FmSideSheet
|
|
82
|
+
:header="t('order.discountRule.selectEffects')"
|
|
83
|
+
:maxWidth="600"
|
|
84
|
+
dismiss-away
|
|
85
|
+
v-model="sideSheet"
|
|
86
|
+
>
|
|
87
|
+
<div>
|
|
88
|
+
<div class="text-fm-color-typo-secondary mt-5 mb-5 flex flex-row">
|
|
89
|
+
{{
|
|
90
|
+
t('order.discountRule.effectSelected', {
|
|
91
|
+
count: selectedEffectGroup?.effectIds?.length ?? 0
|
|
92
|
+
})
|
|
93
|
+
}}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<FmCheckbox
|
|
97
|
+
:label="t('order.discountRule.selectAllEffects')"
|
|
98
|
+
:model-value="isAllSelectedForCurrentGroup"
|
|
99
|
+
value=""
|
|
100
|
+
@update:model-value="(v: boolean) => selectAllEffects(v)"
|
|
101
|
+
></FmCheckbox>
|
|
102
|
+
|
|
103
|
+
<div
|
|
104
|
+
v-for="pEffect in processedEffects"
|
|
105
|
+
:key="pEffect.id"
|
|
106
|
+
class="flex flex-col mb-2 ml-5"
|
|
107
|
+
>
|
|
108
|
+
<div class="flex flex-row">
|
|
109
|
+
<div class="flex flex-row items-center">
|
|
110
|
+
<FmCheckbox
|
|
111
|
+
:model-value="pEffect.isSelectedInCurrentGroup"
|
|
112
|
+
value=""
|
|
113
|
+
@update:model-value="(v) => selectEffect(pEffect, v)"
|
|
114
|
+
:disabled="pEffect.isDisabled"
|
|
115
|
+
/>
|
|
116
|
+
<div class="ml-2">
|
|
117
|
+
<span>{{ pEffect.name }}</span>
|
|
118
|
+
<template v-if="pEffect.showUsedInOtherGroupHint">
|
|
119
|
+
<span class="text-sm text-fm-color-typo-secondary pl-1">
|
|
120
|
+
({{ t('order.discountRule.effectUsedInOtherGroup') }})
|
|
121
|
+
</span>
|
|
122
|
+
</template>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
<template #side-sheet-footer>
|
|
129
|
+
<div class="flex gap-8 items-center justify-start">
|
|
130
|
+
<FmButton variant="primary" :label="t('order.confirm')" size="lg" @click="confirm" />
|
|
131
|
+
<FmButton
|
|
132
|
+
variant="secondary"
|
|
133
|
+
:label="t('order.cancel')"
|
|
134
|
+
size="lg"
|
|
135
|
+
@click="onCancel"
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
</template>
|
|
139
|
+
</FmSideSheet>
|
|
140
|
+
</div>
|
|
141
|
+
<FmCircularProgress size="xxl" v-else />
|
|
142
|
+
</div>
|
|
143
|
+
<!-- Restaurants Table Section -->
|
|
144
|
+
<div class="flex flex-col">
|
|
145
|
+
<FmPageHead
|
|
146
|
+
class="flex-grow"
|
|
147
|
+
:title="t('order.discountRule.restaurants')"
|
|
148
|
+
:description="t('order.discountRule.restaurantsDescription')"
|
|
149
|
+
/>
|
|
150
|
+
<div class="ml-5">
|
|
151
|
+
<div class="flex justify-end items-center mb-3 gap-5">
|
|
152
|
+
<FmButton
|
|
153
|
+
variant="tertiary"
|
|
154
|
+
:label="t('order.discountRule.forceSync')"
|
|
155
|
+
@click="syncDiscountRule"
|
|
156
|
+
:disabled="isLoading"
|
|
157
|
+
prepend-icon="refresh"
|
|
158
|
+
/>
|
|
159
|
+
<FmSearch v-model="searchKey" :placeholder="t('order.search')" />
|
|
160
|
+
</div>
|
|
161
|
+
<FmTable
|
|
162
|
+
:row-data="filteredRestaurants"
|
|
163
|
+
:column-defs="columns"
|
|
164
|
+
class="w-full"
|
|
165
|
+
:loading="isLoading"
|
|
166
|
+
:loading-text="t('order.discountRule.loadingRestaurants')"
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
</template>
|
|
172
|
+
|
|
173
|
+
<script setup lang="ts">
|
|
174
|
+
import { ref, onMounted, computed, watch, h } from 'vue'
|
|
175
|
+
import { useCoreStore } from '@feedmepos/mf-common'
|
|
176
|
+
import { useBusinessStore } from '@/stores/business'
|
|
177
|
+
import { useI18n } from '@feedmepos/mf-common'
|
|
178
|
+
import { effectApi } from '@/api/effects'
|
|
179
|
+
import { useLoading } from '@/composables/loading'
|
|
180
|
+
import useSearch from '@/composables/search'
|
|
181
|
+
import { Pos } from '@feedmepos/core'
|
|
182
|
+
import { FdoEffectGroup, FdtoDiscountRuleRes, F_FEATURE } from '@feedmepos/core/entity'
|
|
183
|
+
import { useSnackbarFunctions } from '@/components/snackbar'
|
|
184
|
+
import { type ColumnDef } from '@feedmepos/ui-library'
|
|
185
|
+
import { components } from '@feedmepos/ui-library'
|
|
186
|
+
|
|
187
|
+
interface Effect {
|
|
188
|
+
id: string
|
|
189
|
+
name: string
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const { startAsyncCallWithErr, isLoading } = useLoading()
|
|
193
|
+
const { t } = useI18n()
|
|
194
|
+
const businessStore = useBusinessStore()
|
|
195
|
+
const { currentBusiness } = useCoreStore()
|
|
196
|
+
const { showSuccess, showError } = useSnackbarFunctions()
|
|
197
|
+
const { searchKey, filter } = useSearch()
|
|
198
|
+
|
|
199
|
+
const maxApplicableEffectsRules = [(val: number) => val >= 1 || 'Must be greater than 0']
|
|
200
|
+
|
|
201
|
+
const canSave = computed(() =>
|
|
202
|
+
effectGroups.value.every((group) =>
|
|
203
|
+
maxApplicableEffectsRules.every((rule) => typeof rule(group.maxApplicableEffects) !== 'string')
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
const hasEffects = computed(() => effects.value.length > 0)
|
|
208
|
+
const sideSheet = ref(false)
|
|
209
|
+
const rawEffectGroups = ref<FdoEffectGroup[]>([])
|
|
210
|
+
const effectGroups = ref<FdoEffectGroup[]>([])
|
|
211
|
+
const restaurants = ref<{ id: string; name: string; lastUpdatedAt: string }[]>([])
|
|
212
|
+
const filteredRestaurants = computed<{ id: string; name: string; lastUpdatedAt: string }[]>(() =>
|
|
213
|
+
restaurants.value.filter(({ id, name }) => filter([id, name]))
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
const lastUpdatedAt = ref<string | null>(null)
|
|
217
|
+
const effects = ref<Effect[]>([])
|
|
218
|
+
const selectedEffectGroup = ref<FdoEffectGroup | null>(null)
|
|
219
|
+
const selectedEffectIndex = ref<number | null>(null)
|
|
220
|
+
|
|
221
|
+
const pad = (n: number) => n.toString().padStart(2, '0')
|
|
222
|
+
|
|
223
|
+
function formatDate(date?: string | null): string {
|
|
224
|
+
if (!date) return ''
|
|
225
|
+
try {
|
|
226
|
+
const dateObj = typeof date === 'string' ? new Date(date) : date
|
|
227
|
+
const y = dateObj.getFullYear()
|
|
228
|
+
const m = pad(dateObj.getMonth() + 1)
|
|
229
|
+
const d = pad(dateObj.getDate())
|
|
230
|
+
let hour = dateObj.getHours()
|
|
231
|
+
const min = pad(dateObj.getMinutes())
|
|
232
|
+
const ampm = hour >= 12 ? 'PM' : 'AM'
|
|
233
|
+
hour = hour % 12
|
|
234
|
+
hour = hour ? hour : 12
|
|
235
|
+
const h12 = pad(hour)
|
|
236
|
+
return `${y}-${m}-${d} ${h12}:${min} ${ampm}`
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error('Error formatting date:', error)
|
|
239
|
+
return ''
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const isLatest = (restaurantLastUpdatedAt?: string) =>
|
|
244
|
+
(lastUpdatedAt.value == null && restaurantLastUpdatedAt == null) ||
|
|
245
|
+
lastUpdatedAt.value === restaurantLastUpdatedAt
|
|
246
|
+
|
|
247
|
+
const columns = computed<ColumnDef<{ name: string; lastUpdatedAt: string }>[]>(() => [
|
|
248
|
+
{
|
|
249
|
+
accessorKey: 'name',
|
|
250
|
+
header: () => t('order.discountRule.restaurantName'),
|
|
251
|
+
enableSorting: false
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
accessorKey: 'lastUpdatedAt',
|
|
255
|
+
header: () => t('order.discountRule.version'),
|
|
256
|
+
cell: ({ row }) =>
|
|
257
|
+
row.original.lastUpdatedAt ? h('span', formatDate(row.original.lastUpdatedAt)) : '-',
|
|
258
|
+
enableSorting: false
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
accessorKey: 'status',
|
|
262
|
+
header: () => t('order.discountRule.status'),
|
|
263
|
+
cell: ({ row }) =>
|
|
264
|
+
isLatest(row.original.lastUpdatedAt)
|
|
265
|
+
? h(components.FmChip, { variant: 'success', label: t('order.discountRule.latest') })
|
|
266
|
+
: h(components.FmChip, { variant: 'critical', label: t('order.discountRule.outdated') }),
|
|
267
|
+
enableSorting: false
|
|
268
|
+
}
|
|
269
|
+
])
|
|
270
|
+
|
|
271
|
+
function isEffectInOtherGroups(effectId: string, currentGroupIndex: number | null): boolean {
|
|
272
|
+
if (currentGroupIndex === null) return false
|
|
273
|
+
return effectGroups.value.some((group, index) => {
|
|
274
|
+
if (index === currentGroupIndex) return false
|
|
275
|
+
return group.effectIds.includes(effectId)
|
|
276
|
+
})
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const processedEffects = computed(() => {
|
|
280
|
+
if (!effects.value || !selectedEffectGroup.value) {
|
|
281
|
+
return []
|
|
282
|
+
}
|
|
283
|
+
return effects.value.map((effect) => {
|
|
284
|
+
const isSelectedInCurrentGroup =
|
|
285
|
+
selectedEffectGroup.value?.effectIds?.includes(effect.id) ?? false
|
|
286
|
+
const isInOtherGroups = isEffectInOtherGroups(effect.id, selectedEffectIndex.value)
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
...effect,
|
|
290
|
+
id: effect.id,
|
|
291
|
+
name: effect.name,
|
|
292
|
+
isSelectedInCurrentGroup,
|
|
293
|
+
isInOtherGroups,
|
|
294
|
+
isDisabled: isInOtherGroups && !isSelectedInCurrentGroup,
|
|
295
|
+
showUsedInOtherGroupHint: isInOtherGroups
|
|
296
|
+
}
|
|
297
|
+
})
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
const isAllSelectedForCurrentGroup = computed(() => {
|
|
301
|
+
if (!selectedEffectGroup.value || !effects.value.length || selectedEffectIndex.value === null)
|
|
302
|
+
return false
|
|
303
|
+
|
|
304
|
+
const selectableEffectsInCurrentGroup = effects.value.filter(
|
|
305
|
+
(effect: Effect) =>
|
|
306
|
+
selectedEffectGroup.value?.effectIds.includes(effect.id) ||
|
|
307
|
+
!isEffectInOtherGroups(effect.id, selectedEffectIndex.value)
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
if (!selectableEffectsInCurrentGroup.length && effects.value.length > 0) {
|
|
311
|
+
return false
|
|
312
|
+
}
|
|
313
|
+
if (!selectableEffectsInCurrentGroup.length && effects.value.length === 0) {
|
|
314
|
+
return false
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return selectableEffectsInCurrentGroup.every((effect: Effect) =>
|
|
318
|
+
selectedEffectGroup.value?.effectIds.includes(effect.id)
|
|
319
|
+
)
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
function selectAllEffects(v: boolean) {
|
|
323
|
+
if (!selectedEffectGroup.value || selectedEffectIndex.value === null) return
|
|
324
|
+
|
|
325
|
+
if (v) {
|
|
326
|
+
const effectsToAdd = effects.value
|
|
327
|
+
.filter((effect: Effect) => !isEffectInOtherGroups(effect.id, selectedEffectIndex.value))
|
|
328
|
+
.map((effect: Effect) => effect.id)
|
|
329
|
+
const currentEffectsInGroup = selectedEffectGroup.value.effectIds || []
|
|
330
|
+
selectedEffectGroup.value.effectIds = [...new Set([...currentEffectsInGroup, ...effectsToAdd])]
|
|
331
|
+
} else {
|
|
332
|
+
selectedEffectGroup.value.effectIds = []
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function selectEffect(effect: { id: string; isInOtherGroups: boolean }, isSelected: boolean) {
|
|
337
|
+
if (!selectedEffectGroup.value || selectedEffectIndex.value === null) return
|
|
338
|
+
|
|
339
|
+
const effectId = effect.id
|
|
340
|
+
|
|
341
|
+
if (isSelected) {
|
|
342
|
+
if (effect.isInOtherGroups) {
|
|
343
|
+
showError(t('order.discountRule.effectUsedInOtherGroup'))
|
|
344
|
+
}
|
|
345
|
+
if (!selectedEffectGroup.value.effectIds.includes(effectId)) {
|
|
346
|
+
selectedEffectGroup.value.effectIds.push(effectId)
|
|
347
|
+
}
|
|
348
|
+
} else {
|
|
349
|
+
selectedEffectGroup.value.effectIds = selectedEffectGroup.value.effectIds.filter(
|
|
350
|
+
(id) => id !== effectId
|
|
351
|
+
)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function toggleSideSheet(index: number) {
|
|
356
|
+
selectedEffectGroup.value = effectGroups.value[index] ? { ...effectGroups.value[index] } : null
|
|
357
|
+
selectedEffectIndex.value = index
|
|
358
|
+
sideSheet.value = true
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function confirm() {
|
|
362
|
+
sideSheet.value = false
|
|
363
|
+
if (selectedEffectGroup.value && selectedEffectIndex.value != null) {
|
|
364
|
+
effectGroups.value[selectedEffectIndex.value] = selectedEffectGroup.value
|
|
365
|
+
}
|
|
366
|
+
selectedEffectGroup.value = null
|
|
367
|
+
selectedEffectIndex.value = null
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function onCancel() {
|
|
371
|
+
sideSheet.value = false
|
|
372
|
+
selectedEffectGroup.value = null
|
|
373
|
+
selectedEffectIndex.value = null
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function createRule() {
|
|
377
|
+
effectGroups.value = [...effectGroups.value, { maxApplicableEffects: 1, effectIds: [] }]
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function deleteRule(index: number) {
|
|
381
|
+
const groups = [...effectGroups.value]
|
|
382
|
+
groups.splice(index, 1)
|
|
383
|
+
effectGroups.value = groups
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async function _updateDiscountRule(effectGroups: FdoEffectGroup[]) {
|
|
387
|
+
await startAsyncCallWithErr(async () => {
|
|
388
|
+
const discountRule = await businessStore.updateDiscountRule({
|
|
389
|
+
effectGroups,
|
|
390
|
+
lastUpdatedAt: lastUpdatedAt.value || ''
|
|
391
|
+
})
|
|
392
|
+
applyDiscountRuleSettings(discountRule)
|
|
393
|
+
await initSetting()
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async function updateDiscountRule() {
|
|
398
|
+
await _updateDiscountRule(effectGroups.value)
|
|
399
|
+
showSuccess(t('order.discountRule.updateSuccess'))
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async function syncDiscountRule() {
|
|
403
|
+
await _updateDiscountRule(rawEffectGroups.value)
|
|
404
|
+
showSuccess(t('order.discountRule.syncSuccess'))
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function applyDiscountRuleSettings(res: FdtoDiscountRuleRes) {
|
|
408
|
+
lastUpdatedAt.value = res.lastUpdatedAt || null
|
|
409
|
+
restaurants.value = res.restaurants.map((restaurant) => ({
|
|
410
|
+
...restaurant,
|
|
411
|
+
lastUpdatedAt: restaurant.lastUpdatedAt || ''
|
|
412
|
+
}))
|
|
413
|
+
rawEffectGroups.value = res.discountRule?.effectGroups || []
|
|
414
|
+
effectGroups.value = res.discountRule?.effectGroups || []
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async function initSetting() {
|
|
418
|
+
await startAsyncCallWithErr(async () => {
|
|
419
|
+
const discountRule = await businessStore.readDiscountRule()
|
|
420
|
+
applyDiscountRuleSettings(discountRule)
|
|
421
|
+
if (currentBusiness.value) {
|
|
422
|
+
effects.value = await effectApi.getEffects(currentBusiness.value._id)
|
|
423
|
+
}
|
|
424
|
+
})
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
onMounted(async () => {
|
|
428
|
+
await initSetting()
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
watch([() => currentBusiness.value], async () => {
|
|
432
|
+
await initSetting()
|
|
433
|
+
})
|
|
434
|
+
</script>
|