@feedmepos/mf-order-setting 0.0.28 → 0.0.30

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 (28) hide show
  1. package/dist/{KioskDevicesView-BgXkmJ7v.js → KioskDevicesView-Dvr4RUmt.js} +1 -1
  2. package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-DZT0BuUN.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-CJ-xAR8i.js} +2 -2
  3. package/dist/{KioskSettingView-DyX3Wv_2.js → KioskSettingView-DaJz8ZZi.js} +1 -1
  4. package/dist/{KioskView-Bgff7QPc.js → KioskView-v8Yl4x4R.js} +4 -4
  5. package/dist/{OrderSettingsView-C63s4uCD.js → OrderSettingsView-DT9krR3_.js} +10916 -10702
  6. package/dist/{app-Dp79Gu_F.js → app-Dhx_DQ6c.js} +36 -15
  7. package/dist/app.js +1 -1
  8. package/dist/{dayjs.min-B2ZkfNUH.js → dayjs.min-BLlPHZkl.js} +1 -1
  9. package/dist/frontend/mf-order/src/api/remoteOrder/index.d.ts +1 -0
  10. package/dist/frontend/mf-order/src/app.d.ts +21 -0
  11. package/dist/frontend/mf-order/src/main.d.ts +21 -0
  12. package/dist/frontend/mf-order/src/stores/menu/menu.d.ts +1 -0
  13. package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
  14. package/dist/{index-DzQn92Tp.js → index-Cg9kSeyn.js} +2 -2
  15. package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +3 -0
  16. package/dist/package/entity/order/pickup/pickup.dto.d.ts +37 -0
  17. package/dist/package/entity/order-platform/grabfood/grabfood.dto.d.ts +40 -0
  18. package/dist/package/entity/order-platform/grabfood/grabfood.enum.d.ts +2 -0
  19. package/dist/package/entity/queue/queue.dto.d.ts +11446 -93
  20. package/dist/package/entity/user/user.do.d.ts +129 -18
  21. package/dist/{queue.do-BUtcyDk3.js → queue.do-zk6sqriQ.js} +4543 -4509
  22. package/package.json +2 -2
  23. package/src/api/remoteOrder/index.ts +3 -0
  24. package/src/locales/en-US.json +8 -1
  25. package/src/locales/th-TH.json +8 -1
  26. package/src/locales/zh-CN.json +8 -1
  27. package/src/views/order-settings/delivery/integrated-delivery/GrabfoodSetting.vue +38 -1
  28. package/src/views/order-settings/discount-rule/DiscountRuleSetting.vue +47 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feedmepos/mf-order-setting",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "type": "module",
5
5
  "module": "./dist/app.js",
6
6
  "license": "UNLICENSED",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@feedmepos/core": "^2.14.19",
30
- "@feedmepos/menu": "^1.5.18",
30
+ "@feedmepos/menu": "^1.5.21",
31
31
  "@feedmepos/mf-common": "1.20.0-beta.2",
32
32
  "@feedmepos/ordering": "^0.0.3",
33
33
  "@feedmepos/ui-library": "1.5.2-beta.1",
@@ -88,6 +88,9 @@ export const remoteOrderApi = {
88
88
  async syncGrabfoodMenu(merchantId: string): Promise<FdoGrabfoodSettings> {
89
89
  return getData(await deliveryClientInstance('grabfood').get(`/menu-sync/${merchantId}`));
90
90
  },
91
+ async startSelfServeFlow(restaurantId: string): Promise<string|null> {
92
+ return getData(await deliveryClientInstance('grabfood').get(`/setting/integration-url/${restaurantId}`));
93
+ },
91
94
 
92
95
  async readShopeefood(restaurantId: string): Promise<FdoShopeeFoodSettings | null> {
93
96
  return getData(await deliveryClientInstance('shopeefood').get(`/setting/${restaurantId}`));
@@ -207,6 +207,11 @@
207
207
  "selectRestaurant": "Select Restaurant",
208
208
  "selectServiceChargeType": "Select service charge type",
209
209
  "selectTable": "Select table",
210
+ "selfServeActivation": {
211
+ "title": "Self Serve Activation",
212
+ "subTitle": "New to the flow? Click here to",
213
+ "learnMore": "learn more"
214
+ },
210
215
  "serve": "serve",
211
216
  "serviceCharge": "Service Charge",
212
217
  "serviceChargeRule": "* Service Charge required POS version 4.0.0 or higher",
@@ -286,7 +291,9 @@
286
291
  "syncSuccess": "Discount rule setting synced to all restaurants",
287
292
  "title": "Discount Rule",
288
293
  "updateSuccess": "Discount rule setting updated",
289
- "version": "Version"
294
+ "version": "Version",
295
+ "promotion": "Promotion",
296
+ "voucher": "Voucher"
290
297
  }
291
298
  }
