@feedmepos/mf-order-setting 0.0.27 → 0.0.29

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