@feedmepos/mf-order-setting 0.0.26 → 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.
Files changed (146) hide show
  1. package/dist/{KioskDevicesView-BiF6v7Zj.js → KioskDevicesView-BgXkmJ7v.js} +1 -1
  2. package/dist/KioskDevicesView.vue_vue_type_script_setup_true_lang-DZT0BuUN.js +301 -0
  3. package/dist/{KioskSettingView-COhGcRtP.js → KioskSettingView-DyX3Wv_2.js} +3 -3
  4. package/dist/{KioskView-C1T-n1MY.js → KioskView-Bgff7QPc.js} +5 -5
  5. package/dist/OrderSettingsView-C63s4uCD.js +74334 -0
  6. package/dist/app-Dp79Gu_F.js +1016 -0
  7. package/dist/app.js +1 -1
  8. package/dist/{dayjs.min-BHDLv42p.js → dayjs.min-B2ZkfNUH.js} +633 -641
  9. package/dist/frontend/mf-order/src/App.vue.d.ts +1 -1
  10. package/dist/frontend/mf-order/src/Entry.vue.d.ts +1 -1
  11. package/dist/frontend/mf-order/src/api/business/index.d.ts +5 -0
  12. package/dist/frontend/mf-order/src/api/effects/index.d.ts +3 -0
  13. package/dist/frontend/mf-order/src/api/index.d.ts +2 -0
  14. package/dist/frontend/mf-order/src/api/kiosk/index.d.ts +2 -0
  15. package/dist/frontend/mf-order/src/app.d.ts +336 -0
  16. package/dist/frontend/mf-order/src/components/GoogleMap.vue.d.ts +3 -5
  17. package/dist/frontend/mf-order/src/main.d.ts +79 -0
  18. package/dist/frontend/mf-order/src/modules/kiosk/interface.d.ts +5 -1
  19. package/dist/frontend/mf-order/src/stores/business/index.d.ts +62 -0
  20. package/dist/frontend/mf-order/src/stores/kiosk/index.d.ts +16 -1
  21. package/dist/frontend/mf-order/src/stores/menu/menu.d.ts +207 -112
  22. package/dist/frontend/mf-order/src/stores/restaurant/index.d.ts +81 -78
  23. package/dist/frontend/mf-order/src/views/all-orders/ActionMenuCell.vue.d.ts +2 -2
  24. package/dist/frontend/mf-order/src/views/all-orders/FilterRestaurant.vue.d.ts +1 -1
  25. package/dist/frontend/mf-order/src/views/all-orders/FilterStatus.vue.d.ts +2 -2
  26. package/dist/frontend/mf-order/src/views/all-orders/FilterStatusMenu.vue.d.ts +2 -2
  27. package/dist/frontend/mf-order/src/views/all-orders/ReflowOrder.vue.d.ts +56 -54
  28. package/dist/frontend/mf-order/src/views/all-orders/UpdateDeliveryOrderDialog.vue.d.ts +2 -2
  29. package/dist/frontend/mf-order/src/views/kiosk/KioskSummary.vue.d.ts +1 -1
  30. package/dist/frontend/mf-order/src/views/kiosk/KioskView.vue.d.ts +1 -1
  31. package/dist/frontend/mf-order/src/views/kiosk/devices/KioskDeviceCard.vue.d.ts +1 -1
  32. package/dist/frontend/mf-order/src/views/kiosk/devices/KioskDeviceDetail.vue.d.ts +1 -1
  33. package/dist/frontend/mf-order/src/views/kiosk/devices/KioskDevicesView.vue.d.ts +1 -1
  34. package/dist/frontend/mf-order/src/views/kiosk/devices/KioskOtpDialog.vue.d.ts +1 -1
  35. package/dist/frontend/mf-order/src/views/kiosk/devices/KioskUnbindConfirm.vue.d.ts +2 -2
  36. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskDineInSection.vue.d.ts +2 -2
  37. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskDisplayStandSection.vue.d.ts +2 -2
  38. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskEnablePaxDialogSection.vue.d.ts +2 -2
  39. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskInstructionSection.vue.d.ts +2 -2
  40. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskMenuItemSection.vue.d.ts +1 -1
  41. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskPaymentTypeSection.vue.d.ts +1 -1
  42. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskPickAtCounterSection.vue.d.ts +2 -2
  43. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskSettingView.vue.d.ts +1 -1
  44. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskTakeawaySection.vue.d.ts +2 -2
  45. package/dist/frontend/mf-order/src/views/order-settings/delivery/DeliveryList.vue.d.ts +2 -2
  46. package/dist/frontend/mf-order/src/views/order-settings/delivery/components/ManualIntegratedDeliverySetting.vue.d.ts +1 -1
  47. package/dist/frontend/mf-order/src/views/order-settings/delivery/components/TaxInput.vue.d.ts +2 -2
  48. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/CurrencyInput.vue.d.ts +1 -1
  49. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/DeliveryCustomTime.vue.d.ts +1 -1
  50. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/DeliveryOrder.vue.d.ts +6 -141
  51. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/DeliveryTime.vue.d.ts +1 -1
  52. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/InHouseDelivery.vue.d.ts +1 -1
  53. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/TimePicker.vue.d.ts +1 -1
  54. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/ZoneDialog.vue.d.ts +1 -1
  55. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/ExternalSetting.vue.d.ts +6 -2
  56. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/FeedmeDelivery.vue.d.ts +1 -1
  57. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/FoodpandaCampaignDialog.vue.d.ts +1 -1
  58. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/FoodpandaSetting.vue.d.ts +1 -1
  59. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/GrabfoodSetting.vue.d.ts +1 -1
  60. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/IntegratedDelivery.vue.d.ts +5 -5
  61. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/ShopeefoodSetting.vue.d.ts +1 -1
  62. package/dist/frontend/mf-order/src/views/order-settings/dine-in/OfflinePaymentTypeDialog.vue.d.ts +1 -1
  63. package/dist/frontend/mf-order/src/views/order-settings/dine-in/OfflinePaymentTypeDialogContent.vue.d.ts +2 -2
  64. package/dist/frontend/mf-order/src/views/order-settings/dine-in/PaymentType.vue.d.ts +1 -1
  65. package/dist/frontend/mf-order/src/views/order-settings/discount-rule/DiscountRuleSetting.vue.d.ts +2 -0
  66. package/dist/frontend/mf-order/src/views/order-settings/pickup/AddressInput.vue.d.ts +1 -1
  67. package/dist/frontend/mf-order/src/views/order-settings/pickup/CustomPayment.vue.d.ts +1 -1
  68. package/dist/frontend/mf-order/src/views/order-settings/pickup/PaymentSidesheet.vue.d.ts +2 -2
  69. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpPointDialog.vue.d.ts +1 -1
  70. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpPointDialogContent.vue.d.ts +2 -137
  71. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpSettingDialog.vue.d.ts +1 -1
  72. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpSettingDialogContent.vue.d.ts +1 -1
  73. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickupList.vue.d.ts +2 -2
  74. package/dist/frontend/mf-order/src/views/order-settings/pickup/Preorder.vue.d.ts +1 -1
  75. package/dist/frontend/mf-order/src/views/order-settings/servicecharge/RateInput.vue.d.ts +1 -1
  76. package/dist/frontend/mf-order/src/views/order-settings/servicecharge/ServiceChargeRule.vue.d.ts +1 -1
  77. package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
  78. package/dist/{index-DSCb3ndM.js → index-BXsnV_eO.js} +5 -5
  79. package/dist/{index-B5kfsi9C.js → index-DzQn92Tp.js} +2 -2
  80. package/dist/package/entity/booking/booking.do.d.ts +596 -551
  81. package/dist/package/entity/cursor/cursor.dto.d.ts +2 -2
  82. package/dist/package/entity/delivery/delivery.dto.d.ts +118 -109
  83. package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +349 -659
  84. package/dist/package/entity/incoming-order/incoming-order.do.d.ts +13800 -487
  85. package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +746 -1245
  86. package/dist/package/entity/incoming-order/incoming-order.enum.d.ts +1 -1
  87. package/dist/package/entity/index.d.ts +1 -0
  88. package/dist/package/entity/kiosk/kiosk.do.d.ts +64 -0
  89. package/dist/package/entity/kiosk/kiosk.dto.d.ts +79 -0
  90. package/dist/package/entity/kiosk/marketing/marketing.dto.d.ts +1469 -621
  91. package/dist/package/entity/member/member.dto.d.ts +14 -7
  92. package/dist/package/entity/order/dine-in/dine-in.do.d.ts +8 -8
  93. package/dist/package/entity/order/dine-in/dine-in.dto.d.ts +4 -4
  94. package/dist/package/entity/order/effects/effect.dto.d.ts +154 -6
  95. package/dist/package/entity/order/menu/menu.dto.d.ts +12 -12
  96. package/dist/package/entity/order/order-item/order-item.dto.d.ts +101 -42
  97. package/dist/package/entity/order/order.do.d.ts +206 -601
  98. package/dist/package/entity/order/order.dto.d.ts +1096 -1600
  99. package/dist/package/entity/order/order.enum.d.ts +2 -2
  100. package/dist/package/entity/order-platform/external/menu/external-menu.dto.d.ts +8 -0
  101. package/dist/package/entity/order-platform/external/order/external-order.do.d.ts +8 -0
  102. package/dist/package/entity/order-platform/external/order/external-order.dto.d.ts +22 -3
  103. package/dist/package/entity/order-platform/external/order/external-order.enum.d.ts +1 -1
  104. package/dist/package/entity/order-platform/external/setting/external-setting.do.d.ts +5 -0
  105. package/dist/package/entity/order-platform/external/setting/external-setting.dto.d.ts +5 -0
  106. package/dist/package/entity/order-platform/external/zus/zus-menu.dto.d.ts +192 -0
  107. package/dist/package/entity/order-platform/foodpanda/foodpanda-order.do.d.ts +104 -0
  108. package/dist/package/entity/order-platform/foodpanda/foodpanda-order.dto.d.ts +152 -109
  109. package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.do.d.ts +3 -0
  110. package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.dto.d.ts +3 -0
  111. package/dist/package/entity/order-platform/foodpanda/foodpanda.enum.d.ts +2 -0
  112. package/dist/package/entity/order-platform/grabfood/grabfood-order.do.d.ts +139 -109
  113. package/dist/package/entity/order-platform/grabfood/grabfood-settings.do.d.ts +3 -0
  114. package/dist/package/entity/order-platform/grabfood/grabfood.dto.d.ts +112 -2
  115. package/dist/package/entity/order-platform/menu.dto.d.ts +31 -0
  116. package/dist/package/entity/order-platform/order-platform.dto.d.ts +6 -3
  117. package/dist/package/entity/order-platform/shopeefood/shopeefood-order.do.d.ts +164 -109
  118. package/dist/package/entity/order-platform/shopeefood/shopeefood-order.dto.d.ts +22 -0
  119. package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.do.d.ts +3 -0
  120. package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.dto.d.ts +3 -0
  121. package/dist/{queue.do-y-ubeoKZ.js → queue.do-BUtcyDk3.js} +53522 -50841
  122. package/package.json +4 -3
  123. package/src/api/business/index.ts +16 -0
  124. package/src/api/effects/index.ts +7 -0
  125. package/src/api/index.ts +9 -1
  126. package/src/api/kiosk/index.ts +9 -4
  127. package/src/app.ts +4 -1
  128. package/src/locales/en-US.json +24 -1
  129. package/src/locales/th-TH.json +31 -1
  130. package/src/locales/zh-CN.json +27 -1
  131. package/src/modules/kiosk/interface.ts +5 -1
  132. package/src/stores/business/index.ts +45 -0
  133. package/src/stores/kiosk/index.ts +9 -4
  134. package/src/stores/kiosk/mapper.ts +5 -1
  135. package/src/stores/restaurant/index.ts +3 -1
  136. package/src/views/kiosk/devices/KioskDeviceCard.vue +202 -80
  137. package/src/views/order-settings/OrderSettingsView.vue +17 -5
  138. package/src/views/order-settings/delivery/DeliverySetting.vue +1 -1
  139. package/src/views/order-settings/delivery/delivery.data.ts +2 -2
  140. package/src/views/order-settings/delivery/integrated-delivery/ExternalSetting.vue +14 -2
  141. package/src/views/order-settings/delivery/integrated-delivery/FoodpandaSetting.vue +2 -34
  142. package/src/views/order-settings/delivery/integrated-delivery/IntegratedDelivery.vue +15 -12
  143. package/src/views/order-settings/discount-rule/DiscountRuleSetting.vue +434 -0
  144. package/dist/KioskDevicesView.vue_vue_type_script_setup_true_lang-1r_DBAc-.js +0 -207
  145. package/dist/OrderSettingsView-CI5bdVXr.js +0 -72108
  146. package/dist/app-BfWp4ow3.js +0 -682
