@feedmepos/mf-order-setting 0.0.75-prod → 0.0.76

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 (29) hide show
  1. package/dist/{KioskDevicesView-B1dsUMwh.js → KioskDevicesView-H7stMDFu.js} +1 -1
  2. package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-BmCrSZnS.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-DgpV4oKE.js} +3 -3
  3. package/dist/{KioskSettingView-DUUr39PJ.js → KioskSettingView-fF6k9s_q.js} +3 -3
  4. package/dist/KioskView-Cxcc1UL1.js +420 -0
  5. package/dist/{OrderSettingsView-AY0L3EfF.js → OrderSettingsView-Ds2L_rbu.js} +7717 -7871
  6. package/dist/{app-DzO7wZsC.js → app-BDlPjU4y.js} +9 -5
  7. package/dist/app.js +1 -1
  8. package/dist/{dayjs.min-BNHTbbaJ.js → dayjs.min-OJf1trOq.js} +1 -1
  9. package/dist/frontend/mf-order/src/app.d.ts +4 -0
  10. package/dist/frontend/mf-order/src/main.d.ts +4 -0
  11. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpSetting.vue.d.ts +0 -17
  12. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpSettingDialogContent.vue.d.ts +9 -0
  13. package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
  14. package/dist/{index-DQA37h5T.js → index-Bid9lO2x.js} +2 -2
  15. package/dist/index-gGOpbnY3.js +23 -0
  16. package/dist/{lineman-settings.dto-BMG_DnTF.js → lineman-settings.dto-Cny_fF4n.js} +1 -1
  17. package/package.json +1 -1
  18. package/src/locales/en-US.json +1 -0
  19. package/src/locales/ja-JP.json +1 -0
  20. package/src/locales/th-TH.json +1 -0
  21. package/src/locales/zh-CN.json +1 -0
  22. package/src/views/order-settings/pickup/PickUpSetting.vue +124 -195
  23. package/src/views/order-settings/pickup/PickUpSettingDialogContent.vue +24 -1
  24. package/dist/KioskView-4_Kl607M.js +0 -362
  25. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickUpSettingDialog.vue.d.ts +0 -16
  26. package/dist/frontend/mf-order/src/views/order-settings/pickup/PickupList.vue.d.ts +0 -16
  27. package/dist/index-BP0fOlVh.js +0 -86
  28. package/src/views/order-settings/pickup/PickUpSettingDialog.vue +0 -118
  29. package/src/views/order-settings/pickup/PickupList.vue +0 -49
@@ -1,9 +1,9 @@
1
1
  import { defineComponent as Q, ref as O, resolveComponent as F, openBlock as g, createElementBlock as E, createElementVNode as h, toDisplayString as C, createVNode as D, unref as $, createBlock as j, computed as N, watch as ne, onMounted as ae, withCtx as M, createTextVNode as re, createCommentVNode as x, Fragment as oe, renderList as se, renderSlot as ue } from "vue";
2
- import { e as w } from "./app-DzO7wZsC.js";
2
+ import { e as w } from "./app-BDlPjU4y.js";
3
3
  import { useDialog as le, useSnackbar as ie } from "@feedmepos/ui-library";
4
4
  import { useI18n as G, useCoreStore as te } from "@feedmepos/mf-common";
5
5
  import { defineStore as de } from "pinia";
