@feedmepos/mf-order-setting 0.0.12 → 0.0.14-alpha

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 (91) hide show
  1. package/dist/KioskSettingView-DNN7VBM4.js +4 -0
  2. package/dist/{app-DnR4r5jW.js → app-CbKAPxxI.js} +42471 -41975
  3. package/dist/app.js +1 -1
  4. package/dist/frontend/mf-order/src/main.d.ts +472 -0
  5. package/dist/frontend/mf-order/src/stores/order-setting/index.d.ts +12 -0
  6. package/dist/frontend/mf-order/src/stores/restaurant/index.d.ts +1 -0
  7. package/dist/frontend/mf-order/src/views/order-settings/delivery/DeliverySetting.vue.d.ts +1 -1
  8. package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/InHouseDelivery.vue.d.ts +0 -8
  9. package/dist/frontend/mf-order/src/views/order-settings/general/GeneralSetting.vue.d.ts +2 -0
  10. package/dist/frontend/mf-order/src/views/order-settings/pickup/PaymentSidesheet.vue.d.ts +2 -16
  11. package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
  12. package/dist/package/entity/booking/booking.do.d.ts +60 -1025
  13. package/dist/package/entity/delivery/delivery.dto.d.ts +39 -208
  14. package/dist/package/entity/delivery/gateway/pandago.dto.d.ts +6 -6
  15. package/dist/package/entity/food-court/order.dto.d.ts +1607 -13450
  16. package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +1413 -291
  17. package/dist/package/entity/incoming-order/incoming-order.do.d.ts +602 -99
  18. package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +1182 -154
  19. package/dist/package/entity/kiosk/marketing/marketing.dto.d.ts +66 -875
  20. package/dist/package/entity/order/delivery/delivery.do.d.ts +12 -0
  21. package/dist/package/entity/order/menu/menu.dto.d.ts +6 -1
  22. package/dist/package/entity/order/order-item/order-item.dto.d.ts +847 -40
  23. package/dist/package/entity/order/order.do.d.ts +9 -3
  24. package/dist/package/entity/order/order.dto.d.ts +2639 -8399
  25. package/dist/package/entity/order-platform/foodpanda/foodpanda-order.dto.d.ts +12 -205
  26. package/dist/package/entity/order-platform/grabfood/grabfood-order.do.d.ts +12 -205
  27. package/dist/package/entity/order-platform/menu.dto.d.ts +48 -48
  28. package/dist/package/entity/order-platform/shopeefood/shopeefood-order.do.d.ts +12 -205
  29. package/dist/package/entity/order-setting/order-setting.do.d.ts +8 -0
  30. package/dist/package/entity/order-setting/order-setting.dto.d.ts +16 -0
  31. package/dist/package/entity/order-setting/v3/v3.do.d.ts +3 -0
  32. package/dist/package/entity/order-setting/v3/v3.dto.d.ts +3 -0
  33. package/dist/package/entity/queue/queue.do.d.ts +50 -50
  34. package/dist/package/entity/restaurant/restaurant.dto.d.ts +10 -0
  35. package/package.json +3 -2
  36. package/src/i18n.d.ts +11 -0
  37. package/src/locales/en-US.json +235 -0
  38. package/src/locales/zh-CN.json +235 -0
  39. package/src/main.ts +23 -1
  40. package/src/stores/restaurant/index.ts +31 -3
  41. package/src/stores/table-settings.ts +0 -5
  42. package/src/views/kiosk/KioskSummary.vue +16 -13
  43. package/src/views/kiosk/KioskView.vue +16 -11
  44. package/src/views/kiosk/devices/KioskDeviceCard.vue +10 -7
  45. package/src/views/kiosk/devices/KioskDevicesView.vue +6 -4
  46. package/src/views/kiosk/devices/KioskOtpDialog.vue +4 -1
  47. package/src/views/kiosk/devices/KioskUnbindConfirm.vue +3 -1
  48. package/src/views/kiosk/settings/KioskDineInSection.vue +4 -1
  49. package/src/views/kiosk/settings/KioskDisplayStandSection.vue +14 -11
  50. package/src/views/kiosk/settings/KioskPickAtCounterSection.vue +4 -1
  51. package/src/views/kiosk/settings/KioskSettingView.vue +8 -5
  52. package/src/views/kiosk/settings/KioskTakeawaySection.vue +4 -1
  53. package/src/views/order-settings/OrderSettingsView.vue +13 -7
  54. package/src/views/order-settings/components/RestaurantSelector.vue +5 -2
  55. package/src/views/order-settings/delivery/DeliverySetting.vue +113 -60
  56. package/src/views/order-settings/delivery/components/ManualIntegratedDeliverySetting.vue +11 -8
  57. package/src/views/order-settings/delivery/components/TaxInput.vue +1 -1
  58. package/src/views/order-settings/delivery/inhouse/CurrencyInput.vue +2 -2
  59. package/src/views/order-settings/delivery/inhouse/DeliveryCustomTime.vue +31 -0
  60. package/src/views/order-settings/delivery/inhouse/DeliveryOrder.vue +12 -9
  61. package/src/views/order-settings/delivery/inhouse/DeliveryTime.vue +9 -6
  62. package/src/views/order-settings/delivery/inhouse/InHouseDelivery.vue +63 -68
  63. package/src/views/order-settings/delivery/inhouse/TimePicker.vue +4 -1
  64. package/src/views/order-settings/delivery/inhouse/ZoneDialog.vue +7 -4
  65. package/src/views/order-settings/delivery/integrated-delivery/FeedmeDelivery.vue +38 -15
  66. package/src/views/order-settings/delivery/integrated-delivery/FoodpandaCampaignDialog.vue +7 -4
  67. package/src/views/order-settings/delivery/integrated-delivery/FoodpandaSetting.vue +7 -4
  68. package/src/views/order-settings/delivery/integrated-delivery/IntegratedDelivery.vue +99 -41
  69. package/src/views/order-settings/dinein/DineInSetting.vue +15 -12
  70. package/src/views/order-settings/dinein/OfflinePaymentTypeDialog.vue +9 -6
  71. package/src/views/order-settings/dinein/OfflinePaymentTypeDialogContent.vue +6 -3
  72. package/src/views/order-settings/dinein/PaymentType.vue +9 -6
  73. package/src/views/order-settings/general/GeneralSetting.vue +103 -0
  74. package/src/views/order-settings/pickup/AddressInput.vue +5 -2
  75. package/src/views/order-settings/pickup/CustomPayment.vue +10 -8
  76. package/src/views/order-settings/pickup/PaymentSidesheet.vue +114 -63
  77. package/src/views/order-settings/pickup/PickUpPointDialog.vue +7 -4
  78. package/src/views/order-settings/pickup/PickUpPointDialogContent.vue +7 -4
  79. package/src/views/order-settings/pickup/PickUpSetting.vue +13 -10
  80. package/src/views/order-settings/pickup/PickUpSettingDialog.vue +13 -8
  81. package/src/views/order-settings/pickup/PickUpSettingDialogContent.vue +37 -37
  82. package/src/views/order-settings/pickup/Preorder.vue +10 -8
  83. package/src/views/order-settings/servicecharge/RateInput.vue +12 -5
  84. package/src/views/order-settings/servicecharge/ServiceChargeRule.vue +44 -24
  85. package/src/views/order-settings/servicecharge/ServiceChargeSetting.vue +82 -29
  86. package/src/views/order-settings/sms/SmsSetting.vue +105 -29
  87. package/tsconfig.app.json +3 -1
  88. package/tsconfig.json +2 -1
  89. package/tsconfig.node.json +3 -1
  90. package/vite.config.ts +2 -1
  91. package/dist/KioskSettingView-YfMgLMyn.js +0 -4