292
299
  }
@@ -203,6 +203,11 @@
203
203
  "selectRestaurant": "เลือกร้านอาหาร",
204
204
  "selectServiceChargeType": "เลือกประเภทค่าบริการ",
205
205
  "selectTable": "เลือกโต๊ะ",
206
+ "selfServeActivation": {
207
+ "title": "เปิดใช้งานการบริการตนเอง",
208
+ "subTitle": "เปิดใช้งานการบริการตนเองเพื่อให้ลูกค้าสามารถสั่งซื้อได้ด้วยตนเอง",
209
+ "learnMore": "เรียนรู้เพิ่มเติม"
210
+ },
206
211
  "serve": "เสิร์ฟ",
207
212
  "serviceCharge": "ค่าบริการ",
208
213
  "serviceChargeRule": "* ค่าบริการจำเป็นต้องใช้ POS เวอร์ชัน 4.0.0 ขึ้นไป",
@@ -281,7 +286,9 @@
281
286
  "syncSuccess": "ซิงค์กฎส่วนลดไปยังร้านอาหารทั้งหมดเรียบร้อยแล้ว",
282
287
  "title": "กฎส่วนลด",
283
288
  "updateSuccess": "อัปเดตกฎส่วนลดเรียบร้อยแล้ว",
284
- "version": "เวอร์ชัน"
289
+ "version": "เวอร์ชัน",
290
+ "promotion": "โปรโมชั่น",
291
+ "voucher": "บัตรกำนัล"
285
292
  }
286
293
  }
287
294
  }
@@ -210,6 +210,11 @@
210
210
  "selectRestaurant": "选择餐厅",
211
211
  "selectServiceChargeType": "选择服务费类型",
212
212
  "selectTable": "选择餐桌",
213
+ "selfServeActivation": {
214
+ "title": "自助激活对接",
215
+ "subTitle": "第一次使用这个流程?点击此处",
216
+ "learnMore": "了解更多"
217
+ },
213
218
  "serve": "服务",
214
219
  "serviceCharge": "服务费",
215
220
  "serviceChargeRule": "* 服务费功能仅适用于POS版本4.0.0或更高版本。",
@@ -289,7 +294,9 @@
289
294
  "syncSuccess": "折扣规则设置已同步到所有餐厅",
290
295
  "title": "折扣规则",
291
296
  "updateSuccess": "折扣规则设置已更新",
292
- "version": "版本"
297
+ "version": "版本",
298
+ "promotion": "促销",
299
+ "voucher": "代金券"
293
300
  }
294
301
  }
295
302
  }
@@ -88,7 +88,7 @@ async function syncMenu() {
88
88
  }
89
89
 
90
90
  import { useSnackbarFunctions } from '@/components/snackbar'
91
- const { showSuccess } = useSnackbarFunctions()
91
+ const { showSuccess, showError } = useSnackbarFunctions()
92
92
 
