@feedmepos/mf-order-setting 0.0.52 → 0.0.53
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.
- package/.env.dev +1 -1
- package/.env.prod +1 -1
- package/dist/{KioskDevicesView-D_YT-CL0.js → KioskDevicesView-CMKNjgWx.js} +1 -1
- package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-Bxv6oiFw.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-B1sNvlUC.js} +2 -2
- package/dist/KioskSettingView-BE_pMA-i.js +720 -0
- package/dist/KioskView-U-Wg8oMC.js +480 -0
- package/dist/OrderSettingsView-BWzaITT6.js +51916 -0
- package/dist/app-CFfgPAd8.js +10445 -0
- package/dist/app.js +3 -3
- package/dist/dayjs.min-CuRr-wlf.js +283 -0
- package/dist/frontend/mf-order/src/app.d.ts +60 -8
- package/dist/frontend/mf-order/src/main.d.ts +60 -8
- package/dist/frontend/mf-order/src/modules/order-setting/kiosk/interface.d.ts +4 -2
- package/dist/frontend/mf-order/src/stores/order-setting/index.d.ts +15 -6
- package/dist/frontend/mf-order/src/stores/restaurant/index.d.ts +3 -3
- package/dist/frontend/mf-order/src/utils/firebase-app.d.ts +4 -0
- package/dist/frontend/mf-order/src/utils/firebase-storage.d.ts +2 -0
- package/dist/frontend/mf-order/src/views/all-orders/ReflowOrder.vue.d.ts +2 -2
- package/dist/frontend/mf-order/src/views/order-settings/delivery/inhouse/InHouseDelivery.vue.d.ts +2 -2
- package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
- package/dist/{index-Bjwv8B4h.js → index-Bj0bCGTm.js} +25 -26
- package/dist/menu.dto-DAh1J2ES.js +128627 -0
- package/dist/package/entity/booking/booking.do.d.ts +30 -30
- package/dist/package/entity/delivery/delivery.dto.d.ts +6 -6
- package/dist/package/entity/food-court/order.do.d.ts +24 -4
- package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +12553 -162
- package/dist/package/entity/incoming-order/incoming-order.do.d.ts +43 -22268
- package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +14805 -66
- package/dist/package/entity/incoming-order/incoming-order.enum.d.ts +1 -1
- package/dist/package/entity/index.d.ts +3 -0
- package/dist/package/entity/kiosk/marketing/marketing.dto.d.ts +1 -19864
- package/dist/package/entity/order/order-item/order-item.dto.d.ts +1 -3721
- package/dist/package/entity/order/order.dto.d.ts +342 -7293
- package/dist/package/entity/order/payment/payment.dto.d.ts +3 -344
- package/dist/package/entity/order-platform/foodpanda/foodpanda-order.dto.d.ts +6 -6
- package/dist/package/entity/order-platform/grabfood/grabfood-edit-order.do.d.ts +144 -0
- package/dist/package/entity/order-platform/grabfood/grabfood-omni.do.d.ts +282 -47
- package/dist/package/entity/order-platform/grabfood/grabfood-order.do.d.ts +6 -6
- package/dist/package/entity/order-platform/grabfood/grabfood-webhook.dto.d.ts +69 -14
- package/dist/package/entity/order-platform/grabfood/grabfood.enum.d.ts +2 -0
- package/dist/package/entity/order-platform/order-platform.dto.d.ts +7306 -3
- package/dist/package/entity/order-platform/shopeefood/shopeefood-order.do.d.ts +6 -6
- package/dist/package/entity/order-setting/dine-in/dine-in.do.d.ts +12 -0
- package/dist/package/entity/order-setting/dine-in/dine-in.dto.d.ts +12 -0
- package/dist/package/entity/order-setting/kiosk/kiosk.do.d.ts +6 -3
- package/dist/package/entity/order-setting/kiosk/kiosk.dto.d.ts +6 -3
- package/dist/package/entity/order-setting/order-setting.do.d.ts +13 -8
- package/dist/package/entity/order-setting/order-setting.dto.d.ts +30 -10
- package/dist/package/entity/queue/queue.do.d.ts +1 -11
- package/dist/package/entity/restaurant/restaurant.dto.d.ts +14 -9
- package/dist/package/entity/websocket/websocket.dto.d.ts +24 -12
- package/package.json +4 -2
- package/src/App.vue +3 -0
- package/src/locales/en-US.json +15 -2
- package/src/locales/ja-JP.json +31 -18
- package/src/locales/th-TH.json +15 -2
- package/src/locales/zh-CN.json +15 -2
- package/src/main.ts +10 -20
- package/src/modules/order-setting/kiosk/interface.ts +4 -2
- package/src/stores/order-setting/mapper.ts +63 -60
- package/src/utils/firebase-app.ts +34 -0
- package/src/utils/firebase-storage.ts +112 -0
- package/src/views/kiosk/settings/KioskPaymentTypeSection.vue +1 -19
- package/src/views/kiosk/settings/KioskSettingView.vue +136 -43
- package/src/views/order-settings/OrderSettingsView.vue +1 -1
- package/src/views/order-settings/dine-in/DineInSetting.vue +23 -1
- package/src/views/order-settings/drive-thru/DriveThruSetting.vue +19 -18
- package/src/views/order-settings/servicecharge/ServiceChargeRule.vue +5 -1
- package/dist/KioskSettingView-DS5vEQ07.js +0 -573
- package/dist/KioskView-B8NHcyGz.js +0 -477
- package/dist/OrderSettingsView-BhEN-2ZZ.js +0 -51602
- package/dist/app-BWFBpJUR.js +0 -2986
- package/dist/dayjs.min-CD9R3x-Y.js +0 -2092
- package/dist/menu.dto-Wzm4Tz0i.js +0 -101874
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feedmepos/mf-order-setting",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.53",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"module": "./dist/app.js",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"build:mf": "vite build --mode fmmf",
|
|
18
18
|
"build:dts": "NODE_OPTIONS=--max-old-space-size=16384 vue-tsc --declaration --emitDeclarationOnly -p tsconfig.app.json --outDir ./dist",
|
|
19
19
|
"publish-npm": "yarn build && yarn npm publish --no-git-checks",
|
|
20
|
-
"build-only": "
|
|
20
|
+
"build-only": "yarn build-only:dev",
|
|
21
|
+
"build-only:dev": "dotenv -e .env.dev -- yarn build:mf && yarn build:dts",
|
|
22
|
+
"build-only:prod": "dotenv -e .env.prod -- yarn build:mf && yarn build:dts",
|
|
21
23
|
"build:dev": "cross-env NODE_ENV=dev vite build --mode dev",
|
|
22
24
|
"build:prod": "vite build --mode prod",
|
|
23
25
|
"type-check": "set NODE_OPTIONS=--max-old-space-size=16384 && vue-tsc --noEmit -p tsconfig.app.json --composite false",
|
package/src/App.vue
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import { onMounted } from "vue"
|
|
3
3
|
import { googleMap, setGoogleMap } from "./helpers/map"
|
|
4
4
|
import { Loader } from 'google-maps'
|
|
5
|
+
import { ensureFirebaseApp } from '@/utils/firebase-app'
|
|
6
|
+
|
|
7
|
+
ensureFirebaseApp()
|
|
5
8
|
|
|
6
9
|
async function initGoogleMap() {
|
|
7
10
|
if (googleMap()) return
|
package/src/locales/en-US.json
CHANGED
|
@@ -95,8 +95,6 @@
|
|
|
95
95
|
"deliveryZone": "Delivery Zone",
|
|
96
96
|
"deviceBinding": "Device Binding",
|
|
97
97
|
"deviceDetails": "Device Details",
|
|
98
|
-
"otaChannel": "OTA channel",
|
|
99
|
-
"otaChannelHint": "Optional. Leave blank to use the default OTA feed.",
|
|
100
98
|
"dineIn": "Dine In",
|
|
101
99
|
"dineInCanTakeaway": "Allow Takeaway",
|
|
102
100
|
"driveThru": "Drive Thru",
|
|
@@ -168,6 +166,19 @@
|
|
|
168
166
|
"kioskSettingFailed": "Failed to update kiosk order setting",
|
|
169
167
|
"kioskSettingSuccess": "Kiosk order setting updated",
|
|
170
168
|
"kioskSummary": "Kiosk Summary",
|
|
169
|
+
"coverImage": "Cover Image",
|
|
170
|
+
"coverImageLandscape": "Cover Image (Landscape)",
|
|
171
|
+
"coverImagePortrait": "Cover Image (Portrait)",
|
|
172
|
+
"coverImageLandscapeHint": "Recommended size: 1920 x 1080",
|
|
173
|
+
"coverImagePortraitHint": "Recommended size: 1080 x 1920",
|
|
174
|
+
"coverImageFallbackHint": "If not set, it will default to the Cover Image from restaurant settings.",
|
|
175
|
+
"uploadImage": "Upload Image",
|
|
176
|
+
"imageUrl": "Image URL",
|
|
177
|
+
"imageUrlPlaceholder": "Enter image URL",
|
|
178
|
+
"clearImage": "Clear Image",
|
|
179
|
+
"imageUploadSuccess": "Image uploaded",
|
|
180
|
+
"imageUploadFailed": "Failed to upload image",
|
|
181
|
+
"imageUploadRejected": "Image upload rejected",
|
|
171
182
|
"lastOrderBeforeClosing": "Last order before closing",
|
|
172
183
|
"lastOrderBeforeClosingDescription": "Orders must be placed before the designated closing time",
|
|
173
184
|
"lastOrderMinutesBeforeCloseRule": "Cannot be less than 0 minutes",
|
|
@@ -228,6 +239,8 @@
|
|
|
228
239
|
"disableRemoteQueue": "Disable Remote Queue",
|
|
229
240
|
"disableSMS": "Disable SMS",
|
|
230
241
|
"printChecklist": "Print Checklist",
|
|
242
|
+
"overridePax": "Overwrite Bill Pax",
|
|
243
|
+
"overridePaxSublabel": "Incoming order will overwrite the existing bill pax",
|
|
231
244
|
"codeSettings": "Queue Code Settings",
|
|
232
245
|
"addCodeSetting": "Add Queue Code Setting",
|
|
233
246
|
"current": "Current",
|
package/src/locales/ja-JP.json
CHANGED
|
@@ -91,17 +91,15 @@
|
|
|
91
91
|
"deliveryOrder": "配達注文",
|
|
92
92
|
"deliveryTerm": "配達条件",
|
|
93
93
|
"deliveryTime": "配達時間",
|
|
94
|
-
"deliveryTitle": "{company}配達",
|
|
95
|
-
"deliveryZone": "配達エリア",
|
|
96
|
-
"deviceBinding": "デバイス紐付け",
|
|
97
|
-
"deviceDetails": "デバイス詳細",
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"driveThruSettingUpdated": "ドライブスルー設定が更新されました。",
|
|
104
|
-
"enableDriveThru": "ドライブスルーを有効にする",
|
|
94
|
+
"deliveryTitle": "{company}配達",
|
|
95
|
+
"deliveryZone": "配達エリア",
|
|
96
|
+
"deviceBinding": "デバイス紐付け",
|
|
97
|
+
"deviceDetails": "デバイス詳細",
|
|
98
|
+
"dineIn": "店内飲食",
|
|
99
|
+
"dineInCanTakeaway": "テイクアウト許可",
|
|
100
|
+
"driveThru": "ドライブスルー",
|
|
101
|
+
"driveThruSettingUpdated": "ドライブスルー設定が更新されました。",
|
|
102
|
+
"enableDriveThru": "ドライブスルーを有効にする",
|
|
105
103
|
"enableDriveThruSublabel": "お客様向けのドライブスルー注文を有効にする",
|
|
106
104
|
"dineInType": "店内飲食タイプ",
|
|
107
105
|
"discountCampaign": "割引キャンペーン",
|
|
@@ -159,11 +157,24 @@
|
|
|
159
157
|
"item": "商品",
|
|
160
158
|
"kiosk": "キオスク",
|
|
161
159
|
"kioskDisplay": "キオスクディスプレイ",
|
|
162
|
-
"kioskDisplayDescription": "「デバイスを紐付け」をクリックしてデバイス紐付け用の特別コードを取得してください。",
|
|
163
|
-
"kioskSettingFailed": "キオスク注文設定の更新に失敗しました",
|
|
164
|
-
"kioskSettingSuccess": "キオスク注文設定が更新されました",
|
|
165
|
-
"kioskSummary": "キオスクサマリー",
|
|
166
|
-
"
|
|
160
|
+
"kioskDisplayDescription": "「デバイスを紐付け」をクリックしてデバイス紐付け用の特別コードを取得してください。",
|
|
161
|
+
"kioskSettingFailed": "キオスク注文設定の更新に失敗しました",
|
|
162
|
+
"kioskSettingSuccess": "キオスク注文設定が更新されました",
|
|
163
|
+
"kioskSummary": "キオスクサマリー",
|
|
164
|
+
"coverImage": "カバー画像",
|
|
165
|
+
"coverImageLandscape": "カバー画像(横向き)",
|
|
166
|
+
"coverImagePortrait": "カバー画像(縦向き)",
|
|
167
|
+
"coverImageLandscapeHint": "推奨サイズ: 1920 x 1080",
|
|
168
|
+
"coverImagePortraitHint": "推奨サイズ: 1080 x 1920",
|
|
169
|
+
"coverImageFallbackHint": "未設定の場合、レストラン設定のカバー画像が使用されます",
|
|
170
|
+
"uploadImage": "画像をアップロード",
|
|
171
|
+
"imageUrl": "画像URL",
|
|
172
|
+
"imageUrlPlaceholder": "画像URLを入力",
|
|
173
|
+
"clearImage": "画像をクリア",
|
|
174
|
+
"imageUploadSuccess": "画像をアップロードしました",
|
|
175
|
+
"imageUploadFailed": "画像のアップロードに失敗しました",
|
|
176
|
+
"imageUploadRejected": "画像アップロードが拒否されました",
|
|
177
|
+
"lastOrderBeforeClosing": "閉店前の最終注文",
|
|
167
178
|
"lastOrderBeforeClosingDescription": "指定された閉店時間前に注文を行う必要があります",
|
|
168
179
|
"lastOrderMinutesBeforeCloseRule": "0分未満にはできません",
|
|
169
180
|
"lastSync": "最終同期",
|
|
@@ -222,8 +233,10 @@
|
|
|
222
233
|
"duration": "時間",
|
|
223
234
|
"disableRemoteQueue": "リモート順番待ちを無効にする",
|
|
224
235
|
"disableSMS": "SMSを無効にする",
|
|
225
|
-
"printChecklist": "チェックリストを印刷",
|
|
226
|
-
"
|
|
236
|
+
"printChecklist": "チェックリストを印刷",
|
|
237
|
+
"overridePax": "請求書の人数を上書き",
|
|
238
|
+
"overridePaxSublabel": "新しい注文が既存の請求書の人数を上書きします",
|
|
239
|
+
"codeSettings": "順番待ちコード設定",
|
|
227
240
|
"addCodeSetting": "順番待ちコード設定を追加",
|
|
228
241
|
"current": "現在",
|
|
229
242
|
"paxMin": "最小人数",
|
package/src/locales/th-TH.json
CHANGED
|
@@ -95,8 +95,6 @@
|
|
|
95
95
|
"deliveryZone": "โซนการจัดส่ง",
|
|
96
96
|
"deviceBinding": "การผูกอุปกรณ์",
|
|
97
97
|
"deviceDetails": "รายละเอียดอุปกรณ์",
|
|
98
|
-
"otaChannel": "ช่อง OTA",
|
|
99
|
-
"otaChannelHint": "ไม่บังคับ เว้นว่างเพื่อใช้ฟีด OTA เริ่มต้น",
|
|
100
98
|
"dineIn": "รับประทานอาหารที่ร้าน",
|
|
101
99
|
"dineInCanTakeaway": "อนุญาตให้นำกลับบ้าน",
|
|
102
100
|
"driveThru": "ไดรฟ์ทรู",
|
|
@@ -166,6 +164,19 @@
|
|
|
166
164
|
"kioskSettingFailed": "อัปเดตการตั้งค่าคำสั่งซื้อคีออสก์ล้มเหลว",
|
|
167
165
|
"kioskSettingSuccess": "อัปเดตการตั้งค่าคำสั่งซื้อคีออสก์แล้ว",
|
|
168
166
|
"kioskSummary": "สรุปคีออสก์",
|
|
167
|
+
"coverImage": "รูปภาพหน้าปก",
|
|
168
|
+
"coverImageLandscape": "รูปภาพหน้าปก (แนวนอน)",
|
|
169
|
+
"coverImagePortrait": "รูปภาพหน้าปก (แนวตั้ง)",
|
|
170
|
+
"coverImageLandscapeHint": "ขนาดที่แนะนำ: 1920 x 1080",
|
|
171
|
+
"coverImagePortraitHint": "ขนาดที่แนะนำ: 1080 x 1920",
|
|
172
|
+
"coverImageFallbackHint": "หากไม่ตั้งค่า ระบบจะใช้ Cover Image จากการตั้งค่าร้านอาหารโดยอัตโนมัติ",
|
|
173
|
+
"uploadImage": "อัปโหลดรูปภาพ",
|
|
174
|
+
"imageUrl": "ลิงก์รูปภาพ",
|
|
175
|
+
"imageUrlPlaceholder": "กรอกลิงก์รูปภาพ",
|
|
176
|
+
"clearImage": "ล้างรูปภาพ",
|
|
177
|
+
"imageUploadSuccess": "อัปโหลดรูปภาพแล้ว",
|
|
178
|
+
"imageUploadFailed": "อัปโหลดรูปภาพไม่สำเร็จ",
|
|
179
|
+
"imageUploadRejected": "การอัปโหลดรูปภาพถูกปฏิเสธ",
|
|
169
180
|
"lastOrderBeforeClosing": "เวลาสั่งอาหารครั้งสุดท้ายก่อนปิดร้าน",
|
|
170
181
|
"lastOrderBeforeClosingDescription": "ต้องทำรายการสั่งซื้อก่อนเวลาปิดที่กำหนด",
|
|
171
182
|
"lastOrderMinutesBeforeCloseRule": "ไม่สามารถน้อยกว่า 0 นาทีได้",
|
|
@@ -211,6 +222,8 @@
|
|
|
211
222
|
"pleaseSelectRestaurant": "โปรดเลือกร้านอาหาร",
|
|
212
223
|
"prefix": "คำนำหน้า",
|
|
213
224
|
"printChecklist": "พิมพ์รายการตรวจสอบ",
|
|
225
|
+
"overridePax": "เขียนทับจำนวนคนในบิล",
|
|
226
|
+
"overridePaxSublabel": "ออเดอร์ใหม่จะเขียนทับจำนวนคนในบิลที่มีอยู่",
|
|
214
227
|
"preOrder": "สั่งซื้อล่วงหน้า",
|
|
215
228
|
"preOrderHint": "สั่งซื้อในวันที่ {today} ลูกค้าสามารถสั่งซื้อได้ระหว่าง {start} และ {end} สูงสุด 7 วัน",
|
|
216
229
|
"pricePerMessage": "ราคาต่อข้อความ",
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -96,8 +96,6 @@
|
|
|
96
96
|
"deliveryZone": "配送区域",
|
|
97
97
|
"deviceBinding": "设备绑定",
|
|
98
98
|
"deviceDetails": "设备详情",
|
|
99
|
-
"otaChannel": "OTA 渠道",
|
|
100
|
-
"otaChannelHint": "可选。留空将使用默认的 OTA 源。",
|
|
101
99
|
"dineIn": "堂食",
|
|
102
100
|
"dineInCanTakeaway": "允许外带",
|
|
103
101
|
"driveThru": "得来速",
|
|
@@ -170,6 +168,19 @@
|
|
|
170
168
|
"kioskSettingFailed": "自助点餐设备订单设置更新失败",
|
|
171
169
|
"kioskSettingSuccess": "自助点餐设备订单设置更新成功",
|
|
172
170
|
"kioskSummary": "自助点餐设备概览",
|
|
171
|
+
"coverImage": "封面图片",
|
|
172
|
+
"coverImageLandscape": "封面图片(横向)",
|
|
173
|
+
"coverImagePortrait": "封面图片(竖向)",
|
|
174
|
+
"coverImageLandscapeHint": "推荐尺寸:1920 x 1080",
|
|
175
|
+
"coverImagePortraitHint": "推荐尺寸:1080 x 1920",
|
|
176
|
+
"coverImageFallbackHint": "若不设置,将默认使用餐厅设置中的 Cover Image",
|
|
177
|
+
"uploadImage": "上传图片",
|
|
178
|
+
"imageUrl": "图片链接",
|
|
179
|
+
"imageUrlPlaceholder": "请输入图片链接",
|
|
180
|
+
"clearImage": "清除图片",
|
|
181
|
+
"imageUploadSuccess": "图片上传成功",
|
|
182
|
+
"imageUploadFailed": "图片上传失败",
|
|
183
|
+
"imageUploadRejected": "图片上传被拒绝",
|
|
173
184
|
"lastOrderBeforeClosing": "关闭前最后点餐时间",
|
|
174
185
|
"lastOrderBeforeClosingDescription": "订单必须在指定的关闭时间前提交",
|
|
175
186
|
"lastOrderMinutesBeforeCloseRule": "不能少过0分钟",
|
|
@@ -215,6 +226,8 @@
|
|
|
215
226
|
"pleaseSelectRestaurant": "请选择一个餐厅",
|
|
216
227
|
"prefix": "前缀",
|
|
217
228
|
"printChecklist": "打印清单",
|
|
229
|
+
"overridePax": "覆盖账单人数",
|
|
230
|
+
"overridePaxSublabel": "新订单将覆盖现有账单的人数",
|
|
218
231
|
"preOrder": "预订",
|
|
219
232
|
"preOrderHint": "于今日 {today} 下单,客户可以在 {start} 和 {end} 之间预订。最多 7 天。",
|
|
220
233
|
"printReceiptAfterClose": "自动关闭账单后打印收据",
|
package/src/main.ts
CHANGED
|
@@ -7,8 +7,7 @@ import { router } from './router'
|
|
|
7
7
|
import { initialize, useCoreStore } from '@feedmepos/mf-common'
|
|
8
8
|
import { FeedMeUI } from '@feedmepos/ui-library';
|
|
9
9
|
import { AuthApi } from './api/auth'
|
|
10
|
-
import {
|
|
11
|
-
import { initializeApp } from 'firebase/app'
|
|
10
|
+
import { signInWithCustomToken } from 'firebase/auth'
|
|
12
11
|
import { useIframeStore } from './stores/iframe'
|
|
13
12
|
import { createFeedMeI18n, type I18n, detectLocale } from "@feedmepos/mf-common"
|
|
14
13
|
import enUS from "./locales/en-US.json"
|
|
@@ -16,6 +15,8 @@ import zhCN from "./locales/zh-CN.json"
|
|
|
16
15
|
import thTH from "./locales/th-TH.json"
|
|
17
16
|
import jaJP from "./locales/ja-JP.json"
|
|
18
17
|
|
|
18
|
+
import { getFirebaseAuth } from '@/utils/firebase-app'
|
|
19
|
+
|
|
19
20
|
export const i18nMessages = {
|
|
20
21
|
"en-US": enUS,
|
|
21
22
|
"zh-CN": zhCN,
|
|
@@ -34,15 +35,15 @@ function initI18n(): I18n {
|
|
|
34
35
|
|
|
35
36
|
const app = createApp(Entry)
|
|
36
37
|
|
|
38
|
+
app.use(initI18n())
|
|
39
|
+
app.use(createPinia())
|
|
40
|
+
app.use(router)
|
|
41
|
+
|
|
42
|
+
|
|
37
43
|
app.use(FeedMeUI, {
|
|
38
44
|
locale: detectLocale(),
|
|
39
45
|
})
|
|
40
46
|
|
|
41
|
-
app.use(createPinia() as any)
|
|
42
|
-
app.use(router)
|
|
43
|
-
app.use(initI18n() as any)
|
|
44
|
-
|
|
45
|
-
|
|
46
47
|
const CoreStore = useCoreStore();
|
|
47
48
|
const iframeMode = computed(() => {
|
|
48
49
|
return new URLSearchParams(window.location.search).get('iframe') === 'true';
|
|
@@ -50,18 +51,7 @@ const iframeMode = computed(() => {
|
|
|
50
51
|
|
|
51
52
|
useIframeStore().init(iframeMode.value);
|
|
52
53
|
|
|
53
|
-
const
|
|
54
|
-
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
|
55
|
-
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
|
56
|
-
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
|
57
|
-
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
|
58
|
-
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
|
59
|
-
appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
|
60
|
-
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
|
61
|
-
databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const firebaseAuth = getAuth(firebaseApp);
|
|
54
|
+
const firebaseAuth = getFirebaseAuth()
|
|
65
55
|
|
|
66
56
|
async function signInWithToken(token: string) {
|
|
67
57
|
const customToken = await AuthApi.getCustomToken(token);
|
|
@@ -94,4 +84,4 @@ async function init() {
|
|
|
94
84
|
}
|
|
95
85
|
|
|
96
86
|
|
|
97
|
-
init().then(() => app.mount('#app'))
|
|
87
|
+
init().then(() => app.mount('#app'))
|
|
@@ -80,7 +80,8 @@ export interface MfKioskOrderSetting {
|
|
|
80
80
|
takeaway: MfKioskTakeawaySetting,
|
|
81
81
|
paymentSetting: MfKioskPaymentSetting,
|
|
82
82
|
menuItem: MfKioskOrderSettingMenuItemForm,
|
|
83
|
-
|
|
83
|
+
coverImageLandscape: string | null,
|
|
84
|
+
coverImagePortrait: string | null,
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
export interface MfKioskOrderSettingMenuItemForm {
|
|
@@ -92,7 +93,8 @@ export interface MfKioskOrderSettingForm {
|
|
|
92
93
|
takeaway: KioskTakeawaySettingForm,
|
|
93
94
|
paymentSetting: KioskPaymentSettingForm,
|
|
94
95
|
menuItem: KioskMenuItemSettingForm,
|
|
95
|
-
|
|
96
|
+
coverImageLandscape: string | null,
|
|
97
|
+
coverImagePortrait: string | null,
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
export type KioskPickAtCounterSettingForm = MfKioskPickAtCounterSetting;
|
|
@@ -50,7 +50,7 @@ export const defaultPickUp: KioskPickAtCounterSettingForm = {
|
|
|
50
50
|
enablePaxDialog: false
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export const defaultKioskOrderSetting: MfKioskOrderSettingForm = {
|
|
53
|
+
export const defaultKioskOrderSetting: MfKioskOrderSettingForm = {
|
|
54
54
|
dineIn: {
|
|
55
55
|
enabled: false,
|
|
56
56
|
pickUp: defaultPickUp,
|
|
@@ -74,12 +74,13 @@ export const defaultKioskOrderSetting: MfKioskOrderSettingForm = {
|
|
|
74
74
|
scanPay: false
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
},
|
|
78
|
-
menuItem: {
|
|
79
|
-
showAllOnly: false
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
},
|
|
78
|
+
menuItem: {
|
|
79
|
+
showAllOnly: false
|
|
80
|
+
},
|
|
81
|
+
coverImageLandscape: null,
|
|
82
|
+
coverImagePortrait: null
|
|
83
|
+
}
|
|
83
84
|
|
|
84
85
|
export const defaultSubmitOrderInstruction: MfKioskSubmitOrderInstruction = {
|
|
85
86
|
payAtCounter: null,
|
|
@@ -108,10 +109,10 @@ const toKiosk = (
|
|
|
108
109
|
enabled: kioskOrderSettings?.canTakeaway ?? false,
|
|
109
110
|
submitOrderInstruction: kioskOrderSettings?.takeaway?.submitOrderInstruction
|
|
110
111
|
? {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
payAtCounter:
|
|
113
|
+
kioskOrderSettings?.takeaway?.submitOrderInstruction?.payAtCounter?.['en'] ?? null,
|
|
114
|
+
paid: kioskOrderSettings?.takeaway?.submitOrderInstruction?.paid?.['en'] ?? null
|
|
115
|
+
}
|
|
115
116
|
: defaultSubmitOrderInstruction
|
|
116
117
|
},
|
|
117
118
|
paymentSetting: {
|
|
@@ -130,12 +131,13 @@ const toKiosk = (
|
|
|
130
131
|
}
|
|
131
132
|
})
|
|
132
133
|
},
|
|
133
|
-
menuItem: {
|
|
134
|
-
showAllOnly: kioskOrderSettings?.menuItem?.showAllOnly ?? false
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
134
|
+
menuItem: {
|
|
135
|
+
showAllOnly: kioskOrderSettings?.menuItem?.showAllOnly ?? false
|
|
136
|
+
},
|
|
137
|
+
coverImageLandscape: kioskOrderSettings?.coverImageLandscape ?? null,
|
|
138
|
+
coverImagePortrait: kioskOrderSettings?.coverImagePortrait ?? null
|
|
139
|
+
}
|
|
140
|
+
}
|
|
139
141
|
|
|
140
142
|
const toKioskDineInSetting = (
|
|
141
143
|
kioskDineInSeq: OrderKioskDineInSequenceDto,
|
|
@@ -146,35 +148,35 @@ const toKioskDineInSetting = (
|
|
|
146
148
|
sequenceNumber: kioskDineInSeq,
|
|
147
149
|
pickUp: kioskDineInSetting?.pickUp
|
|
148
150
|
? {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
151
|
+
...kioskDineInSetting.pickUp,
|
|
152
|
+
submitOrderInstruction: kioskDineInSetting.pickUp.submitOrderInstruction
|
|
153
|
+
? {
|
|
154
|
+
payAtCounter:
|
|
155
|
+
kioskDineInSetting.pickUp.submitOrderInstruction?.payAtCounter?.['en'] ?? null,
|
|
156
|
+
paid: kioskDineInSetting.pickUp.submitOrderInstruction?.paid?.['en'] ?? null
|
|
157
|
+
}
|
|
158
|
+
: defaultSubmitOrderInstruction,
|
|
159
|
+
enablePaxDialog: kioskDineInSetting.pickUp.enablePaxDialog
|
|
160
|
+
? kioskDineInSetting.pickUp.enablePaxDialog
|
|
161
|
+
: false
|
|
162
|
+
}
|
|
161
163
|
: defaultPickUp,
|
|
162
164
|
displayStand: kioskDineInSetting?.displayStand
|
|
163
165
|
? {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
166
|
+
enabled: kioskDineInSetting.displayStand.enabled,
|
|
167
|
+
standSlotRange: kioskDineInSetting.displayStand.standSlotRange,
|
|
168
|
+
prefix: kioskDineInSetting.displayStand.prefix,
|
|
169
|
+
padDigit: kioskDineInSetting.displayStand.padDigit,
|
|
170
|
+
enablePaxDialog: kioskDineInSetting.displayStand.enablePaxDialog ?? false,
|
|
171
|
+
submitOrderInstruction: kioskDineInSetting.displayStand.submitOrderInstruction
|
|
172
|
+
? {
|
|
173
|
+
payAtCounter:
|
|
174
|
+
kioskDineInSetting.displayStand.submitOrderInstruction?.payAtCounter?.['en'] ??
|
|
175
|
+
null,
|
|
176
|
+
paid: kioskDineInSetting.displayStand.submitOrderInstruction?.paid?.['en'] ?? null
|
|
177
|
+
}
|
|
178
|
+
: defaultSubmitOrderInstruction
|
|
179
|
+
}
|
|
178
180
|
: defaultDisplayStand
|
|
179
181
|
}
|
|
180
182
|
}
|
|
@@ -191,13 +193,13 @@ const toOrderKioskSettingsDto = (
|
|
|
191
193
|
submitOrderInstruction: {
|
|
192
194
|
payAtCounter: dineInSetting.displayStand.submitOrderInstruction?.payAtCounter
|
|
193
195
|
? {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
+
en: dineInSetting.displayStand.submitOrderInstruction.payAtCounter
|
|
197
|
+
}
|
|
196
198
|
: null,
|
|
197
199
|
paid: dineInSetting.displayStand.submitOrderInstruction?.paid
|
|
198
200
|
? {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
en: dineInSetting.displayStand.submitOrderInstruction.paid
|
|
202
|
+
}
|
|
201
203
|
: null
|
|
202
204
|
}
|
|
203
205
|
},
|
|
@@ -206,26 +208,27 @@ const toOrderKioskSettingsDto = (
|
|
|
206
208
|
submitOrderInstruction: {
|
|
207
209
|
payAtCounter: dineInSetting.pickUp.submitOrderInstruction?.payAtCounter
|
|
208
210
|
? {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
+
en: dineInSetting.pickUp.submitOrderInstruction.payAtCounter
|
|
212
|
+
}
|
|
211
213
|
: null,
|
|
212
214
|
paid: dineInSetting.pickUp.submitOrderInstruction?.paid
|
|
213
215
|
? {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
en: dineInSetting.pickUp.submitOrderInstruction.paid
|
|
217
|
+
}
|
|
216
218
|
: null
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
221
|
})
|
|
220
222
|
|
|
221
|
-
const createKioskSettings = (dineIn?: OrderKioskDineIn): OrderKioskSettings => ({
|
|
222
|
-
canTakeaway: kioskSetting.takeaway.enabled,
|
|
223
|
-
dineIn,
|
|
224
|
-
menuItem: kioskSetting.menuItem,
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
const createKioskSettings = (dineIn?: OrderKioskDineIn): OrderKioskSettings => ({
|
|
224
|
+
canTakeaway: kioskSetting.takeaway.enabled,
|
|
225
|
+
dineIn,
|
|
226
|
+
menuItem: kioskSetting.menuItem,
|
|
227
|
+
coverImageLandscape: kioskSetting.coverImageLandscape,
|
|
228
|
+
coverImagePortrait: kioskSetting.coverImagePortrait,
|
|
229
|
+
paymentSetting: createPaymentSettings(kioskSetting.paymentSetting),
|
|
230
|
+
takeaway: kioskSetting.takeaway.submitOrderInstruction
|
|
231
|
+
? {
|
|
229
232
|
submitOrderInstruction: {
|
|
230
233
|
payAtCounter: kioskSetting.takeaway.submitOrderInstruction.payAtCounter
|
|
231
234
|
? {
|
|
@@ -237,8 +240,8 @@ const toOrderKioskSettingsDto = (
|
|
|
237
240
|
en: kioskSetting.takeaway.submitOrderInstruction.paid
|
|
238
241
|
}
|
|
239
242
|
: null
|
|
243
|
+
}
|
|
240
244
|
}
|
|
241
|
-
}
|
|
242
245
|
: undefined
|
|
243
246
|
})
|
|
244
247
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FirebaseApp } from 'firebase/app'
|
|
2
|
+
import { getApp, getApps, initializeApp } from 'firebase/app'
|
|
3
|
+
import { getAuth } from 'firebase/auth'
|
|
4
|
+
import { getStorage } from 'firebase/storage'
|
|
5
|
+
|
|
6
|
+
let firebaseApp: FirebaseApp | null = null
|
|
7
|
+
|
|
8
|
+
export function ensureFirebaseApp(): FirebaseApp {
|
|
9
|
+
if (firebaseApp) return firebaseApp
|
|
10
|
+
|
|
11
|
+
firebaseApp =
|
|
12
|
+
getApps().length > 0
|
|
13
|
+
? getApp()
|
|
14
|
+
: initializeApp({
|
|
15
|
+
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
|
16
|
+
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
|
17
|
+
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
|
18
|
+
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
|
19
|
+
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
|
20
|
+
appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
|
21
|
+
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
|
22
|
+
databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
return firebaseApp
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getFirebaseAuth() {
|
|
29
|
+
return getAuth(ensureFirebaseApp())
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getFirebaseStorage() {
|
|
33
|
+
return getStorage(ensureFirebaseApp())
|
|
34
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { AuthApi } from '@/api/auth'
|
|
2
|
+
import { SvcConfig } from '@/api'
|
|
3
|
+
import { signInWithCustomToken, signOut } from 'firebase/auth'
|
|
4
|
+
import { ref, uploadBytes } from 'firebase/storage'
|
|
5
|
+
import { getFirebaseAuth, getFirebaseStorage } from './firebase-app'
|
|
6
|
+
|
|
7
|
+
let pendingFirebaseSignIn: Promise<void> | null = null
|
|
8
|
+
|
|
9
|
+
function getFileExtension(file: File): string {
|
|
10
|
+
const nameExt = file.name.split('.').pop()?.toLowerCase()
|
|
11
|
+
if (nameExt && /^[a-z0-9]+$/.test(nameExt)) return nameExt
|
|
12
|
+
|
|
13
|
+
const mimeExtMap: Record<string, string> = {
|
|
14
|
+
'image/jpeg': 'jpg',
|
|
15
|
+
'image/png': 'png',
|
|
16
|
+
'image/webp': 'webp',
|
|
17
|
+
'image/gif': 'gif'
|
|
18
|
+
}
|
|
19
|
+
return mimeExtMap[file.type] ?? 'bin'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getStorageBucketHost(): string {
|
|
23
|
+
const endpointWithFirebase = appEndpoint as typeof appEndpoint & {
|
|
24
|
+
firebase?: { storageBucket?: string }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const bucket =
|
|
28
|
+
endpointWithFirebase.firebase?.storageBucket ??
|
|
29
|
+
appApi.firebase.storageBucket ??
|
|
30
|
+
import.meta.env.VITE_FIREBASE_STORAGE_BUCKET
|
|
31
|
+
|
|
32
|
+
return bucket.replace(/^https?:\/\//, '').replace(/\/+$/, '')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function generateItemThumbnailUrl(path: string): string {
|
|
36
|
+
const normalizedPath = path.replace(/^\/+/, '')
|
|
37
|
+
return `https://${getStorageBucketHost()}/${normalizedPath}`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function ensureFirebaseAuth(): Promise<void> {
|
|
41
|
+
const auth = getFirebaseAuth()
|
|
42
|
+
if (auth.currentUser) return
|
|
43
|
+
await auth.authStateReady()
|
|
44
|
+
if (auth.currentUser) return
|
|
45
|
+
|
|
46
|
+
if (!pendingFirebaseSignIn) {
|
|
47
|
+
pendingFirebaseSignIn = (async () => {
|
|
48
|
+
const idToken = SvcConfig.getIdToken()
|
|
49
|
+
if (!idToken) {
|
|
50
|
+
throw new Error('Missing session token for Firebase authentication')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const customToken = await AuthApi.getCustomToken(idToken)
|
|
54
|
+
await signInWithCustomToken(auth, customToken)
|
|
55
|
+
})().finally(() => {
|
|
56
|
+
pendingFirebaseSignIn = null
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await pendingFirebaseSignIn
|
|
61
|
+
if (!auth.currentUser) {
|
|
62
|
+
throw new Error('User not authenticated for image upload')
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function forceRefreshFirebaseAuth(): Promise<void> {
|
|
67
|
+
const auth = getFirebaseAuth()
|
|
68
|
+
const idToken = SvcConfig.getIdToken()
|
|
69
|
+
if (!idToken) {
|
|
70
|
+
throw new Error('Missing session token for Firebase authentication')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (auth.currentUser) {
|
|
74
|
+
await signOut(auth)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const customToken = await AuthApi.getCustomToken(idToken)
|
|
78
|
+
await signInWithCustomToken(auth, customToken)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function uploadWithAuthRetry(storagePath: string, file: File): Promise<void> {
|
|
82
|
+
const storage = getFirebaseStorage()
|
|
83
|
+
const fileRef = ref(storage, storagePath)
|
|
84
|
+
try {
|
|
85
|
+
await uploadBytes(fileRef, file, {
|
|
86
|
+
contentType: file.type || undefined
|
|
87
|
+
})
|
|
88
|
+
return
|
|
89
|
+
} catch (error) {
|
|
90
|
+
const code = (error as { code?: string })?.code
|
|
91
|
+
if (code !== 'storage/unauthorized') {
|
|
92
|
+
throw error
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await forceRefreshFirebaseAuth()
|
|
97
|
+
const retriedRef = ref(storage, storagePath)
|
|
98
|
+
await uploadBytes(retriedRef, file, {
|
|
99
|
+
contentType: file.type || undefined
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function uploadImageFile(pathPrefix: string, file: File): Promise<string> {
|
|
104
|
+
await ensureFirebaseAuth()
|
|
105
|
+
|
|
106
|
+
const normalizedPrefix = pathPrefix.replace(/^\/+/, '').replace(/\/+$/, '')
|
|
107
|
+
const ext = getFileExtension(file)
|
|
108
|
+
const fileName = `${Date.now()}_${Math.random().toString(36).slice(2, 10)}.${ext}`
|
|
109
|
+
const fullPath = `${normalizedPrefix}/${fileName}`
|
|
110
|
+
await uploadWithAuthRetry(fullPath, file)
|
|
111
|
+
return generateItemThumbnailUrl(fullPath)
|
|
112
|
+
}
|