@feedmepos/mf-order-setting 0.0.47 → 0.0.49

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 (85) hide show
  1. package/dist/{KioskDevicesView-Dd3xcM5X.js → KioskDevicesView-Ch_mWJz9.js} +1 -1
  2. package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-D-epeOIx.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-DV2HYd8u.js} +19 -19
  3. package/dist/KioskSettingView-CaBhf48e.js +553 -0
  4. package/dist/{KioskView-BGiHHSjd.js → KioskView-BGm-emCw.js} +12 -8
  5. package/dist/OrderSettingsView-CRgoLOD2.js +51603 -0
  6. package/dist/app-CDTAjXj9.js +2930 -0
  7. package/dist/app.js +1 -1
  8. package/dist/{dayjs.min-D-vfvSns.js → dayjs.min-dI_j30pv.js} +49 -49
  9. package/dist/frontend/mf-order/src/api/restaurant-setting/index.d.ts +2 -1
  10. package/dist/frontend/mf-order/src/app.d.ts +1785 -0
  11. package/dist/frontend/mf-order/src/composables/useDeprecationNotice.d.ts +7 -0
  12. package/dist/frontend/mf-order/src/main.d.ts +1785 -0
  13. package/dist/frontend/mf-order/src/stores/menu/menu.d.ts +61 -0
  14. package/dist/frontend/mf-order/src/stores/order-setting/index.d.ts +18 -12
  15. package/dist/frontend/mf-order/src/stores/restaurant/index.d.ts +23 -8
  16. package/dist/frontend/mf-order/src/views/all-orders/ReflowOrder.vue.d.ts +12 -4
  17. package/dist/frontend/mf-order/src/views/kiosk/settings/KioskPaymentTypeSection.vue.d.ts +12 -8
  18. package/dist/frontend/mf-order/src/views/order-settings/delivery/components/FeedmeExpressDeprecationNotice.vue.d.ts +2 -0
  19. package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/ExternalSetting.vue.d.ts +8 -0
  20. package/dist/frontend/mf-order/src/views/order-settings/drive-thru/DriveThruSetting.vue.d.ts +2 -0
  21. package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
  22. package/dist/{index-DAruvcri.js → index-B8U5Sawr.js} +2 -2
  23. package/dist/menu.dto-qVeqpSdz.js +101810 -0
  24. package/dist/package/entity/booking/booking.do.d.ts +170 -40
  25. package/dist/package/entity/delivery/delivery.dto.d.ts +34 -8
  26. package/dist/package/entity/food-court/order.dto.d.ts +2890 -2890
  27. package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +222 -222
  28. package/dist/package/entity/incoming-order/incoming-order.do.d.ts +1053 -771
  29. package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +344 -344
  30. package/dist/package/entity/index.d.ts +1 -0
  31. package/dist/package/entity/kiosk/marketing/marketing.dto.d.ts +1302 -109
  32. package/dist/package/entity/order/effects/effect.dto.d.ts +10 -10
  33. package/dist/package/entity/order/order-item/order-item.dto.d.ts +118 -110
  34. package/dist/package/entity/order/order.do.d.ts +20 -20
  35. package/dist/package/entity/order/order.dto.d.ts +23756 -40781
  36. package/dist/package/entity/order/payment/payment.dto.d.ts +784 -10508
  37. package/dist/package/entity/order-platform/deliveroo/deliveroo-dto.d.ts +2 -2
  38. package/dist/package/entity/order-platform/deliveroo/deliveroo-order.do.d.ts +26 -26
  39. package/dist/package/entity/order-platform/deliveroo/deliveroo-setting.do.d.ts +2 -2
  40. package/dist/package/entity/order-platform/external/menu/external-master-menu.do.d.ts +158 -158
  41. package/dist/package/entity/order-platform/external/menu/external-menu.do.d.ts +196 -196
  42. package/dist/package/entity/order-platform/external/setting/external-setting.do.d.ts +6 -0
  43. package/dist/package/entity/order-platform/external/setting/external-setting.dto.d.ts +6 -0
  44. package/dist/package/entity/order-platform/foodpanda/foodpanda-order.dto.d.ts +34 -8
  45. package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.do.d.ts +4 -4
  46. package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.dto.d.ts +5 -5
  47. package/dist/package/entity/order-platform/grabfood/grabfood-order.do.d.ts +34 -8
  48. package/dist/package/entity/order-platform/grabfood/grabfood-settings.do.d.ts +2 -2
  49. package/dist/package/entity/order-platform/grabfood/grabfood.dto.d.ts +6 -6
  50. package/dist/package/entity/order-platform/menu.dto.d.ts +75 -44
  51. package/dist/package/entity/order-platform/shopeefood/shopeefood-order.do.d.ts +34 -8
  52. package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.do.d.ts +2 -2
  53. package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.dto.d.ts +2 -2
  54. package/dist/package/entity/order-setting/kiosk/kiosk.do.d.ts +57 -42
  55. package/dist/package/entity/order-setting/kiosk/kiosk.dto.d.ts +44 -32
  56. package/dist/package/entity/order-setting/order-setting.do.d.ts +31 -22
  57. package/dist/package/entity/order-setting/order-setting.dto.d.ts +62 -44
  58. package/dist/package/entity/payment/payment.dto.d.ts +2 -2
  59. package/dist/package/entity/payment/transaction.d.ts +1937 -0
  60. package/dist/package/entity/queue/queue.do.d.ts +12 -0
  61. package/dist/package/entity/queue/queue.dto.d.ts +2677 -7335
  62. package/dist/package/entity/restaurant/restaurant.dto.d.ts +220 -144
  63. package/dist/package/entity/websocket/websocket.dto.d.ts +68 -48
  64. package/package.json +4 -4
  65. package/src/api/restaurant-setting/index.ts +6 -0
  66. package/src/app.ts +2 -0
  67. package/src/composables/useDeprecationNotice.ts +52 -0
  68. package/src/locales/en-US.json +10 -0
  69. package/src/locales/ja-JP.json +1755 -0
  70. package/src/locales/th-TH.json +10 -0
  71. package/src/locales/zh-CN.json +10 -0
  72. package/src/main.ts +4 -2
  73. package/src/stores/order-setting/mapper.ts +35 -23
  74. package/src/stores/restaurant/index.ts +6 -0
  75. package/src/views/kiosk/settings/KioskPaymentTypeSection.vue +27 -1
  76. package/src/views/order-settings/OrderSettingsView.vue +6 -1
  77. package/src/views/order-settings/delivery/DeliverySetting.vue +46 -2
  78. package/src/views/order-settings/delivery/components/FeedmeExpressDeprecationNotice.vue +16 -0
  79. package/src/views/order-settings/delivery/integrated-delivery/ExternalSetting.vue +22 -1
  80. package/src/views/order-settings/delivery/integrated-delivery/FeedmeDelivery.vue +39 -39
  81. package/src/views/order-settings/drive-thru/DriveThruSetting.vue +101 -0
  82. package/dist/KioskSettingView-D50Gh7NR.js +0 -528
  83. package/dist/OrderSettingsView-DPYYH1zL.js +0 -74512
  84. package/dist/app-CAt1JfN3.js +0 -1145
  85. package/dist/menu.dto-B82ITnH5.js +0 -124296