93
93
  async function flowTestOrder() {
94
94
  await startAsyncCallWithErr(async () => {
@@ -108,6 +108,20 @@ async function cancelTestOrder() {
108
108
  })
109
109
  showSuccess('Completed. ')
110
110
  }
111
+
112
+ async function startSelfServeFlow() {
113
+ const url = await startAsyncCallWithErr(async () => {
114
+ return await remoteOrderApi.integratedDelivery.startSelfServeFlow(
115
+ currentRestaurant.value?._id ?? ''
116
+ )
117
+ })
118
+
119
+ if (!url) {
120
+ showError(`Failed to get integration url for ${currentRestaurant?.value?._id}`)
121
+ } else {
122
+ window.open(url, '_blank')
123
+ }
124
+ }
111
125
  </script>
112
126
 
113
127
  <template>
@@ -120,4 +134,27 @@ async function cancelTestOrder() {
120
134
  @flow-test-order="flowTestOrder"
121
135
  @cancel-test-order="cancelTestOrder"
122
136
  />
137
+ <div v-if="canUseAutoDeliveryIntegration === true">
138
+ <div class="flex flex-row mt-5 items-center">
139
+ <div class="flex-grow fm-typo-en-title-sm-600 mb-3 mt-3">
140
+ {{ t('order.selfServeActivation.title') }}
141
+ </div>
142
+ <FmButton
143
+ variant="primary"
144
+ :label="t('order.start')"
145
+ @click="startSelfServeFlow"
146
+ class="m-1"
147
+ />
148
+ </div>
149
+ <div>
150
+ {{ t('order.selfServeActivation.subTitle') }}
151
+ <a
152
+ href="https://doc.clickup.com/25608366/d/h/rdg5e-52596/7d44e2bd89752e0"
153
+ target="_blank"
154
+ style="color: blue; text-decoration: underline"
155
+ >
156
+ {{ t('order.selfServeActivation.learnMore') }}</a
157
+ >.
158
+ </div>
159
+ </div>
123
160
  </template>
@@ -44,12 +44,18 @@
44
44
  />
45
45
  </div>
46
46
  <FmTextField
47
- v-model="group.maxApplicableEffects"
47
+ :model-value="group.maxApplicableEffects"
48
48
  :label="t('order.discountRule.maxTotalUses')"
49
49
  type="number"
50
50
  :rules="maxApplicableEffectsRules"
51
51
  :min="1"
52
52
  :helper-text="t('order.discountRule.maxTotalUsesSublabel')"
53
+ @update:model-value="
54
+ (newValue) => {
55
+ const parsedValue = parseInt(newValue)
56
+ group.maxApplicableEffects = isNaN(parsedValue) ? 1 : parsedValue
57
+ }
58
+ "
53
59
  />
54
60
  </FmCard>
55
61
  <FmCard
@@ -85,6 +91,7 @@
85
91
  v-model="sideSheet"
86
92
  >
87
93
  <div>
94
+ <FmSearch v-model="sideSheetSearch" :placeholder="t('order.search')" class="mb-4" />
88
95
  <div class="text-fm-color-typo-secondary mt-5 mb-5 flex flex-row">
89
96
  {{
90
97
  t('order.discountRule.effectSelected', {
@@ -101,22 +108,30 @@
101
108
  ></FmCheckbox>
102
109
 
103
110
  <div
104
- v-for="pEffect in processedEffects"
111
+ v-for="pEffect in filteredProcessedEffects"
105
112
  :key="pEffect.id"
106
- class="flex flex-col mb-2 ml-5"
113
+ class="flex flex-col mb-2 ml-5 cursor-pointer"
107
114
  >
108
115
  <div class="flex flex-row">
109
- <div class="flex flex-row items-center">
116
+ <div
117
+ class="flex flex-row items-center"
118
+ @click="selectEffect(pEffect, !pEffect.isSelectedInCurrentGroup)"
119
+ >
110
120
  <FmCheckbox
111
121
  :model-value="pEffect.isSelectedInCurrentGroup"
112
122
  value=""
113
123
  @update:model-value="(v) => selectEffect(pEffect, v)"
114
124
  :disabled="pEffect.isDisabled"
115
125
  />
116
- <div class="ml-2">
126
+ <div class="ml-2 flex flex-wrap gap-2 items-center">
127
+ <span
128
+ 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"
129
+ >
130
+ {{ pEffect.type }}
131
+ </span>
117
132
  <span>{{ pEffect.name }}</span>
118
133
  <template v-if="pEffect.showUsedInOtherGroupHint">
119
- <span class="text-sm text-fm-color-typo-secondary pl-1">
134
+ <span class="text-sm text-fm-color-typo-secondary">
120
135
  ({{ t('order.discountRule.effectUsedInOtherGroup') }})
121
136
  </span>
122
137
  </template>
@@ -187,6 +202,11 @@ import { components } from '@feedmepos/ui-library'
187
202
  interface Effect {
188
203
  id: string
189
204
  name: string
205
+ type: string
206
+ isSelectedInCurrentGroup: boolean
207
+ isInOtherGroups: boolean
208
+ isDisabled: boolean
209
+ showUsedInOtherGroupHint: boolean
190
210
  }
191
211
 
192
212
  const { startAsyncCallWithErr, isLoading } = useLoading()
@@ -217,6 +237,7 @@ const lastUpdatedAt = ref<string | null>(null)
217
237
  const effects = ref<Effect[]>([])
218
238
  const selectedEffectGroup = ref<FdoEffectGroup | null>(null)
219
239
  const selectedEffectIndex = ref<number | null>(null)
240
+ const sideSheetSearch = ref('')
220
241
 
221
242
  const pad = (n: number) => n.toString().padStart(2, '0')
222
243
 
@@ -284,11 +305,13 @@ const processedEffects = computed(() => {
284
305
  const isSelectedInCurrentGroup =
285
306
  selectedEffectGroup.value?.effectIds?.includes(effect.id) ?? false
286
307
  const isInOtherGroups = isEffectInOtherGroups(effect.id, selectedEffectIndex.value)
308
+ const isPromotion = effect.id.startsWith('promotion_')
287
309
 
288
310
  return {
289
311
  ...effect,
290
312
  id: effect.id,
291
313
  name: effect.name,
314
+ type: isPromotion ? t('order.discountRule.promotion') : t('order.discountRule.voucher'),
292
315
  isSelectedInCurrentGroup,
293
316
  isInOtherGroups,
294
317
  isDisabled: isInOtherGroups && !isSelectedInCurrentGroup,
@@ -297,25 +320,25 @@ const processedEffects = computed(() => {
297
320
  })
298
321
  })
299
322
 
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)
323
+ const filteredProcessedEffects = computed(() => {
324
+ const search = sideSheetSearch.value.trim().toLowerCase()
325
+ if (!search) return processedEffects.value
326
+ return processedEffects.value.filter(
327
+ (effect) =>
328
+ effect.name.toLowerCase().includes(search) || effect.type.toLowerCase().includes(search)
308
329
  )
330
+ })
309
331
 
310
- if (!selectableEffectsInCurrentGroup.length && effects.value.length > 0) {
311
- return false
312
- }
313
- if (!selectableEffectsInCurrentGroup.length && effects.value.length === 0) {
332
+ const isAllSelectedForCurrentGroup = computed(() => {
333
+ if (
334
+ !selectedEffectGroup.value ||
335
+ !filteredProcessedEffects.value.length ||
336
+ selectedEffectIndex.value === null
337
+ )
314
338
  return false
315
- }
316
339
 
317
- return selectableEffectsInCurrentGroup.every((effect: Effect) =>
318
- selectedEffectGroup.value?.effectIds.includes(effect.id)
340
+ return filteredProcessedEffects.value.every(
341
+ (effect: Effect) => effect.isSelectedInCurrentGroup || effect.isDisabled
319
342
  )
320
343
  })
321
344
 
@@ -323,8 +346,8 @@ function selectAllEffects(v: boolean) {
323
346
  if (!selectedEffectGroup.value || selectedEffectIndex.value === null) return
324
347
 
325
348
  if (v) {
326
- const effectsToAdd = effects.value
327
- .filter((effect: Effect) => !isEffectInOtherGroups(effect.id, selectedEffectIndex.value))
349
+ const effectsToAdd = filteredProcessedEffects.value
350
+ .filter((effect: Effect) => !effect.isInOtherGroups)
328
351
  .map((effect: Effect) => effect.id)
329
352
  const currentEffectsInGroup = selectedEffectGroup.value.effectIds || []
330
353
  selectedEffectGroup.value.effectIds = [...new Set([...currentEffectsInGroup, ...effectsToAdd])]
@@ -353,6 +376,7 @@ function selectEffect(effect: { id: string; isInOtherGroups: boolean }, isSelect
353
376
  }
354
377
 
355
378
  function toggleSideSheet(index: number) {
379
+ sideSheetSearch.value = ''
356
380
  selectedEffectGroup.value = effectGroups.value[index] ? { ...effectGroups.value[index] } : null
357
381
  selectedEffectIndex.value = index
358
382
  sideSheet.value = true
@@ -390,7 +414,6 @@ async function _updateDiscountRule(effectGroups: FdoEffectGroup[]) {
390
414
  lastUpdatedAt: lastUpdatedAt.value || ''
391
415
  })
392
416
  applyDiscountRuleSettings(discountRule)
393
- await initSetting()
394
417
  })
395
418
  }
396
419