@@ -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>
@@ -1,207 +0,0 @@
1
- import { defineComponent as g, ref as D, resolveComponent as f, openBlock as i, createElementBlock as c, createElementVNode as a, toDisplayString as d, unref as m, createVNode as v, computed as B, withCtx as F, Fragment as y, renderList as h, createCommentVNode as C, createBlock as M } from "vue";
2
- import { useDialog as O, useSnackbar as q } from "@feedmepos/ui-library";
3
- import { useI18n as I } from "@feedmepos/mf-common";
4
- import { defineStore as N } from "pinia";
5
- import { r as w, g as K, D as T } from "./dayjs.min-BHDLv42p.js";
6
- import "./queue.do-y-ubeoKZ.js";
7
- const U = /* @__PURE__ */ g({
8
- __name: "KioskUnbindConfirm",
9
- props: {
10
- machineId: {}
11
- },
12
- emits: ["update:modelValue"],
13
- setup(e, { emit: t }) {
14
- const { t: n } = I(), l = t, o = D("");
15
- function s(r) {
16
- l("update:modelValue", r);
17
- }
18
- return (r, x) => {
19
- const _ = f("FmTextField");
20
- return i(), c("div", null, [
21
- a("span", null, d(m(n)("order.unbindKioskDeviceWarning", { machineId: r.machineId })), 1),
22
- v(_, {
23
- "model-value": o.value,
24
- "onUpdate:modelValue": s,
25
- placeholder: r.machineId
26
- }, null, 8, ["model-value", "placeholder"])
27
- ]);
28
- };
29
- }
30
- });
31
- async function Y() {
32
- const e = await w().get("/kiosk/otp");
33
- return K(e);
34
- }
35
- async function j() {
36
- const e = await w().get("/kiosk/devices");
37
- return K(e);
38
- }
39
- async function L(e) {
40
- await w().delete(`/kiosk/unbind/${e}`);
41
- }
42
- const k = {
43
- requestOtp: Y,
44
- getDevices: j,
45
- unbind: L
46
- }, W = (e) => ({
47
- name: e.name ?? "N/A",
48
- machineId: e.machineId,
49
- config: {
50
- scannerInfo: e.scannerInfo ?? void 0,
51
- printerInfo: e.printerInfo ?? void 0,
52
- terminalInfo: e.terminalInfo ?? void 0
53
- },
54
- activatedAt: H(e.token)
55
- });
56
- function H(e) {
57
- const t = e.substring(0, 8), n = parseInt(t, 16);
58
- return new Date(n * 1e3);
59
- }
60
- const P = {
61
- toMfKioskDevice: W
62
- }, z = N("kiosk", () => {
63
- const e = D({
64
- otp: "",
65
- devices: []
66
- });
67
- async function t() {
68
- const o = await k.requestOtp();
69
- e.value.otp = o.otp;
70
- }
71
- async function n() {
72
- const o = await k.getDevices();
73
- e.value.devices = o.map((s) => P.toMfKioskDevice(s));
74
- }
75
- async function l(o) {
76
- await k.unbind(o), await n();
77
- }
78
- return {
79
- state: e.value,
80
- requestOtp: t,
81
- getDevices: n,
82
- unbind: l
83
- };
84
- }), E = { class: "border fm-corner-radius-lg flex justify-between pr-[1rem] w-11/12" }, G = { class: "py-[1rem] flex flex-col gap-6" }, J = { class: "fm-typo-en-title-sm-600" }, Q = { class: "w-full border p-[1.5rem] fm-corner-radius-lg flex flex-col gap-2" }, R = {
85
- key: 0,
86
- class: "fm-typo-en-title-sm-600"
87
- }, X = { class: "flex flex-col gap-1" }, Z = { class: "fm-typo-en-body-lg-400 text-fm-color-typo-secondary" }, ee = { class: "fm-typo-en-body-lg-600 block" }, te = /* @__PURE__ */ g({
88
- __name: "KioskDeviceCard",
89
- props: {
90
- device: {}
91
- },
92
- setup(e) {
93
- const { t } = I(), n = O(), l = q(), o = z(), s = e, r = D(""), x = B(() => Object.entries(s.device.config));
94
- function _() {
95
- r.value = "", n.open({
96
- title: t("order.unbindKioskDevice"),
97
- contentComponent: U,
98
- contentComponentProps: {
99
- machineId: s.device.machineId,
100
- "onUpdate:modelValue": (p) => {
101
- r.value = p;
102
- }
103
- },
104
- dismissAway: !1,
105
- primaryActions: {
106
- text: t("order.unbind"),
107
- variant: "destructive",
108
- close: !1
109
- },
110
- secondaryActions: {
111
- text: t("order.cancel"),
112
- variant: "tertiary",
113
- close: !0
114
- }
115
- }).onPrimary(async () => {
116
- r.value == s.device.machineId ? (await V(), l.open({
117
- type: "success",
118
- message: t("order.unbindSuccess"),
119
- position: "bottom"
120
- }), n.close()) : l.open({
121
- type: "warning",
122
- message: t("order.unbindWarning"),
123
- position: "bottom"
124
- });
125
- });
126
- }
127
- async function V() {
128
- await o.unbind(s.device.machineId);
129
- }
130
- return (p, ce) => {
131
- const S = f("FmListItem"), $ = f("FmSideSheet"), A = f("FmButton");
132
- return i(), c("div", E, [
133
- v($, {
134
- header: m(t)("order.deviceDetails"),
135
- "dismiss-away": "",
136
- class: "w-full",
137
- maxWidth: 700
138
- }, {
139
- "side-sheet-button": F(() => [
140
- v(S, {
141
- class: "flex-1",
142
- label: p.device.name,
143
- sublabel: `${m(t)("order.activatedDate")}: ${m(T)(p.device.activatedAt).format("DD MMM YYYY HH:mm")}`
144
- }, null, 8, ["label", "sublabel"])
145
- ]),
146
- default: F(() => [
147
- a("div", G, [
148
- a("span", J, d(p.device.name), 1),
149
- (i(!0), c(y, null, h(x.value.filter((u) => u[1]), (u) => (i(), c("div", Q, [
150
- u[1] ? (i(), c("span", R, d(u[0]), 1)) : C("", !0),
151
- u[1] ? (i(!0), c(y, { key: 1 }, h(Object.entries(u[1]), (b) => (i(), c("div", X, [
152
- a("span", Z, d(b[0]), 1),
153
- a("span", ee, d(b[1] == "" ? "-" : b[1]), 1)
154
- ]))), 256)) : C("", !0)
155
- ]))), 256))
156
- ])
157
- ]),
158
- _: 1
159
- }, 8, ["header"]),
160
- v(A, {
161
- variant: "plain",
162
- "append-icon": "link_off",
163
- class: "text-fm-color-system-error-300 align-middle my-auto",
164
- onClick: _
165
- })
166
- ]);
167
- };
168
- }
169
- }), ne = { class: "flex flex-col gap-2" }, oe = { class: "flex flex-col gap-2" }, se = { class: "fm-typo-en-title-sm-600 block" }, ie = { class: "fm-typo-en-body-md-400 block" }, ae = { class: "flex flex-col gap-6" }, fe = /* @__PURE__ */ g({
170
- __name: "KioskDevicesView",
171
- props: {
172
- devices: {},
173
- requestOtp: { type: Function }
174
- },
175
- setup(e) {
176
- const { t } = I();
177
- return (n, l) => {
178
- const o = f("FmButton");
179
- return i(), c("div", null, [
180
- a("div", ne, [
181
- a("div", oe, [
182
- a("span", se, d(m(t)("order.kioskDisplay")), 1),
183
- a("span", ie, d(m(t)("order.kioskDisplayDescription")), 1)
184
- ]),
185
- a("div", ae, [
186
- (i(!0), c(y, null, h(n.devices, (s) => (i(), M(te, {
187
- key: s.machineId,
188
- device: s
189
- }, null, 8, ["device"]))), 128)),
190
- v(o, {
191
- variant: "plain",
192
- class: "w-[10rem] border border-fm-color-primary fm-corner-radius-lg",
193
- label: m(t)("order.bindDevice"),
194
- size: "md",
195
- "prepend-icon": "link",
196
- onClick: n.requestOtp
197
- }, null, 8, ["label", "onClick"])
198
- ])
199
- ])
200
- ]);
201
- };
202
- }
203
- });
204
- export {
205
- fe as _,
206
- z as u
207
- };