@@ -97,6 +97,10 @@
97
97
  "deviceDetails": "รายละเอียดอุปกรณ์",
98
98
  "dineIn": "รับประทานอาหารที่ร้าน",
99
99
  "dineInCanTakeaway": "อนุญาตให้นำกลับบ้าน",
100
+ "driveThru": "ไดรฟ์ทรู",
101
+ "driveThruSettingUpdated": "อัปเดตการตั้งค่าไดรฟ์ทรูแล้ว",
102
+ "enableDriveThru": "เปิดใช้งานไดรฟ์ทรู",
103
+ "enableDriveThruSublabel": "เปิดใช้งานการสั่งอาหารไดรฟ์ทรูสำหรับลูกค้า",
100
104
  "dineInType": "ประเภทรับประทานอาหารที่ร้าน",
101
105
  "discountCampaign": "แคมเปญส่วนลด",
102
106
  "displayStand": "แท่นวางสินค้า",
@@ -122,6 +126,11 @@
122
126
  "feedmeExpressPayoutAccIssue": "จำเป็นต้องมีบัญชีการจ่ายเงินเพื่อเปิดใช้งาน FeedMe Express",
123
127
  "feedmeExpressPosVersionIssue": "จำเป็นต้องมีเวอร์ชัน POS ขั้นต่ำ {minVersion} สำหรับ FeedMe Express",
124
128
  "feedmeExpressTitle": "อัปเดต FeedMe express",
129
+ "feedmeExpressDeprecationTitle": "FeedMe Express — ปิดรับสมัคร บริการสิ้นสุด 1 ก.พ. 2026",
130
+ "feedmeExpressDeprecationMessage": "การสมัคร FeedMe Express ปิดรับทันที บริการสำหรับร้านค้าที่มีอยู่จะสิ้นสุดในวันที่ 1 ก.พ. 2026 ติดต่อฝ่ายสนับสนุนเพื่อหาทางเลือกอื่น",
131
+ "feedmeExpressDeprecationThanks": "ขอบคุณสำหรับการสนับสนุนอย่างต่อเนื่อง",
132
+ "feedmeExpressDeprecationConfirm": "ฉันเข้าใจแล้ว",
133
+ "feedmeExpressAdminOnly": "การตั้งค่า FeedMe Express เป็นแบบอ่านอย่างเดียว ติดต่อผู้ดูแลระบบเพื่อทำการเปลี่ยนแปลง",
125
134
  "fieldCannotBeEmpty": "ไม่สามารถเว้นช่องได้",
126
135
  "followDineIn": "ทำตามการรับประทานอาหารที่ร้าน",
127
136
  "fixedTime": "เวลาที่กำหนด",
@@ -222,6 +231,7 @@
222
231
  "qrPay": "ชำระเงินด้วย QR",