6
- import { r as R, g as n, x as V, w as z, e as q } from "./lineman-settings.dto-BMG_DnTF.js";
6
+ import { r as R, g as n, x as V, w as z, e as q } from "./lineman-settings.dto-Cny_fF4n.js";
7
7
  const ce = /* @__PURE__ */ Q({
8
8
  __name: "OfflinePaymentTypeDialogContent",
9
9
  props: {
@@ -0,0 +1,23 @@
1
+ import { g as n, v as a, w as r, r as e } from "./lineman-settings.dto-Cny_fF4n.js";
2
+ async function i() {
3
+ const t = await e().get("/order-settings");
4
+ return n(t);
5
+ }
6
+ async function c(t) {
7
+ const s = await e().put("/order-settings", t);
8
+ return n(s);
9
+ }
10
+ const u = {
11
+ getOrderSetting: i,
12
+ updateOrderSetting: c
13
+ };
14
+ async function o() {
15
+ return n(await a().get(`balance/${r.getBusinessId()}`));
16
+ }
17
+ const d = {
18
+ read: o
19
+ };
20
+ export {
21
+ u as O,
22
+ d as s
23
+ };
@@ -1,7 +1,7 @@
1
1
  var G5 = Object.defineProperty;
2
2
  var q5 = (i, u, s) => u in i ? G5(i, u, { enumerable: !0, configurable: !0, writable: !0, value: s }) : i[u] = s;
3
3
  var YS = (i, u, s) => q5(i, typeof u != "symbol" ? u + "" : u, s);
4
- import { e as x, l, c as ge, i as re, j as Y5, z as ut } from "./app-DzO7wZsC.js";
4
+ import { e as x, l, c as ge, i as re, j as Y5, z as ut } from "./app-BDlPjU4y.js";
5
5
  import { useCoreStore as _u } from "@feedmepos/mf-common";
6
6
  function fO(i, u) {
7
7
  return function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feedmepos/mf-order-setting",
3
- "version": "0.0.75-prod",
3
+ "version": "0.0.76",
4
4
  "type": "module",
5
5
  "module": "./dist/app.js",
6
6
  "license": "UNLICENSED",
@@ -284,6 +284,7 @@
284
284
  "offlinePayment": "Offline Payment",
285
285
  "offlinePaymentName": "Offline Payment Name",
286
286
  "online": "Online",
287
+ "onlineFromPos": "Adjust from POS",
287
288
  "operatingHour": "Operating hour",
288
289
  "operatingSystem": "Operating System",
289
290
  "orderFrom": "Order from",
@@ -204,6 +204,7 @@
204
204
  "offlinePayment": "オフライン支払い",
205
205
  "offlinePaymentName": "オフライン支払い名",
206
206
  "online": "オンライン",
207
+ "onlineFromPos": "POSで調整",
207
208
  "operatingHour": "営業時間",
208
209
  "orderFrom": "注文元",
209
210
  "orderNumberSettings": "番号設定",
@@ -207,6 +207,7 @@
207
207
  "offlinePayment": "การชำระเงินแบบออฟไลน์",
208
208
  "offlinePaymentName": "ชื่อการชำระเงินแบบออฟไลน์",
209
209
  "online": "ออนไลน์",
210
+ "onlineFromPos": "ปรับจาก POS",
210
211
  "operatingHour": "เวลาทำการ",
211
212
  "orderFrom": "คำสั่งซื้อจาก",
212
213
  "orderNumberSettings": "การตั้งค่าการออกหมายเลข",
@@ -211,6 +211,7 @@
211
211
  "offlinePayment": "线下支付",
212
212
  "offlinePaymentName": "付款名称",
213
213
  "online": "在线",
214
+ "onlineFromPos": "在 POS 调整",
214
215
  "operatingHour": "营业时间",
215
216
  "orderFrom": "预订从",
216
217
  "orderNumberSettings": "编号设置",
@@ -1,226 +1,155 @@
1
1
  <template>
2
- <div v-if="isLoading" class="column">
3
- <FmCircularProgress size="xxl" />
2
+ <div class="flex justify-between items-center">
3
+ <RestaurantSelector />
4
4
  </div>
5
- <div v-else class="block m-3">
6
- <div class="flex justify-end items-center mb-3">
7
- <FmSearch v-model="searchKey" :placeholder="t('order.search')" />
5
+ <div v-if="isReady">
6
+ <div class="p-[1.5rem] flex flex-col m-5 w-2/3 max-w-4xl">
7
+ <PickUpSettingDialogContent
8
+ :pickup="pickupSetting"
9
+ :order-pickup-settings="orderPickupSettings"
10
+ :accept-pickup="acceptPickup"
11
+ @update-pickup="updatePickupSetting"
12
+ @update-order-settings="updateOrderPickupSettings"
13
+ />
14
+ <div class="fm-corner-radius-lg flex flex-col gap-5 mt-5">
15
+ <FmButton
16
+ variant="primary"
17
+ :label="t('order.saveSetting')"
18
+ class="mr-auto"
19
+ @click="onSave"
20
+ />
21
+ </div>
8
22
  </div>
9
- <PickupList
10
- :pickupSettingData="pickupSettingData"
11
- @toggleSideSheet="toggleSideSheet"
12
- class="mt-5 md:hidden lg:hidden xl:hidden"
13
- />
14
- <FmTable
15
- class="h-[500px] xs:hidden sm:hidden"
16
- :row-data="pickupSettingData"
17
- :hideFooter="true"
18
- :column-defs="columns"
19
- :loading="isLoading"
20
- @row-click="toggleSideSheet"
21
- :pageSize="pickupSettingData.length"
22
- >
23
- </FmTable>
24
- <PickUpSettingDialog :showPickupDialog="sideSheet" @closeSideSheet="closeSideSheet" />
25
23
  </div>
24
+ <div v-else-if="!currentRestaurant?._id" class="p-[1.5rem] m-5">
25
+ {{ t('order.noRestaurantSelected') }}
26
+ </div>
27
+ <div v-else-if="loadError" class="p-[1.5rem] m-5">
28
+ <FmButton variant="secondary" :label="t('order.retry')" @click="loadSetting" />
29
+ </div>
30
+ <FmCircularProgress size="xxl" v-else />
26
31
  </template>
27
32
 
28
33
  <script setup lang="ts">
29
- import { computed, h, onMounted, ref, watch } from 'vue'
30
- import type { ColumnDef } from '@feedmepos/ui-library'
34
+ import { computed, onMounted, ref, watch } from 'vue'
31
35
  import { useCoreStore, useI18n } from '@feedmepos/mf-common'
32
- import type { FdoRestaurant, FdoRestaurantPickup } from '@feedmepos/core/entity'
36
+ import { utils } from '@feedmepos/core'
37
+ import { F_ORDER_PAYMENT_TYPE, FdoRestaurantPickup } from '@feedmepos/core/entity'
38
+ import type { OrderPickupSettingsDto, OrderSettingsDto } from '@entity'
39
+ import RestaurantSelector from '../components/RestaurantSelector.vue'
40
+ import PickUpSettingDialogContent from './PickUpSettingDialogContent.vue'
41
+ import { MAX_PREORDER_DAYS } from './Preorder.vue'
33
42
  import { useRestaurantStore } from '@/stores/restaurant'
34
- import useSearch from '@/composables/search'
35
- import { sentenceCase } from 'change-case'
36
- import PickUpSettingDialog from './PickUpSettingDialog.vue'
37
43
  import { useLoading } from '@/composables/loading'
38
- import PickupList from './PickupList.vue'
39
-
40
- interface FmpRestaurant extends FdoRestaurant {
41
- managable: boolean
42
- }
44
+ import { useSnackbarFunctions } from '@/components/snackbar'
45
+ import { OrderSettingApi } from '@/api/order-setting'
43
46
 
44
47
  const { t } = useI18n()
45
- const { searchKey, filter } = useSearch()
46
- const { restaurants, changeRestaurant, currentRestaurant } = useCoreStore()
48
+ const { currentRestaurant } = useCoreStore()
47
49
  const restaurantStore = useRestaurantStore()
48
- const sideSheet = ref<boolean>(false)
49
50
  const { isLoading, startAsyncCallWithErr } = useLoading()
50
- const currentRestaurants = ref<FmpRestaurant[]>([])
51
-
52
- const pickupSetting = computed<RestaurantPickup[]>(() => {
53
- return currentRestaurants.value.map((r: FmpRestaurant) => {
54
- const restaurantSetting = restaurantStore.state.restaurantSettings[r._id]
55
-
56
- return {
57
- enable: restaurantSetting?.acceptPickup,
58
- restaurant: {
59
- id: r._id,
60
- name: r.profile.name
61
- },
62
- ...(restaurantSetting?.pickup || r.pickup)
63
- }
64
- })
65
- })
51
+ const { showSuccess, showError } = useSnackbarFunctions()
52
+
53
+ const pickupSetting = ref<FdoRestaurantPickup>(initDefaultPickupSetting())
54
+ const acceptPickup = ref<boolean>(false)
55
+ // The form (and its Save) must only render once BOTH fetches completed for the
56
+ // restaurant that is still selected — otherwise a failed or raced load exposes
57
+ // an editable default form whose Save would overwrite the real config.
58
+ const loadedForId = ref<string | null>(null)
59
+ const loadError = ref(false)
60
+ const isReady = computed(
61
+ () => !isLoading.value && loadedForId.value === currentRestaurant.value?._id
62
+ )
63
+ // `orderSetting.pickupSettings` (bill auto-close / receipt-print) is a separate doc
64
+ // from the restaurant-level pickup setting; loaded/saved alongside it here.
65
+ const orderSetting = ref<OrderSettingsDto | undefined>(undefined)
66
+ const orderPickupSettings = ref<OrderPickupSettingsDto>({})
67
+
68
+ function initDefaultPickupSetting(): FdoRestaurantPickup {
69
+ return {
70
+ offlinePaymentTypes: [],
71
+ paymentTypes: [F_ORDER_PAYMENT_TYPE.enum.cash]
72
+ }
73
+ }
66
74
 
67
- async function fetchRestaurants() {
68
- await startAsyncCallWithErr(async () => {
69
- if (!!restaurants.value) {
70
- currentRestaurants.value = [...restaurants.value]
75
+ async function loadSetting() {
76
+ const restaurant = currentRestaurant.value
77
+ if (!restaurant?._id) return
78
+ // Reset before any await so a partial failure can never leave the previous
79
+ // restaurant's docs live under this restaurant's selector (a later save would
80
+ // write them to the wrong restaurant).
81
+ loadedForId.value = null
82
+ loadError.value = false
83
+ pickupSetting.value = initDefaultPickupSetting()
84
+ acceptPickup.value = false
85
+ orderSetting.value = undefined
86
+ orderPickupSettings.value = {}
87
+ try {
88
+ await startAsyncCallWithErr(async () => {
89
+ const restaurantSetting = await restaurantStore.readRestaurantSetting(restaurant._id)
90
+ // The selector stays clickable while requests are in flight — a late response
91
+ // for a restaurant the user already switched away from must not land.
92
+ if (currentRestaurant.value?._id !== restaurant._id) return
93
+ acceptPickup.value = !!restaurantSetting?.acceptPickup
94
+ // Clone: the form's in-place edits must never mutate the store-cached
95
+ // setting doc or the core-store restaurant object.
96
+ pickupSetting.value = utils.clone(
97
+ restaurantSetting?.pickup ?? restaurant.pickup ?? initDefaultPickupSetting()
98
+ )
99
+ const setting = await OrderSettingApi.getOrderSetting()
100
+ if (currentRestaurant.value?._id !== restaurant._id) return
101
+ orderSetting.value = setting
102
+ orderPickupSettings.value = setting.pickupSettings ?? {}
103
+ loadedForId.value = restaurant._id
104
+ })
105
+ } catch {
106
+ // startAsyncCallWithErr already surfaced the error snackbar; keep the form
107
+ // behind the retry state so Save can never persist the reset defaults.
108
+ if (currentRestaurant.value?._id === restaurant._id) {
109
+ loadError.value = true
71
110
  }
72
- await Promise.all(
73
- currentRestaurants.value.map(async (r: FmpRestaurant) => {
74
- await restaurantStore.readRestaurantSetting(r._id)
75
- })
76
- )
77
- })
111
+ }
78
112
  }
79
113
 
80
- onMounted(async () => {
81
- await fetchRestaurants()
82
- })
114
+ onMounted(loadSetting)
83
115
 
84
116
  watch(
85
- () => restaurants.value,
86
- async () => {
87
- await fetchRestaurants()
88
- }
117
+ () => currentRestaurant.value?._id,
118
+ () => loadSetting()
89
119
  )
90
120
 
91
- async function onUpdate() {
92
- await fetchRestaurants()
121
+ function updatePickupSetting(value: FdoRestaurantPickup) {
122
+ pickupSetting.value = value
93
123
  }
94
124
 
95
- let originalRestaurant: any
96
-
97
- async function toggleSideSheet(rowData: any) {
98
- const v = rowData?.original?.restaurantId ?? rowData?.restaurantId
99
- originalRestaurant = currentRestaurant.value
100
-
101
- const restaurant: FmpRestaurant | undefined = currentRestaurants.value.find(
102
- (r: FmpRestaurant) => r._id === v
103
- )
104
- if (restaurant) {
105
- await changeRestaurant(restaurant as any)
106
- }
107
- sideSheet.value = true
125
+ function updateOrderPickupSettings(value: OrderPickupSettingsDto) {
126
+ orderPickupSettings.value = value
108
127
  }
109
128
 
110
- async function closeSideSheet(refresh = false) {
111
- sideSheet.value = false
112
- if (originalRestaurant) {
113
- await changeRestaurant(originalRestaurant)
114
- }
115
- if (refresh) {
116
- await onUpdate()
129
+ async function onSave() {
130
+ const restaurant = currentRestaurant.value
131
+ if (!restaurant?._id) return
132
+ const pickupTime = pickupSetting.value.pickupTime
133
+ if (pickupTime?.day) {
134
+ const { min, max } = pickupTime.day
135
+ if (max <= min || max - min > MAX_PREORDER_DAYS) {
136
+ showError(t('order.preOrderMaxDaysError', { days: MAX_PREORDER_DAYS }))
137
+ return
138
+ }
117
139
  }
118
- }
119
-
120
- const filteredPickupSettings = computed<RestaurantPickup[]>(() => {
121
- return pickupSetting.value.filter(({ restaurant, paymentTypes, offlinePaymentTypes }) =>
122
- filter([
123
- restaurant.name,
124
- paymentTypes?.join('') || '',
125
- offlinePaymentTypes?.map((p) => p.name).join('') || ''
126
- ])
127
- )
128
- })
129
-
130
- const pickupSettingData = computed<PickupSettingData[]>(() => {
131
- return filteredPickupSettings.value.map((item) => {
132
- const hasCustomOfflinePayment = !!item.offlinePaymentTypes?.length
133
- const canOfflinePayment = (item.paymentTypes || []).includes('cash')
134
- const paymentMethod = !hasCustomOfflinePayment
135
- ? (item.paymentTypes || []).map((p) => sentenceCase(p)).join(', ')
136
- : [
137
- (item.paymentTypes || [])
138
- .filter((p) => p !== 'cash')
139
- .map((p) => sentenceCase(p))
140
- .join(', '),
141
- canOfflinePayment
142
- ? (item.offlinePaymentTypes || []).map((p) => sentenceCase(p.name)).join(', ')
143
- : ''
144
- ]
145
- .filter((v) => !!v)
146
- .join(', ')
147
-
148
- const onlineStatus = item.enable ? t('order.activated') : t('order.inactive')
149
-
150
- const preorderRange = item.pickupTime
151
- ? `${item.pickupTime.day.min} ${t('order.to')} ${item.pickupTime.day.max - 1} ${t('order.day')}`
152
- : '-'
153
- const pickupPointCount = item.pickupPointConfig?.points.length || 0
154
-
155
- return {
156
- restaurantId: item.restaurant.id,
157
- restaurant: item.restaurant.name,
158
- paymentmethod: paymentMethod,
159
- online: onlineStatus,
160
- enable: item.enable,
161
- preorder: preorderRange,
162
- pickuppoint: `${pickupPointCount} ${t('order.pickupPoint')}`
140
+ await startAsyncCallWithErr(async () => {
141
+ await restaurantStore.updatePickupSetting(pickupSetting.value)
142
+ restaurant.pickup = utils.clone(pickupSetting.value)
143
+ // The order-settings client resolves the CURRENT restaurant at call time —
144
+ // if the user switched away while the pickup PUT was in flight, this would
145
+ // write this restaurant's doc onto the newly selected one. Skip instead.
146
+ if (orderSetting.value && currentRestaurant.value?._id === restaurant._id) {
147
+ orderSetting.value = await OrderSettingApi.updateOrderSetting({
148
+ ...orderSetting.value,
149
+ pickupSettings: orderPickupSettings.value
150
+ })
163
151
  }
152
+ showSuccess('Pickup setting updated.')
164
153
  })
165
- })
166
-
167
- export interface PickupSettingData {
168
- restaurantId: string
169
- restaurant: string
170
- paymentmethod: string
171
- online: string
172
- enable: boolean
173
- preorder: string
174
- pickuppoint: string
175
- }
176
-
177
- export interface RestaurantPickup extends FdoRestaurantPickup {
178
- enable: boolean
179
- restaurant: {
180
- id: string
181
- name: string
182
- }
183
154
  }
184
-
185
- const getClassForOnline = (enabled: boolean) => {
186
- return enabled
187
- ? 'bg-fm-color-system-success-100 text-fm-color-system-success-400 fm-typo-en-body-md-600 border fm-corner-radius-lg w-max gap-8 p-4'
188
- : ' bg-fm-color-neutral-gray-100 fm-typo-en-body-md-600 border fm-corner-radius-lg w-max gap-8 p-4'
189
- }
190
-
191
- const columns: ColumnDef<any>[] = [
192
- {
193
- accessorKey: 'restaurant',
194
- header: () => t('order.restaurant'),
195
- meta: {
196
- maxWidth: '150px'
197
- },
198
- enableSorting: false
199
- },
200
- {
201
- accessorKey: 'paymentmethod',
202
- header: () => t('order.paymentMethod'),
203
- enableSorting: false
204
- },
205
- {
206
- accessorKey: 'online',
207
- header: () => t('order.online'),
208
- cell: (info: any) => {
209
- const enabled = info.row.original.enable
210
- const onlineStatus = info.getValue()
211
- return h('div', { class: getClassForOnline(enabled) }, onlineStatus)
212
- },
213
- enableSorting: false
214
- },
215
- {
216
- accessorKey: 'preorder',
217
- header: () => t('order.preOrder'),
218
- enableSorting: false
219
- },
220
- {
221
- accessorKey: 'pickuppoint',
222
- header: () => t('order.pickupPoint'),
223
- enableSorting: false
224
- }
225
- ]
226
155
  </script>
@@ -1,5 +1,16 @@
1
1
  <template>
2
- <div class="flex-grow fm-typo-en-title-sm-600 mb-3 mt-3">{{ t('order.generalSetting') }}</div>
2
+ <div class="flex-grow fm-typo-en-title-sm-600 mb-5">{{ t('order.generalSetting') }}</div>
3
+ <div class="flex flex-col mb-5">
4
+ <div class="flex items-center gap-3">
5
+ <span class="fm-typo-en-body-md-600">{{ t('order.online') }}</span>
6
+ <div :class="getClassForOnline(acceptPickup)">
7
+ {{ acceptPickup ? t('order.activated') : t('order.inactive') }}
8
+ </div>
9
+ </div>
10
+ <span class="fm-typo-en-body-sm-400 text-fm-color-typo-secondary">
11
+ {{ t('order.onlineFromPos') }}
12
+ </span>
13
+ </div>
3
14
  <FmSwitch
4
15
  :model-value="pickupSetting.ignoreStock ?? false"
5
16
  value="ignoreStock"
@@ -107,9 +118,21 @@ const props = defineProps({
107
118
  orderPickupSettings: {
108
119
  type: Object as PropType<OrderPickupSettingsDto>,
109
120
  default: () => ({})
121
+ },
122
+ // Read-only pickup online status (restaurant-level `acceptPickup`); shown as a
123
+ // labeled row at the top of this section, not editable here.
124
+ acceptPickup: {
125
+ type: Boolean,
126
+ default: false
110
127
  }
111
128
  })
112
129
 
130
+ const getClassForOnline = (enabled: boolean) => {
131
+ return enabled
132
+ ? 'bg-fm-color-system-success-100 text-fm-color-system-success-400 fm-typo-en-body-md-600 border fm-corner-radius-lg w-max p-4'
133
+ : 'bg-fm-color-neutral-gray-100 text-fm-color-typo-neutral fm-typo-en-body-md-600 border fm-corner-radius-lg w-max p-4'
134
+ }
135
+
113
136
  function updateAutoCloseBill(autoCloseBill: boolean) {
114
137
  emits('update-order-settings', { ...props.orderPickupSettings, autoCloseBill })
115
138
  }