@@ -1,9 +1,13 @@
1
1
  <template>
2
- <FmTextField
3
- :model-value="rate"
4
- label="Rate"
5
- append-icon="percent"
6
- @update:model-value="handleInputChange"
2
+ <FmTextField
3
+ :model-value="rate"
4
+ :label="t('order.rate')"
5
+ append-icon="percent"
6
+ :rules="[
7
+ (val) => (val >= 0 && val <= 100) || 'Invalid rate (0% - 100%)',
8
+ ]"
9
+ type="number"
10
+ @update:model-value="handleInputChange"
7
11
  />
8
12
  </template>
9
13
 
@@ -11,6 +15,9 @@
11
15
  import { Dinero } from '@feedmepos/core'
12
16
  import { type PropType, computed } from 'vue'
13
17
  import { percentToAdjustment, type AdjustmentAmount } from '@/helpers/number'
18
+ import { useI18n } from '@feedmepos/mf-common'
19
+
20
+ const { t } = useI18n()
14
21
 
15
22
  const props = defineProps({
16
23
  modelValue: {
@@ -6,6 +6,9 @@ import RateInput from './RateInput.vue'
6
6
  import type { FdoServiceChargeRule, FdoTable } from '@feedmepos/core/entity'
7
7
  import type { AdjustmentAmount } from '@/helpers/number'
8
8
  import { F_SERVICE_CHARGE_ORDER_TYPE } from '@feedmepos/core/entity'
9
+ import { useI18n } from '@feedmepos/mf-common'
10
+
11
+ const { t } = useI18n()
9
12
 
10
13
  const props = defineProps({
11
14
  modelValue: {
@@ -44,19 +47,19 @@ const emits = defineEmits<{
44
47
  }>()
45
48
 
46
49
  const itemSelected = computed(() => {
47
- if (props.isLoadingMenu) return 'Loading menu'
48
- if (!props.items.length) return 'No available item'
50
+ if (props.isLoadingMenu) return t('order.loadingMenu')
51
+ if (!props.items.length) return t('order.noAvailableItem')
49
52
  const items = props.modelValue.condition.items
50
- if (!items) return 'All'
51
- return `${items.length} Item`
53
+ if (!items) return t('order.all')
54
+ return `${items.length} ${t('order.item')}`
52
55
  })
53
56
 
54
57
  const tableSelected = computed(() => {
55
- if (props.isLoadingTable) return 'Loading table'
56
- if (!props.tables.length) return 'No available table'
58
+ if (props.isLoadingTable) return t('order.loadingTable')
59
+ if (!props.tables.length) return t('order.noAvailableTable')
57
60
  const tables = props.modelValue.condition.tables
58
- if (!tables) return 'All'
59
- return `${tables.length} Table`
61
+ if (!tables) return t('order.all')
62
+ return `${tables.length} ${t('order.table')}`
60
63
  })
61
64
 
62
65
  enum ServiceChargeOrderType {
@@ -67,9 +70,26 @@ enum ServiceChargeOrderType {
67
70
  pickup = 'PICKUP'
68
71
  }
69
72
 
73
+ function convertServiceChargeOrderToI18n(serviceChargeType: ServiceChargeOrderType) {
74
+ switch (serviceChargeType) {
75
+ case ServiceChargeOrderType.dineIn:
76
+ return t('order.dineIn')
77
+ case ServiceChargeOrderType.takeaway:
78
+ return t('order.takeaway')
79
+ case ServiceChargeOrderType.inHouseDelivery:
80
+ return t('order.deliveryTitle', {company: "In house"})
81
+ case ServiceChargeOrderType.deliveryCompany:
82
+ return t('order.deliveryCompany')
83
+ case ServiceChargeOrderType.pickup:
84
+ return t('order.pickup')
85
+ default:
86
+ return
87
+ }
88
+ }
89
+
70
90
  const diningOptions = computed(() => {
71
91
  return Object.values(ServiceChargeOrderType).map((v) => ({
72
- label: sentenceCase(v),
92
+ label: convertServiceChargeOrderToI18n(v),
73
93
  value: v
74
94
  }))
75
95
  })
@@ -311,15 +331,15 @@ function initializeMenuState(items: any[]) {
311
331
  <FmButton append-icon="delete" variant="tertiary" @click="emits('delete')" />
312
332
  </div>
313
333
  <div class="flex items-center justify-between">
314
- <div class="font-semibold mb-3">Select item</div>
334
+ <div class="font-semibold mb-3">{{ t('order.selectItem') }}</div>
315
335
  <FmButton variant="plain" :label="itemSelected" size="lg" @click="toggleSideSheet" />
316
336
  </div>
317
337
 
318
- <FmSideSheet header="Select item" :maxWidth="600" dismiss-away v-model="sideSheetItem">
338
+ <FmSideSheet :header="t('order.selectItem')" :maxWidth="600" dismiss-away v-model="sideSheetItem">
319
339
  <div>
320
340
  <div class="text-fm-color-typo-secondary mt-5 mb-5 flex flex-row">
321
- {{ props.modelValue.condition.items?.length ?? initialValue?.length }} product(s) selected
322
- <FmSearch v-model:model-value="searchValueItem" class="ml-auto" placeholder="Search" />
341
+ {{ props.modelValue.condition.items?.length ?? initialValue?.length }} {{ t('order.productSelected') }}
342
+ <FmSearch v-model:model-value="searchValueItem" class="ml-auto" :placeholder="t('order.search')" />
323
343
  </div>
324
344
 
325
345
  <div v-for="(item, index) in filteredItem" :key="index" class="flex flex-col mb-6">
@@ -366,20 +386,20 @@ function initializeMenuState(items: any[]) {
366
386
  </div>
367
387
  <template #side-sheet-footer>
368
388
  <div class="flex gap-8 items-center justify-start">
369
- <FmButton variant="primary" label="Confirm" size="lg" @click="updateItems" />
370
- <FmButton variant="secondary" label="Cancel" size="lg" @click="sideSheetItem = false" />
389
+ <FmButton variant="primary" :label="t('order.confirm')" size="lg" @click="updateItems" />
390
+ <FmButton variant="secondary" :label="t('order.cancel')" size="lg" @click="sideSheetItem = false" />
371
391
  </div>
372
392
  </template>
373
393
  </FmSideSheet>
374
394
 
375
395
  <div class="flex items-center justify-between">
376
- <div class="font-semibold mb-3">Select table</div>
396
+ <div class="font-semibold mb-3">{{ t('order.selectTable') }}</div>
377
397
  <FmButton variant="plain" :label="tableSelected" size="lg" @click="toggleSideSheetTable" />
378
398
  </div>
379
- <FmSideSheet header="Select table" :maxWidth="600" dismiss-away v-model="sideSheetTable">
399
+ <FmSideSheet :header="t('order.selectTable')" :maxWidth="600" dismiss-away v-model="sideSheetTable">
380
400
  <div class="text-fm-color-typo-secondary mt-5 mb-5 flex flex-row">
381
- {{ props.modelValue.condition.tables?.length ?? props.tables.length }} table(s) selected
382
- <FmSearch v-model:model-value="searchValueTable" class="ml-auto" placeholder="Search" />
401
+ {{ props.modelValue.condition.tables?.length ?? props.tables.length }} {{ t('order.tableSelected') }}
402
+ <FmSearch v-model:model-value="searchValueTable" class="ml-auto" :placeholder="t('order.search')" />
383
403
  </div>
384
404
 
385
405
  <FmCard variant="outlined" class="p-5">
@@ -387,7 +407,7 @@ function initializeMenuState(items: any[]) {
387
407
  <FmCheckbox
388
408
  :value="parentTable"
389
409
  :model-value="parentTable"
390
- label="All"
410
+ :label="t('order.all')"
391
411
  :indeterminate="
392
412
  nestedValTable.length > 0 && nestedValTable.length < checkboxChildrenTable.length
393
413
  "
@@ -426,17 +446,17 @@ function initializeMenuState(items: any[]) {
426
446
  </FmCard>
427
447
  <template #side-sheet-footer>
428
448
  <div class="flex gap-8 items-center justify-start">
429
- <FmButton variant="primary" label="Confirm" size="lg" @click="updateTable" />
430
- <FmButton variant="secondary" label="Cancel" size="lg" @click="sideSheetTable = false" />
449
+ <FmButton variant="primary" :label="t('order.confirm')" size="lg" @click="updateTable" />
450
+ <FmButton variant="secondary" :label="t('order.cancel')" size="lg" @click="sideSheetTable = false" />
431
451
  </div>
432
452
  </template>
433
453
  </FmSideSheet>
434
454
 
435
- <div>Apply for</div>
455
+ <div>{{ t('order.applyFor') }}</div>
436
456
  <div class="flex flex-col">
437
457
  <FmCheckbox
438
458
  v-model="parent"
439
- label="All"
459
+ :label="t('order.all')"
440
460
  value="all"
441
461
  :indeterminate="nestedVal.length > 0 && nestedVal.length < diningOptions.length"
442
462
  @update:model-value="handleParentUpdate"
@@ -5,48 +5,82 @@
5
5
  <div v-if="!isLoading">
6
6
  <div class="p-[1.5rem] flex flex-col gap-5">
7
7
  <FmCard variant="outlined" class="p-5 sm:w-2/3 md:w-2/3 lg:w-1/3 xl:w-1/3">
8
- <div class="flex-grow fm-typo-en-title-sm-600 mb-3">Enable Service Charge</div>
9
- <FmSwitch v-model="data.active" value="first"
10
- sublabel="Make your own rules to omit change based on different conditions such as restaurant, dining option, items, slot, etc."
11
- label="Service charge" label-placement="right" :disabled="!canUseServiceCharge" />
12
- <div v-if="!canUseServiceCharge" class="fm-typo-en-body-md-400 text-fm-color-typo-error ml-14">
13
- * Service Charge required POS version 4.0.0 or higher.
8
+ <div class="flex-grow fm-typo-en-title-sm-600 mb-3">
9
+ {{ t('order.enableServiceCharge') }}
10
+ </div>
11
+ <FmSwitch
12
+ v-model="data.active"
13
+ value="first"
14
+ :sublabel="t('order.serviceChargeSublabel')"
15
+ :label="t('order.serviceCharge')"
16
+ label-placement="right"
17
+ :disabled="!canUseServiceCharge"
18
+ />
19
+ <div
20
+ v-if="!canUseServiceCharge"
21
+ class="fm-typo-en-body-md-400 text-fm-color-typo-error ml-14"
22
+ >
23
+ {{ t('order.serviceChargeRule') }}
14
24
  </div>
15
25
 
16
26
  <div class="flex flex-col gap-5 m-5" v-if="data.active">
17
- <FmRadioGroup :model-value="chargeTime" label="Charge when" @update:model-value="updateChargeWhen">
18
- <FmRadio value="beforeDiscount" label="Before bill discount" />
19
- <FmRadio value="afterDiscount" label="After bill discount" />
27
+ <FmRadioGroup
28
+ :model-value="chargeTime"
29
+ :label="t('order.chargeWhen')"
30
+ @update:model-value="updateChargeWhen"
31
+ >
32
+ <FmRadio value="beforeDiscount" :label="t('order.beforeBillDiscount')" />
33
+ <FmRadio value="afterDiscount" :label="t('order.afterBillDiscount')" />
20
34
  </FmRadioGroup>
21
35
  <RateInput :model-value="data.rate" @update:model-value="handleUpdateRate" />
22
36
 
23
- <FmRadioGroup :model-value="chargeValue" label="Charge" @update:model-value="updateInclusive">
24
- <FmRadio value="exclusive" label="Exclusive" />
25
- <FmRadio value="inclusive" label="Inclusive" />
37
+ <FmRadioGroup
38
+ :model-value="chargeValue"
39
+ :label="t('order.selectServiceChargeType')"
40
+ @update:model-value="updateInclusive"
41
+ >
42
+ <FmRadio value="exclusive" :label="t('order.exclusive')" />
43
+ <FmRadio value="inclusive" :label="t('order.inclusive')" />
26
44
  </FmRadioGroup>
27
45
  </div>
28
46
  </FmCard>
29
47
  </div>
30
48
  <div v-if="data.active">
31
49
  <div class="flex flex-col gap-5 m-5">
32
- <div class="flex-grow fm-typo-en-title-sm-600 mb-3 mt-3">Custom Service Charge</div>
50
+ <div class="flex-grow fm-typo-en-title-sm-600 mb-3 mt-3">
51
+ {{ t('order.customServiceCharge') }}
52
+ </div>
33
53
  <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-5">
34
54
  <div v-for="(rule, index) in data.rules" :key="index" class="h-full">
35
55
  <FmCard variant="outlined">
36
56
  <FmCardSection>
37
- <ServiceChargeRule :model-value="rule" :inclusive="data.inclusive"
38
- :charge-before-discount="isBeforeDiscountBoolean" :items="menuStore.categorizedItems"
39
- :tables="tableSettingStore.tables" :is-loading-menu="isLoadingMenu"
40
- :is-loading-table="isLoadingTables" @delete="deleteRule(index)"
41
- @update:model-value="(v: FdoServiceChargeRule) => updateRule(index, v)" />
57
+ <ServiceChargeRule
58
+ :model-value="rule"
59
+ :inclusive="data.inclusive"
60
+ :charge-before-discount="isBeforeDiscountBoolean"
61
+ :items="menuStore.categorizedItems"
62
+ :tables="tableSettingStore.tables"
63
+ :is-loading-menu="isLoadingMenu"
64
+ :is-loading-table="isLoadingTables"
65
+ @delete="deleteRule(index)"
66
+ @update:model-value="(v: FdoServiceChargeRule) => updateRule(index, v)"
67
+ />
42
68
  </FmCardSection>
43
69
  </FmCard>
44
70
  </div>
45
71
  <div>
46
- <FmCard variant="outlined" class="flex items-center justify-center w-full h-full border-dashed">
72
+ <FmCard
73
+ variant="outlined"
74
+ class="flex items-center justify-center w-full h-full border-dashed"
75
+ >
47
76
  <FmCardSection class="flex items-center justify-center w-full">
48
- <FmButton variant="plain" label="Add service charge" icon="add" @click="createRule"
49
- class="border fm-corner-radius-lg border-fm-color-primary" />
77
+ <FmButton
78
+ variant="plain"
79
+ :label="t('order.addServiceCharge')"
80
+ icon="add"
81
+ @click="createRule"
82
+ class="border fm-corner-radius-lg border-fm-color-primary"
83
+ />
50
84
  </FmCardSection>
51
85
  </FmCard>
52
86
  </div>
@@ -54,7 +88,12 @@
54
88
  </div>
55
89
  </div>
56
90
  <div class="fm-corner-radius-lg flex flex-col gap-5 m-5">
57
- <FmButton variant="primary" label="Save Setting" class="mr-auto" @click="updateServiceChargeSetting" />
91
+ <FmButton
92
+ variant="primary"
93
+ :label="t('order.saveSetting')"
94
+ class="mr-auto"
95
+ @click="updateServiceChargeSetting"
96
+ />
58
97
  </div>
59
98
  </div>
60
99
  <FmCircularProgress size="xxl" v-else />
@@ -78,6 +117,9 @@ import { percentToAdjustment, type AdjustmentAmount } from '@/helpers/number'
78
117
  import { useTableSettingStore } from '@/stores/table-settings'
79
118
  import ServiceChargeRule from './ServiceChargeRule.vue'
80
119
  import { Pos } from '@feedmepos/core'
120
+ import { useI18n } from '@feedmepos/mf-common'
121
+
122
+ const { t } = useI18n()
81
123
 
82
124
  const isLoadingMenu = ref(false)
83
125
  const isBeforeDiscountBoolean = computed(() => {
@@ -142,11 +184,19 @@ function updateInclusive(inclusiveValue: string) {
142
184
  }
143
185
 
144
186
  function createRule() {
145
- data.value.rules.push({
146
- rate: data.value.rate,
147
- inclusive: data.value.inclusive,
148
- condition: {}
149
- })
187
+ data.value.rules = [
188
+ ...data.value.rules,
189
+ {
190
+ rate: data.value.rate,
191
+ inclusive: data.value.inclusive,
192
+ condition: {}
193
+ }
194
+ ]
195
+ // data.value.rules.push({
196
+ // rate: data.value.rate,
197
+ // inclusive: data.value.inclusive,
198
+ // condition: {}
199
+ // })
150
200
  }
151
201
 
152
202
  function updateRule(index: number, rule: FdoServiceChargeRule) {
@@ -154,7 +204,8 @@ function updateRule(index: number, rule: FdoServiceChargeRule) {
154
204
  }
155
205
 
156
206
  function deleteRule(index: number) {
157
- data.value.rules.splice(index, 1)
207
+ data.value.rules = data.value.rules.filter((_, id) => id !== index)
208
+ // data.value.rules.splice(index, 1)
158
209
  }
159
210
 
160
211
  import { useSnackbarFunctions } from '@/components/snackbar'
@@ -167,7 +218,9 @@ async function updateServiceChargeSetting() {
167
218
  await restaurantStore.updateServiceCharge(data.value)
168
219
  showSuccess('Service charge setting updated. ')
169
220
  })
170
- const restaurantSetting = await restaurantStore.readRestaurantSetting(currentRestaurant.value?._id || '')
221
+ const restaurantSetting = await restaurantStore.readRestaurantSetting(
222
+ currentRestaurant.value?._id || ''
223
+ )
171
224
  initialize(restaurantSetting)
172
225
  }
173
226
 
@@ -2,12 +2,23 @@
2
2
  import { ref, watch, onMounted, computed } from 'vue'
3
3
  import { OrderSettingApi, smsApi } from '@/api/order-setting'
4
4
  import { useLoading } from '@/composables/loading'
5
- import { F_ORDER_TYPE, F_SMS_ACTION, type OrderSettingsDto, type OrderSmsSettingDto } from '@entity'
5
+ import {
6
+ F_ORDER_DINE_IN_TYPE,
7
+ F_ORDER_TYPE,
8
+ F_SMS_ACTION,
9
+ F_SMS_KEY,
10
+ type OrderSettingsDto,
11
+ type OrderSmsSettingDto
12
+ } from '@entity'
6
13
  import RestaurantSelector from '../components/RestaurantSelector.vue'
7
14
 
8
15
  import { useCoreStore } from '@feedmepos/mf-common'
9
16
  import { Dinero } from '@feedmepos/core'
10
17
  import { useSnackbarFunctions } from '@/components/snackbar'
18
+ import { useI18n } from '@feedmepos/mf-common'
19
+
20
+ const { t } = useI18n()
21
+ import { SMS } from '@common'
11
22
 
12
23
  const { showSuccess, showError } = useSnackbarFunctions()
13
24
  const { currentRestaurant } = useCoreStore()
@@ -19,8 +30,6 @@ const orderSmsSettings = ref<OrderSmsSettingDto[]>(initOrderSmsSettings())
19
30
  const smsCredit = ref()
20
31
 
21
32
  const editing = ref<number | undefined>(undefined)
22
- const showTextField = ref<boolean[]>(orderSmsSettings.value.map(() => false))
23
- const inputValues = ref<string[]>(orderSmsSettings.value.map((sms) => sms.message.raw))
24
33
 
25
34
  onMounted(() => {
26
35
  init()
@@ -34,6 +43,25 @@ watch(
34
43
  { immediate: true }
35
44
  )
36
45
 
46
+ const editingOptionKeys = computed(() => {
47
+ if (editing.value != undefined) {
48
+ const setting = orderSmsSettings.value[editing.value]
49
+ return SMS.readKeyByType(setting.type).map((e, i) => ({ label: e, value: e }))
50
+ } else return []
51
+ })
52
+
53
+ const messageKeys = computed(() => {
54
+ if (editing.value != undefined) {
55
+ const rawMessage = orderSmsSettings.value[editing.value].message.raw ?? ''
56
+
57
+ return [
58
+ ...new Set(
59
+ (rawMessage.match(/{{(.*?)}}/g) ?? []).map((e) => e.replace(/{/g, '').replace(/}/g, ''))
60
+ )
61
+ ]
62
+ } else return []
63
+ })
64
+
37
65
  async function readOrderSetting(): Promise<OrderSettingsDto> {
38
66
  return await startAsyncCallWithErr(async () => {
39
67
  return await OrderSettingApi.getOrderSetting()
@@ -82,26 +110,30 @@ async function init() {
82
110
 
83
111
  function processEditing(index?: number) {
84
112
  editing.value = index
85
- if (index !== undefined) {
86
- inputValues.value[index] = orderSmsSettings.value[index].message.raw
87
- }
88
113
  }
89
114
 
90
- function confirmTextField(index: number) {
115
+ async function confirmTextField(index: number) {
91
116
  if (index !== undefined) {
92
- orderSmsSettings.value[index].message.raw = inputValues.value[index]
93
- updateOrderSetting()
94
- showTextField.value[index] = false
117
+ await updateOrderSetting()
95
118
  }
96
119
  }
97
120
 
98
- function toggleTextField(index: number) {
99
- showTextField.value[index] = !showTextField.value[index]
100
- if (showTextField.value[index]) {
101
- inputValues.value[index] = orderSmsSettings.value[index].message.raw
102
- } else {
103
- confirmTextField(index)
104
- }
121
+ function updateRawMessage(rawMessage: string, index: number) {
122
+ const settings = [...orderSmsSettings.value]
123
+ settings[index].message.raw = rawMessage
124
+
125
+ orderSmsSettings.value = settings
126
+ }
127
+
128
+ function updateMessageKey(messageKey: string, option: string, index: number) {
129
+ const settings = [...orderSmsSettings.value]
130
+ settings[index].message.keys[messageKey] = F_SMS_KEY.parse(option)
131
+
132
+ orderSmsSettings.value = settings
133
+ }
134
+
135
+ function isEditing(index: number) {
136
+ return editing.value === index
105
137
  }
106
138
 
107
139
  function initOrderSmsSettings() {
@@ -120,6 +152,26 @@ function initOrderSmsSettings() {
120
152
  }
121
153
  ]
122
154
  }
155
+
156
+ function convertTypeI18n(type: F_ORDER_TYPE | F_ORDER_DINE_IN_TYPE) {
157
+ switch (type) {
158
+ case F_ORDER_TYPE.enum.PICKUP:
159
+ return t('order.pickup')
160
+ default:
161
+ return ''
162
+ }
163
+ }
164
+
165
+ function convertActionI18n(action: F_SMS_ACTION) {
166
+ switch (action) {
167
+ case F_SMS_ACTION.Enum.ACCEPT:
168
+ return t('order.accept')
169
+ case F_SMS_ACTION.Enum.SERVE:
170
+ return t('order.serve')
171
+ default:
172
+ throw new Error('convertActionI18n - Invalid action')
173
+ }
174
+ }
123
175
  </script>
124
176
 
125
177
  <template>
@@ -130,33 +182,57 @@ function initOrderSmsSettings() {
130
182
  <div v-else>
131
183
  <FmCard variant="outlined" class="p-5 m-5 w-2/3">
132
184
  <div class="flex flex-col gap-">
133
- <div class="flex-grow fm-typo-en-title-sm-600 mb-5">Credit</div>
185
+ <div class="flex-grow fm-typo-en-title-sm-600 mb-5">{{ t('order.credit') }}</div>
134
186
 
135
- <span class="text-fm-color-neutral-gray-400">Balance</span>
187
+ <span class="text-fm-color-neutral-gray-400">{{ t('order.balance') }}</span>
136
188
  <span class="font-bold">{{ Dinero.fromFdoDinero(smsCredit?.balance).toFormat(true) }}</span>
137
189
 
138
- <span class="text-fm-color-neutral-gray-400">Price per message</span>
190
+ <span class="text-fm-color-neutral-gray-400">{{ t('order.pricePerMessage') }}</span>
139
191
  <span class="font-bold">{{
140
192
  Dinero.fromFdoDinero(smsCredit?.pricePerMessage).toFormat(true)
141
- }}</span>
193
+ }}</span>
142
194
  </div>
143
195
  </FmCard>
144
196
 
145
197
  <FmCard variant="outlined" class="p-5 m-5 w-2/3">
146
198
  <div class="flex flex-col gap-5">
147
- <div class="flex-grow fm-typo-en-title-sm-600">Setting</div>
199
+ <div class="flex-grow fm-typo-en-title-sm-600">{{ t('order.setting') }}</div>
148
200
  <div v-for="(sms, i) in orderSmsSettings" :key="i">
149
- <FmSwitch :model-value="sms.enable" @update:model-value="(v: boolean) => toggleEnable(v, sms)"
150
- :label="`${sms.type} - ${sms.action}`" :sublabel="sms.message.raw" label-placement="right" />
201
+ <FmSwitch
202
+ :model-value="sms.enable"
203
+ @update:model-value="(v: boolean) => toggleEnable(v, sms)"
204
+ :label="`${convertTypeI18n(sms.type).toUpperCase()} - ${convertActionI18n(sms.action).toUpperCase()}`"
205
+ :sublabel="sms.message.raw"
206
+ label-placement="right"
207
+ />
151
208
  <div class="mb-12"></div>
152
209
 
153
- <div v-if="showTextField[i]">
154
- <FmTextField v-model="inputValues[i]" />
210
+ <div v-if="isEditing(i)">
211
+ <FmTextField
212
+ :model-value="orderSmsSettings[i].message.raw"
213
+ @update:model-value="(message: string) => updateRawMessage(message, i)"
214
+ />
155
215
  <div class="mb-12"></div>
216
+ <div v-for="(messageKey, index) of messageKeys" :key="index" class="row q-py-xs">
217
+ <div class="my-2 col self-center flex flex-row justify-between">
218
+ <div class="col self-center">{{ index + 1 }}. {{ messageKey }}</div>
219
+ <FmSelect
220
+ class="w-1/2"
221
+ :items="editingOptionKeys"
222
+ :model-value="orderSmsSettings[i].message.keys[messageKey]"
223
+ @update:model-value="(value: string) => updateMessageKey(messageKey, value, i)"
224
+ />
225
+ </div>
226
+ </div>
156
227
  </div>
157
- <FmButton variant="secondary" text-color="primary" border-color="primary"
158
- :label="showTextField[i] ? 'Confirm' : 'Edit'" :icon="showTextField[i] ? '' : 'edit'"
159
- @click="showTextField[i] ? confirmTextField(i) : toggleTextField(i)" />
228
+ <FmButton
229
+ variant="secondary"
230
+ text-color="primary"
231
+ border-color="primary"
232
+ :label="isEditing(i) ? t('order.confirm') : t('order.edit')"
233
+ :icon="isEditing(i) ? '' : 'edit'"
234
+ @click="isEditing(i) ? confirmTextField(i) : processEditing(i)"
235
+ />
160
236
  <div class="mb-12"></div>
161
237
  </div>
162
238
  </div>
package/tsconfig.app.json CHANGED
@@ -5,12 +5,14 @@
5
5
  "src/**/*",
6
6
  "src/**/*.vue",
7
7
  "../../package/entity/**/*",
8
- "../../common/**/*"
8
+ "../../common/**/*",
9
+ "src/**/*.json"
9
10
  ],
10
11
  "exclude": ["src/**/__tests__/*"],
11
12
  "compilerOptions": {
12
13
  "rootDir": "./../..",
13
14
  "composite": true,
15
+ "resolveJsonModule": true,
14
16
  "baseUrl": ".",
15
17
  "isolatedModules": true,
16
18
  "types": ["googlemaps"],
package/tsconfig.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "src/*",
14
14
  "../../package/entity/*",
15
15
  "../../package/entity/index.ts",
16
- "../../common/*"
16
+ "../../common/*",
17
+ "src/**/*.json"
17
18
  ]
18
19
  }
@@ -5,10 +5,12 @@
5
5
  "vitest.config.*",
6
6
  "cypress.config.*",
7
7
  "nightwatch.conf.*",
8
- "playwright.config.*"
8
+ "playwright.config.*",
9
+ "src/**/*.json"
9
10
  ],
10
11
  "compilerOptions": {
11
12
  "composite": true,
13
+ "resolveJsonModule": true,
12
14
  "module": "ESNext",
13
15
  "moduleResolution": "Bundler",
14
16
  "types": ["node"]
package/vite.config.ts CHANGED
@@ -12,7 +12,8 @@ export default defineConfig((env) => {
12
12
  preserveSymlinks: true,
13
13
  alias: {
14
14
  '@': fileURLToPath(new URL('./src', import.meta.url)),
15
- '@entity': fileURLToPath(new URL('./../../package/entity', import.meta.url))
15
+ '@entity': fileURLToPath(new URL('./../../package/entity', import.meta.url)),
16
+ '@common': fileURLToPath(new URL('./../../common', import.meta.url))
16
17
  }
17
18
  },
18
19
  define: {
@@ -1,4 +0,0 @@
1
- import { _ as f } from "./app-DnR4r5jW.js";
2
- export {
3
- f as default
4
- };