223
232
  "terminalScanPay": "ชำระเงินด้วยการสแกนเทอร์มินัล",
224
233
  "terminalQrPay": "ชำระเงินด้วย QR เทอร์มินัล",
234
+ "terminalPaymentDescription": "ชำระเงินโดยใช้เครื่องเทอร์มินัลที่รวมอยู่ในระบบ",
225
235
  "rate": "อัตรา",
226
236
  "rateLimitWarning": "กรุณารอ 1 นาทีแล้วซิงค์อีกครั้ง",
227
237
  "remoteId": "รหัสประจำตัวระยะไกล",
@@ -98,6 +98,10 @@
98
98
  "deviceDetails": "设备详情",
99
99
  "dineIn": "堂食",
100
100
  "dineInCanTakeaway": "允许外带",
101
+ "driveThru": "得来速",
102
+ "driveThruSettingUpdated": "得来速设置已更新。",
103
+ "enableDriveThru": "启用得来速",
104
+ "enableDriveThruSublabel": "为顾客启用得来速点餐",
101
105
  "dineInType": "堂食类型",
102
106
  "discountCampaign": "促销活动",
103
107
  "displayStand": "桌牌",
@@ -126,6 +130,11 @@
126
130
  "feedmeExpressPayoutAccIssue": "需要设置支付账户才能启用FeedMe外卖快递",
127
131
  "feedmeExpressPosVersionIssue": "需要最低{minVersion}版本的POS系统才能使用FeedMe外卖快递",
128
132
  "feedmeExpressTitle": "更新 Feedme 外卖快递",
133
+ "feedmeExpressDeprecationTitle": "FeedMe Express — 注册已关闭,服务将于 2026 年 2 月 1 日结束",
134
+ "feedmeExpressDeprecationMessage": "FeedMe Express 注册即日起关闭。现有商家的服务将于 2026 年 2 月 1 日结束。请联系客服了解其他选择。",
135
+ "feedmeExpressDeprecationThanks": "感谢您一直以来的支持。",
136
+ "feedmeExpressDeprecationConfirm": "我已了解",
137
+ "feedmeExpressAdminOnly": "FeedMe Express 设置为只读。如需更改请联系管理员。",
129
138
  "fieldCannotBeEmpty": "字段不可为空",
130
139
  "followDineIn": "跟随堂食",
131
140
  "fixedTime": "固定时间",
@@ -226,6 +235,7 @@
226
235
  "qrPay": "二维码支付",
227
236
  "terminalScanPay": "终端扫描支付",
228
237
  "terminalQrPay": "终端二维码支付",
238
+ "terminalPaymentDescription": "通过集成的终端设备进行支付。",
229
239
  "rate": "费率",
230
240
  "remoteId": "平台注册ID",
231
241
  "restaurant": "餐厅",
package/src/main.ts CHANGED
@@ -14,11 +14,13 @@ import { createFeedMeI18n, type I18n, detectLocale } from "@feedmepos/mf-common"
14
14
  import enUS from "./locales/en-US.json"
15
15
  import zhCN from "./locales/zh-CN.json"
16
16
  import thTH from "./locales/th-TH.json"
17
+ import jaJP from "./locales/ja-JP.json"
17
18
 
18
19
  export const i18nMessages = {
19
20
  "en-US": enUS,
20
21
  "zh-CN": zhCN,
21
22
  "th-TH": thTH,
23
+ "ja-JP": jaJP,
22
24
  }
23
25
 
24
26
  function initI18n(): I18n {
@@ -36,9 +38,9 @@ app.use(FeedMeUI, {
36
38
  locale: detectLocale(),
37
39
  })
38
40
 
39
- app.use(createPinia())
41
+ app.use(createPinia() as any)
40
42
  app.use(router)
41
- app.use(initI18n())
43
+ app.use(initI18n() as any)
42
44
 
43
45
 
44
46
  const CoreStore = useCoreStore();
@@ -55,13 +55,14 @@ export const defaultKioskOrderSetting: MfKioskOrderSettingForm = {
55
55
  enabled: false,
56
56
  pickUp: defaultPickUp,
57
57
  sequenceNumber: FdoOrderKioskDineInSequence.parse({}),
58
- displayStand: defaultDisplayStand,
58
+ displayStand: defaultDisplayStand
59
59
  },
60
60
  takeaway: defaultTakeaway,
61
61
  paymentSetting: {
62
62
  paymentTypes: [],
63
63
  offlinePaymentTypes: [],
64
64
  ePaymentTypes: {
65
+ terminal: false,
65
66
  card: {
66
67
  terminal: false,
67
68
  nfc: false
@@ -72,10 +73,10 @@ export const defaultKioskOrderSetting: MfKioskOrderSettingForm = {
72
73
  qrPay: false,
73
74
  scanPay: false
74
75
  }
75
- },
76
+ }
76
77
  },
77
78
  menuItem: {
78
- showAllOnly: false,
79
+ showAllOnly: false
79
80
  }
80
81
  }
81
82
 
@@ -90,35 +91,46 @@ const convertOrderSettingDto = (dto: OrderSettingsDto): MfOrderSetting => {
90
91
  }
91
92
  }
92
93
 
93
- const toKiosk = (kioskOrderSettings: OrderKioskSettings | null | undefined, kioskDineInSeq?: OrderKioskDineInSequenceDto): MfKioskOrderSetting => {
94
+ const toKiosk = (
95
+ kioskOrderSettings: OrderKioskSettings | null | undefined,
96
+ kioskDineInSeq?: OrderKioskDineInSequenceDto
97
+ ): MfKioskOrderSetting => {
94
98
  return {
95
- dineIn: toKioskDineInSetting(kioskDineInSeq ?? {
96
- current: 0,
97
- prefix: '#K',
98
- }, kioskOrderSettings?.dineIn ?? undefined),
99
+ dineIn: toKioskDineInSetting(
100
+ kioskDineInSeq ?? {
101
+ current: 0,
102
+ prefix: '#K'
103
+ },
104
+ kioskOrderSettings?.dineIn ?? undefined
105
+ ),
99
106
  takeaway: {
100
107
  enabled: kioskOrderSettings?.canTakeaway ?? false,
101
- submitOrderInstruction: kioskOrderSettings?.takeaway?.submitOrderInstruction ? {
102
- payAtCounter: kioskOrderSettings?.takeaway?.submitOrderInstruction?.payAtCounter?.['en'] ?? null,
103
- paid: kioskOrderSettings?.takeaway?.submitOrderInstruction?.paid?.['en'] ?? null,
104
- } : defaultSubmitOrderInstruction,
108
+ submitOrderInstruction: kioskOrderSettings?.takeaway?.submitOrderInstruction
109
+ ? {
110
+ payAtCounter:
111
+ kioskOrderSettings?.takeaway?.submitOrderInstruction?.payAtCounter?.['en'] ?? null,
112
+ paid: kioskOrderSettings?.takeaway?.submitOrderInstruction?.paid?.['en'] ?? null
113
+ }
114
+ : defaultSubmitOrderInstruction
105
115
  },
106
116
  paymentSetting: {
107
117
  paymentTypes: kioskOrderSettings?.paymentSetting?.paymentTypes ?? [],
108
118
  offlinePaymentTypes: kioskOrderSettings?.paymentSetting?.offlinePaymentTypes ?? [],
109
- ePaymentTypes: kioskOrderSettings?.paymentSetting?.ePaymentTypes ?? FdoEPaymentMethod.parse({
110
- card: {
111
- terminal: false,
112
- nfc: false
113
- },
114
- eWallet: {
115
- qrPay: false,
116
- scanPay: false
117
- }
118
- }),
119
+ ePaymentTypes:
120
+ kioskOrderSettings?.paymentSetting?.ePaymentTypes ??
121
+ FdoEPaymentMethod.parse({
122
+ card: {
123
+ terminal: false,
124
+ nfc: false
125
+ },
126
+ eWallet: {
127
+ qrPay: false,
128
+ scanPay: false
129
+ }
130
+ })
119
131
  },
120
132
  menuItem: {
121
- showAllOnly: kioskOrderSettings?.menuItem?.showAllOnly ?? false,
133
+ showAllOnly: kioskOrderSettings?.menuItem?.showAllOnly ?? false
122
134
  }
123
135
  }
124
136
  }
@@ -4,6 +4,7 @@ import {
4
4
  F_FEATURE,
5
5
  F_PAYOUT_ACCOUNT_STATUS,
6
6
  FdoRestaurantDineIn,
7
+ FdoRestaurantDriveThru,
7
8
  FdoRestaurantFeedmeDelivery,
8
9
  FdoRestaurantInHouseDelivery,
9
10
  FdoRestaurantPickup,
@@ -92,6 +93,10 @@ export const useRestaurantStore = defineStore('restaurant', () => {
92
93
  await restaurantApi.updatePickupSetting(setting)
93
94
  }
94
95
 
96
+ async function updateDriveThruSetting(setting: FdoRestaurantDriveThru) {
97
+ await restaurantApi.updateDriveThruSetting(setting)
98
+ }
99
+
95
100
  async function updateInhouseDelivery(restaurantId: string, dto: FdoRestaurantInHouseDelivery) {
96
101
  await remoteOrderApi.integratedDelivery.updateInhouse(restaurantId, dto)
97
102
  }
@@ -149,6 +154,7 @@ export const useRestaurantStore = defineStore('restaurant', () => {
149
154
  updateServiceCharge,
150
155
  updateDineInSetting,
151
156
  updatePickupSetting,
157
+ updateDriveThruSetting,
152
158
  updateInhouseDelivery,
153
159
  updateFeedmeDelivery,
154
160
  updateIntegratedFoodpandaDelivery,
@@ -56,6 +56,7 @@ const paymentCheckboxVal = ref<string[]>([])
56
56
  const cardPaymentRadioVal = ref<string>()
57
57
  const eWalletPaymentCheckboxVal = ref<string[]>([])
58
58
  const useCard = ref(false)
59
+ const useTerminal = ref(false)
59
60
  const useEwallet = ref(false)
60
61
 
61
62
  const checkboxChildren = [
@@ -70,6 +71,10 @@ const initializeCheckboxes = () => {
70
71
  paymentCheckboxVal.value = initialValues
71
72
  parentCheckbox.value = initialValues.length === checkboxChildren.length
72
73
  if (!(Object.keys(props.ePaymentTypes).length === 0)) {
74
+ if (props.ePaymentTypes.terminal) {
75
+ useTerminal.value = true
76
+ }
77
+
73
78
  if (props.ePaymentTypes.card.terminal) {
74
79
  cardPaymentRadioVal.value = F_ORDER_E_PAYMENT_TYPE.enum.TERMINAL
75
80
  useCard.value = true
@@ -152,6 +157,7 @@ const handleChildUpdate = (ev: string[]) => {
152
157
 
153
158
  const handleEPaymentCardUpdate = (ev: string) => {
154
159
  const ePaymentObj = {
160
+ terminal: false,
155
161
  card: {
156
162
  terminal: false,
157
163
  nfc: false
@@ -190,11 +196,16 @@ const handleEPaymentCardUpdate = (ev: string) => {
190
196
  }
191
197
  }
192
198
 
199
+ if (useTerminal.value) {
200
+ ePaymentObj.terminal = true
201
+ }
202
+
193
203
  emits('update:ePaymentTypes', ePaymentObj)
194
204
  }
195
205
 
196
206
  const handleEPaymentEWalletUpdate = () => {
197
207
  const ePaymentObj = {
208
+ terminal: false,
198
209
  card: {
199
210
  terminal: false,
200
211
  nfc: false
@@ -203,7 +214,7 @@ const handleEPaymentEWalletUpdate = () => {
203
214
  qrPay: false,
204
215
  scanPay: false,
205
216
  terminalScanPay: false,
206
- terminalQrPay: false,
217
+ terminalQrPay: false
207
218
  }
208
219
  } as FdoEPaymentMethod
209
220
 
@@ -218,6 +229,10 @@ const handleEPaymentEWalletUpdate = () => {
218
229
  }
219
230
  }
220
231
 
232
+ if (useTerminal.value) {
233
+ ePaymentObj.terminal = true
234
+ }
235
+
221
236
  if (eWalletPaymentCheckboxVal.value.includes(F_ORDER_E_PAYMENT_TYPE.enum.QRPAY)) {
222
237
  ePaymentObj.eWallet.qrPay = true
223
238
  }
@@ -346,6 +361,17 @@ onMounted(() => {
346
361
  </div>
347
362
  </FmCardSection>
348
363
  </FmCard>
364
+ <FmCard variant="outlined" class="mt-2">
365
+ <FmCardSection>
366
+ <FmSwitch
367
+ :label="t('order.terminal')"
368
+ :sublabel="t('order.terminalPaymentDescription')"
369
+ label-placement="right"
370
+ v-model="useTerminal"
371
+ @update:modelValue="updateCardSwitch"
372
+ />
373
+ </FmCardSection>
374
+ </FmCard>
349
375
  <FmCard variant="outlined" class="mt-2">
350
376
  <FmCardSection>
351
377
  <FmSwitch
@@ -19,6 +19,7 @@ import { type FmTabProps } from '@feedmepos/ui-library'
19
19
  import { ref, computed, onMounted, watch } from 'vue'
20
20
  import DeliverySetting from './delivery/DeliverySetting.vue'
21
21
  import DineInSetting from './dine-in/DineInSetting.vue'
22
+ import DriveThruSetting from './drive-thru/DriveThruSetting.vue'
22
23
  import PickUpSetting from './pickup/PickUpSetting.vue'
23
24
  import SmsSetting from './sms/SmsSetting.vue'
24
25
  // import ServiceChargeSetting from './servicecharge/ServiceChargeSetting.vue'
@@ -38,6 +39,7 @@ type OrderSettingMenuItemValue =
38
39
  | 'delivery'
39
40
  | 'pickup'
40
41
  | 'dinein'
42
+ | 'driveThru'
41
43
  // | 'servicecharge'
42
44
  | 'sms'
43
45
  // | 'discountRule'
@@ -49,6 +51,7 @@ const settingItem = computed<FmTabProps[]>(() => [
49
51
  { label: t('order.delivery'), value: 'delivery' },
50
52
  { label: t('order.pickup'), value: 'pickup' },
51
53
  { label: t('order.dineIn'), value: 'dinein' },
54
+ { label: t('order.driveThru'), value: 'driveThru' },
52
55
  // { label: t('order.serviceCharge'), value: 'servicecharge' },
53
56
  // { label: t('order.discountRule.title'), value: 'discountRule' },
54
57
  { label: t('order.sms'), value: 'sms' },
@@ -62,6 +65,8 @@ const currentComponent = computed(() => {
62
65
  return DeliverySetting
63
66
  case 'dinein':
64
67
  return DineInSetting
68
+ case 'driveThru':
69
+ return DriveThruSetting
65
70
  case 'pickup':
66
71
  return PickUpSetting
67
72
  case 'sms':
@@ -83,7 +88,7 @@ onMounted(async () => {
83
88
  }
84
89
  })
85
90
 
86
- watch(currentRestaurant, async (newRestaurant) => {
91
+ watch(currentRestaurant, async (newRestaurant: any) => {
87
92
  if (newRestaurant?._id) {
88
93
  await menuStore.loadCatalogOptions(newRestaurant._id)
89
94
  }
@@ -165,9 +165,9 @@
165
165
  </template>
166
166
 
167
167
  <script setup lang="ts">
168
- import { computed, h, ref, watch } from 'vue'
168
+ import { computed, h, ref, watch, onMounted } from 'vue'
169
169
  import RestaurantSelector from '../components/RestaurantSelector.vue'
170
- import { type ColumnDef } from '@feedmepos/ui-library'
170
+ import { type ColumnDef, useDialog } from '@feedmepos/ui-library'
171
171
  import type { FdoDeliverooSettings, FdoFoodpandaSettings, FdoExternalSetting } from '@entity'
172
172
  import type {
173
173
  FdoLinkedDelivery,
@@ -197,6 +197,8 @@ import { useSnackbarFunctions } from '@/components/snackbar'
197
197
  import useSearch from '@/composables/search'
198
198
  import DeliveryList from './DeliveryList.vue'
199
199
  import DeliverooSetting from './integrated-delivery/DeliverooSetting.vue'
200
+ import FeedmeExpressDeprecationNotice from './components/FeedmeExpressDeprecationNotice.vue'
201
+ import { useDeprecationNotice } from '@/composables/useDeprecationNotice'
200
202
  import { useI18n, useCoreStore } from '@feedmepos/mf-common'
201
203
 
202
204
  const { t } = useI18n()
@@ -212,6 +214,40 @@ const {
212
214
  currentCountry
213
215
  } = useCoreStore()
214
216
  const menuStore = useMenuStore()
217
+ const Dialog = useDialog()
218
+ const { shouldShowNotice, markNoticeAsShown } = useDeprecationNotice()
219
+
220
+ const FEEDME_EXPRESS_DEPRECATION_NOTICE_ID = 'feedme_express_feb_2025'
221
+
222
+ function showFeedmeExpressDeprecationDialog() {
223
+ const restaurantId = currentRestaurant.value?._id
224
+ if (!restaurantId) return
225
+
226
+ Dialog.open({
227
+ title: t('order.feedmeExpressDeprecationTitle'),
228
+ contentComponent: FeedmeExpressDeprecationNotice,
229
+ dismissAway: false,
230
+ primaryActions: {
231
+ text: t('order.feedmeExpressDeprecationConfirm'),
232
+ variant: 'primary',
233
+ close: true
234
+ }
235
+ })
236
+
237
+ markNoticeAsShown(FEEDME_EXPRESS_DEPRECATION_NOTICE_ID, restaurantId)
238
+ }
239
+
240
+ function checkAndShowDeprecationNotice() {
241
+ const restaurantId = currentRestaurant.value?._id
242
+ const isFeedmeExpressEnabled = currentRestaurant.value?.feedmeDelivery?.enable
243
+
244
+ if (restaurantId && isFeedmeExpressEnabled) {
245
+ if (shouldShowNotice(FEEDME_EXPRESS_DEPRECATION_NOTICE_ID, restaurantId)) {
246
+ showFeedmeExpressDeprecationDialog()
247
+ }
248
+ }
249
+ }
250
+
215
251
  const linkedCompanies = ref<LinkedDeliveryDoc[]>([])
216
252
  const deliveryCompanies = ref<DeliveryCompany[]>([])
217
253
  export interface DeliveryRow {
@@ -977,7 +1013,13 @@ function handleModelValueUpdateExternal(v: any) {
977
1013
  }
978
1014
 
979
1015
  const feedmeValidate = ref<boolean | null>(null)
1016
+ const isAdmin = computed(() => sessionUser.value?.role?.isAdmin ?? false)
1017
+
980
1018
  const canSave = computed(() => {
1019
+ // For FeedMe Express, only admin can save
1020
+ if (feedMeComponentProps.value?.key === F_ORDER_PLATFORM.enum.FEEDME) {
1021
+ return feedmeValidate.value !== false && isAdmin.value
1022
+ }
981
1023
  return !feedMeComponentProps.value?.key || feedmeValidate.value !== false
982
1024
  })
983
1025
 
@@ -1035,6 +1077,8 @@ watch(
1035
1077
  async (newRestaurant) => {
1036
1078
  if (newRestaurant) {
1037
1079
  await readData()
1080
+ // Check if FeedMe Express deprecation notice should be shown
1081
+ checkAndShowDeprecationNotice()
1038
1082
  }
1039
1083
  },
1040
1084
  { immediate: true }
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class="flex flex-col gap-4">
3
+ <p class="fm-typo-en-body-lg-400 text-fm-color-typo-secondary">
4
+ {{ t('order.feedmeExpressDeprecationMessage') }}
5
+ </p>
6
+ <p class="fm-typo-en-body-lg-400 text-fm-color-typo-secondary">
7
+ {{ t('order.feedmeExpressDeprecationThanks') }}
8
+ </p>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { useI18n } from '@feedmepos/mf-common'
14
+
15
+ const { t } = useI18n()
16
+ </script>
@@ -63,8 +63,22 @@
63
63
  />
64
64
  </div>
65
65
 
66
+ <div class="text-fm-color-neutral-gray-400 fm-typo-cn-body-md-400 mb-5 mt-5">
67
+ <div v-if="data.updatedAt">
68
+ {{ t('order.updatedAt') }}:
69
+ {{ Day(data.updatedAt).format('DD/MM/YYYY hh:mm a') }}
70
+ </div>
71
+ </div>
72
+
66
73
  <div class="flex flex-row mt-5">
67
74
  <FmButton variant="primary" :label="t('order.syncMenu')" @click="syncMenu()" />
75
+ <div
76
+ v-if="data.lastSynchronize"
77
+ class="m-2 ml-10 text-fm-color-neutral-gray-400 fm-typo-cn-body-md-400"
78
+ >
79
+ {{ t('order.lastSync') }}:
80
+ {{ Day(data.lastSynchronize).format('DD/MM/YYYY hh:mm a') }}
81
+ </div>
68
82
  </div>
69
83
  </FmCard>
70
84
  </div>
@@ -75,6 +89,7 @@
75
89
  import { type PropType, reactive, ref } from 'vue'
76
90
  import { F_ORDER_PLATFORM, type FdoExternalSetting } from '@entity'
77
91
  import { useI18n } from '@feedmepos/mf-common'
92
+ import Day from 'dayjs'
78
93
  import { clone } from '@/helpers/object'
79
94
  import { useMenuStore } from '@/stores/menu/menu'
80
95
  import { useLoading } from '@/composables/loading'
@@ -147,7 +162,13 @@ function updatePlatform(platform: F_ORDER_PLATFORM) {
147
162
  const { startAsyncCallWithErr } = useLoading()
148
163
  async function syncMenu() {
149
164
  await startAsyncCallWithErr(async () => {
150
- await remoteOrderApi.integratedDelivery.syncExternalMenu(data._id ?? '')
165
+ const res = await remoteOrderApi.integratedDelivery.syncExternalMenu(data._id ?? '')
166
+ if (res?.lastSynchronize) {
167
+ data.lastSynchronize = res.lastSynchronize
168
+ }
169
+ if (res?.updatedAt) {
170
+ data.updatedAt = res.updatedAt
171
+ }
151
172
  showSuccess(t('order.syncMenuSuccess'))
152
173
  })
153
174
  }
@@ -45,7 +45,7 @@ const data = reactive<FdoRestaurantFeedme>(
45
45
  props.initialValue ? clone(props.initialValue) : defaultValue
46
46
  )
47
47
  const { sessionUser } = useCoreStore()
48
- const canActivateFeedmeExpress = computed(() => sessionUser.value?.isInternal)
48
+ const canActivateFeedmeExpress = computed(() => sessionUser.value?.role?.isAdmin ?? false)
49
49
  const { currentRestaurant } = useCoreStore()
50
50
  const validatePosVersion = computed<ValidateFeedmeResult>(() => {
51
51
  const posVersion = currentRestaurant?.value?.posVersion
@@ -64,21 +64,15 @@ const router = useRouter();
64
64
 
65
65
  const validatePayoutAccount = computed<ValidateFeedmeResult>(() => {
66
66
  const account = currentRestaurant.value?.payoutAccount
67
+ // Since FeedMe Express is ending, show deprecation message instead of asking to set up payout
67
68
  if (!account?.enable) {
68
69
  return {
69
- message: `${t('order.feedmeExpressPayoutAccIssue')}`,
70
- action: {
71
- label: t('order.updatePayoutAccount'),
72
- callback: () => {
73
- router.push({ name: "mf-payment-payout-account"})
74
- }
75
- }
70
+ message: `${t('order.feedmeExpressDeprecationTitle')}\n\n${t('order.feedmeExpressDeprecationMessage')}`
76
71
  }
77
72
  }
78
73
  if (account.status !== F_PAYOUT_ACCOUNT_STATUS.enum.APPROVED) {
79
74
  return {
80
- message:
81
- `${t('order.feedmeExpressNotApproved')}`
75
+ message: `${t('order.feedmeExpressDeprecationTitle')}\n\n${t('order.feedmeExpressDeprecationMessage')}`
82
76
  }
83
77
  }
84
78
  return true
@@ -113,11 +107,6 @@ const validation = computed<ValidateFeedmeResult>(() => {
113
107
 
114
108
  emits('validation-result', result === true)
115
109
 
116
- if (!(props.initialValue?.enable || false) && !canActivateFeedmeExpress.value) {
117
- return {
118
- message: 'Contact our staff to enable FeedMe Express'
119
- }
120
- }
121
110
  return (
122
111
  [validatePosVersion.value, validatePayoutAccount.value, validateRestaurantProfile.value].find(
123
112
  (result) => result !== true
@@ -125,6 +114,8 @@ const validation = computed<ValidateFeedmeResult>(() => {
125
114
  )
126
115
  })
127
116
 
117
+ const isReadOnly = computed(() => !canActivateFeedmeExpress.value)
118
+
128
119
  const emits = defineEmits<{
129
120
  (event: 'update:model-value', v: FdoRestaurantFeedme): void
130
121
  (event: 'validation-result', result: boolean): void
@@ -166,27 +157,36 @@ import { formatAddress } from '@/helpers/profile'
166
157
 
167
158
  <template>
168
159
  <template v-if="validation === true">
169
- <FmSwitch :model-value="data.enable" :label="`${t('order.actiavteFeedmeExpress')}`" label-placement="right"
170
- :sublabel="t('order.activateFeedmeExpressSublabel')" @update:model-value="updateEnable" />
171
- <div v-if="data.enable">
172
- <FmCard variant="outlined" class="p-5 mt-10">
173
- <div class="flex-grow fm-typo-en-title-sm-600 mb-3">{{ t('order.generalInfo') }}</div>
174
-
175
- <FmSwitch :model-value="data.ignoreStock || false" value="ignoreStock" :label="t('order.ignoreStock')"
176
- :sublabel="t('order.ignoreStockSublabel')" label-placement="right"
177
- @update:model-value="updateIgnoreStock" />
178
-
179
- <div class="mt-5 mb-3">
180
- <FmSelect :model-value="data.catalogId" :label="t('order.catalog')" :items="menuStore.catalogOptions"
181
- @update:model-value="updateCatalogId" />
182
- </div>
183
- <FmTextarea :model-value="data.term ?? undefined" :label="t('order.term')" @update:model-value="updateTerm" />
184
-
185
- <div class="mt-5 mb-3">
186
- <FmTextarea :model-value="data.instruction ?? undefined" :label="t('order.deliveryInstruction')"
187
- @update:model-value="updateInstruction" />
188
- </div>
189
- </FmCard>
160
+ <!-- Read-only banner for non-admin users -->
161
+ <div v-if="isReadOnly" class="mb-4 p-3 bg-fm-color-system-warning-100 rounded-lg">
162
+ <div class="text-fm-color-typo-warning fm-typo-en-body-md-600">
163
+ {{ t('order.feedmeExpressAdminOnly') }}
164
+ </div>
165
+ </div>
166
+
167
+ <div :class="{ 'opacity-60 pointer-events-none': isReadOnly }">
168
+ <FmSwitch :model-value="data.enable" :label="`${t('order.actiavteFeedmeExpress')}`" label-placement="right"
169
+ :sublabel="t('order.activateFeedmeExpressSublabel')" :disabled="isReadOnly" @update:model-value="updateEnable" />
170
+ <div v-if="data.enable">
171
+ <FmCard variant="outlined" class="p-5 mt-10">
172
+ <div class="flex-grow fm-typo-en-title-sm-600 mb-3">{{ t('order.generalInfo') }}</div>
173
+
174
+ <FmSwitch :model-value="data.ignoreStock || false" value="ignoreStock" :label="t('order.ignoreStock')"
175
+ :sublabel="t('order.ignoreStockSublabel')" label-placement="right"
176
+ :disabled="isReadOnly" @update:model-value="updateIgnoreStock" />
177
+
178
+ <div class="mt-5 mb-3">
179
+ <FmSelect :model-value="data.catalogId" :label="t('order.catalog')" :items="menuStore.catalogOptions"
180
+ :disabled="isReadOnly" @update:model-value="updateCatalogId" />
181
+ </div>
182
+ <FmTextarea :model-value="data.term ?? undefined" :label="t('order.term')" :disabled="isReadOnly" @update:model-value="updateTerm" />
183
+
184
+ <div class="mt-5 mb-3">
185
+ <FmTextarea :model-value="data.instruction ?? undefined" :label="t('order.deliveryInstruction')"
186
+ :disabled="isReadOnly" @update:model-value="updateInstruction" />
187
+ </div>
188
+ </FmCard>
189
+ </div>
190
190
  </div>
191
191
  </template>
192
192
  <div v-else>
@@ -194,9 +194,9 @@ import { formatAddress } from '@/helpers/profile'
194
194
  <img :src="svgPath" alt="" />
195
195
  <div class="flex flex-col">
196
196
  <div class="text-center mb-5">{{ validation.message }}</div>
197
- <FmButton
198
- v-if="validation.action"
199
- variant="primary"
197
+ <FmButton
198
+ v-if="validation.action"
199
+ variant="primary"
200
200
  :label="validation.action.label"
201
201
  @click = "(validation as ValidateFeedmeErrorResult).action!.callback"
202
202
  />