@feedmepos/mf-order-setting 0.0.54 → 0.0.56-dev.2
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/.tsbuildinfo +1 -0
- package/dist/{KioskDevicesView-CMKNjgWx.js → KioskDevicesView-Qv-xd_kZ.js} +1 -1
- package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-B1sNvlUC.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-CCF1mKni.js} +2 -2
- package/dist/KioskSettingView-CvvrK6Bv.js +643 -0
- package/dist/{KioskView-U-Wg8oMC.js → KioskView-CppTVBv-.js} +117 -117
- package/dist/OrderSettingsView-C38N61dM.js +36564 -0
- package/dist/{app-CFfgPAd8.js → app-Bss1GkKY.js} +392 -228
- package/dist/app.js +1 -1
- package/dist/{dayjs.min-CuRr-wlf.js → dayjs.min-DZfxGUk4.js} +1 -1
- package/dist/frontend/mf-order/src/api/reservation/index.d.ts +8 -0
- package/dist/frontend/mf-order/src/app.d.ts +164 -0
- package/dist/frontend/mf-order/src/main.d.ts +164 -0
- package/dist/frontend/mf-order/src/stores/order-setting/index.d.ts +3 -0
- package/dist/frontend/mf-order/src/stores/restaurant/index.d.ts +1 -1
- package/dist/frontend/mf-order/src/views/kiosk/settings/KioskPaymentTypeSection.vue.d.ts +13 -3
- package/dist/frontend/mf-order/src/views/order-settings/delivery/integrated-delivery/ExternalSetting.vue.d.ts +12 -4
- package/dist/frontend/mf-order/src/views/order-settings/dine-in/OfflinePaymentTypeDialog.vue.d.ts +4 -4
- package/dist/frontend/mf-order/src/views/order-settings/dine-in/PaymentType.vue.d.ts +38 -4
- package/dist/frontend/mf-order/src/views/order-settings/pickup/PaymentSidesheet.vue.d.ts +1 -0
- package/dist/frontend/mf-order/src/views/order-settings/reservation/CopySettingsSheet.vue.d.ts +186 -0
- package/dist/frontend/mf-order/src/views/order-settings/reservation/CustomSelect.vue.d.ts +15 -0
- package/dist/frontend/mf-order/src/views/order-settings/reservation/CustomTimePicker.vue.d.ts +11 -0
- package/dist/frontend/mf-order/src/views/order-settings/reservation/ReservationSetting.vue.d.ts +2 -0
- package/dist/{index-Bj0bCGTm.js → index-B6AGCsrw.js} +3 -3
- package/dist/index-BpKR-Cxd.js +19757 -0
- package/dist/{menu.dto-DAh1J2ES.js → menu.dto-C_B3M2fs.js} +7390 -7134
- package/dist/package/entity/incoming-order/incoming-order.do.d.ts +22443 -3
- package/dist/package/entity/incoming-order/incoming-order.dto.d.ts +3 -3
- package/dist/package/entity/incoming-order/incoming-order.enum.d.ts +1 -1
- package/dist/package/entity/index.d.ts +6 -0
- package/dist/package/entity/marketing/marketing.dto.d.ts +1 -1
- package/dist/package/entity/order/dine-in/qr.dto.d.ts +38 -0
- package/dist/package/entity/order/order.do.d.ts +6358 -2
- package/dist/package/entity/order/order.dto.d.ts +22 -0
- package/dist/package/entity/order-platform/deliveroo/deliveroo-dto.d.ts +3 -0
- package/dist/package/entity/order-platform/deliveroo/deliveroo-setting.do.d.ts +3 -0
- package/dist/package/entity/order-platform/external/order/external-order.do.d.ts +12 -12
- package/dist/package/entity/order-platform/external/order/external-order.dto.d.ts +32 -32
- package/dist/package/entity/order-platform/external/setting/external-setting.do.d.ts +21 -3
- package/dist/package/entity/order-platform/external/setting/external-setting.dto.d.ts +12 -2
- package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.do.d.ts +3 -0
- package/dist/package/entity/order-platform/foodpanda/foodpanda-settings.dto.d.ts +3 -0
- package/dist/package/entity/order-platform/grabfood/grabfood-edit-order.do.d.ts +9 -1
- package/dist/package/entity/order-platform/grabfood/grabfood-settings.do.d.ts +2 -2
- package/dist/package/entity/order-platform/grabfood/grabfood.dto.d.ts +3 -3
- package/dist/package/entity/order-platform/order-platform.dto.d.ts +2 -2
- package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.do.d.ts +3 -0
- package/dist/package/entity/order-platform/shopeefood/shopeefood-settings.dto.d.ts +3 -0
- package/dist/package/entity/order-setting/order-setting.do.d.ts +864 -0
- package/dist/package/entity/order-setting/order-setting.dto.d.ts +6 -0
- package/dist/package/entity/order-setting/reservationV2/reservation.do.d.ts +1269 -0
- package/dist/package/entity/queue/queue.do.d.ts +3 -8
- package/dist/package/entity/queue/queue.dto.d.ts +10 -0
- package/dist/package/entity/reservation/reservation.do.d.ts +105 -0
- package/dist/package/entity/reservation/reservation.dto.d.ts +335 -0
- package/dist/package/entity/reservation/reservation.enum.d.ts +3 -0
- package/dist/package/entity/reservation/reservation.utils.d.ts +152 -0
- package/dist/style.css +1 -0
- package/package.json +1 -1
- package/src/api/reservation/index.ts +28 -0
- package/src/assets/images/not-found.png +0 -0
- package/src/locales/en-US.json +56 -0
- package/src/locales/th-TH.json +54 -0
- package/src/locales/zh-CN.json +54 -0
- package/src/views/kiosk/KioskSummary.vue +3 -0
- package/src/views/kiosk/settings/KioskPaymentTypeSection.vue +99 -211
- package/src/views/kiosk/settings/KioskSettingView.vue +43 -25
- package/src/views/order-settings/OrderSettingsView.vue +6 -1
- package/src/views/order-settings/dine-in/DineInSetting.vue +1 -0
- package/src/views/order-settings/dine-in/OfflinePaymentTypeDialog.vue +2 -3
- package/src/views/order-settings/dine-in/PaymentType.vue +151 -43
- package/src/views/order-settings/pickup/PaymentSidesheet.vue +33 -172
- package/src/views/order-settings/pickup/PickUpSettingDialogContent.vue +1 -0
- package/src/views/order-settings/reservation/CopySettingsSheet.vue +256 -0
- package/src/views/order-settings/reservation/CustomSelect.vue +99 -0
- package/src/views/order-settings/reservation/CustomTimePicker.vue +311 -0
- package/src/views/order-settings/reservation/ReservationSetting.vue +1555 -0
- package/tsconfig.app.json +8 -6
- package/dist/KioskSettingView-BE_pMA-i.js +0 -720
- package/dist/OrderSettingsView-BWzaITT6.js +0 -51916
- package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +0 -1
- package/dist/index-BXsnV_eO.js +0 -150
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
modelValue: string
|
|
6
|
+
minTime?: string // Optional minimum time (HH:MM format)
|
|
7
|
+
restrictMinTime?: boolean
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const emit = defineEmits<{
|
|
11
|
+
(e: 'update:modelValue', value: string): void
|
|
12
|
+
}>()
|
|
13
|
+
|
|
14
|
+
const isOpen = ref(false)
|
|
15
|
+
const wrapperRef = ref<HTMLDivElement | null>(null)
|
|
16
|
+
const inputRef = ref<HTMLInputElement | null>(null)
|
|
17
|
+
const dropdownRef = ref<HTMLDivElement | null>(null)
|
|
18
|
+
|
|
19
|
+
// Generate time options in 30-minute intervals
|
|
20
|
+
const timeOptions = computed(() => {
|
|
21
|
+
const options: string[] = []
|
|
22
|
+
for (let hour = 0; hour < 24; hour++) {
|
|
23
|
+
for (let minute = 0; minute < 60; minute += 30) {
|
|
24
|
+
const timeString = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`
|
|
25
|
+
options.push(timeString)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
options.push('23:59')
|
|
30
|
+
|
|
31
|
+
// Filter out times earlier than minTime if provided
|
|
32
|
+
if (props.minTime && props.restrictMinTime !== false) {
|
|
33
|
+
return options.filter((time) => isTimeGreaterOrEqual(time, props.minTime!))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return options
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Helper function to compare times in HH:MM format
|
|
40
|
+
function isTimeGreaterOrEqual(time1: string, time2: string): boolean {
|
|
41
|
+
const [hours1, minutes1] = time1.split(':').map(Number)
|
|
42
|
+
const [hours2, minutes2] = time2.split(':').map(Number)
|
|
43
|
+
|
|
44
|
+
const totalMinutes1 = hours1 * 60 + minutes1
|
|
45
|
+
const totalMinutes2 = hours2 * 60 + minutes2
|
|
46
|
+
|
|
47
|
+
return totalMinutes1 >= totalMinutes2
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const displayValue = computed({
|
|
51
|
+
get: () => props.modelValue || '',
|
|
52
|
+
set: (value: string) => {
|
|
53
|
+
emit('update:modelValue', value)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
function selectTime(time: string) {
|
|
58
|
+
displayValue.value = time
|
|
59
|
+
isOpen.value = false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function handleClickOutside(event: MouseEvent) {
|
|
63
|
+
const target = event.target as Node
|
|
64
|
+
const wrapperElement = wrapperRef.value
|
|
65
|
+
|
|
66
|
+
if (
|
|
67
|
+
dropdownRef.value &&
|
|
68
|
+
wrapperElement &&
|
|
69
|
+
!dropdownRef.value.contains(target) &&
|
|
70
|
+
!wrapperElement.contains(target)
|
|
71
|
+
) {
|
|
72
|
+
isOpen.value = false
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function handleFocus() {
|
|
77
|
+
isOpen.value = true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function toggleDropdown(event?: Event) {
|
|
81
|
+
event?.stopPropagation()
|
|
82
|
+
const willOpen = !isOpen.value
|
|
83
|
+
|
|
84
|
+
// Close all other open dropdowns by dispatching a global event
|
|
85
|
+
if (willOpen) {
|
|
86
|
+
window.dispatchEvent(new CustomEvent('closeTimePickers'))
|
|
87
|
+
}
|
|
88
|
+
isOpen.value = willOpen
|
|
89
|
+
|
|
90
|
+
// Scroll to selected time when opening
|
|
91
|
+
if (willOpen) {
|
|
92
|
+
nextTick(() => {
|
|
93
|
+
inputRef.value?.focus()
|
|
94
|
+
scrollToSelectedTime()
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function scrollToSelectedTime() {
|
|
100
|
+
const scrollContainer = dropdownRef.value?.querySelector('.overflow-y-auto')
|
|
101
|
+
if (!scrollContainer) return
|
|
102
|
+
|
|
103
|
+
const selectedElement = scrollContainer.querySelector(
|
|
104
|
+
'[data-selected="true"]'
|
|
105
|
+
) as HTMLElement | null
|
|
106
|
+
if (selectedElement) {
|
|
107
|
+
const container = scrollContainer as HTMLElement
|
|
108
|
+
const targetScrollTop =
|
|
109
|
+
selectedElement.offsetTop - container.clientHeight / 2 + selectedElement.clientHeight / 2
|
|
110
|
+
container.scrollTop = Math.max(0, targetScrollTop)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function formatTimeInput(value: string) {
|
|
115
|
+
const digits = value.replace(/\D/g, '').slice(0, 4)
|
|
116
|
+
|
|
117
|
+
if (!digits) {
|
|
118
|
+
return ''
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let hours = digits.slice(0, 2)
|
|
122
|
+
let minutes = digits.slice(2, 4)
|
|
123
|
+
|
|
124
|
+
if (hours.length === 2) {
|
|
125
|
+
hours = String(Math.min(Number(hours), 23)).padStart(2, '0')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (minutes.length === 1) {
|
|
129
|
+
minutes = String(Math.min(Number(minutes), 5))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (minutes.length === 2) {
|
|
133
|
+
minutes = String(Math.min(Number(minutes), 59)).padStart(2, '0')
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (digits.length <= 2) {
|
|
137
|
+
return digits.length === 2 ? `${hours}:` : hours
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return `${hours}:${minutes}`
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function hasSelection(input: HTMLInputElement) {
|
|
144
|
+
return (input.selectionStart ?? 0) !== (input.selectionEnd ?? 0)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
148
|
+
if (event.ctrlKey || event.metaKey || event.altKey) {
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const allowedKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End']
|
|
153
|
+
if (allowedKeys.includes(event.key)) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!/^\d$/.test(event.key)) {
|
|
158
|
+
event.preventDefault()
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const input = event.target as HTMLInputElement | null
|
|
163
|
+
if (!input) {
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const digitCount = input.value.replace(/\D/g, '').length
|
|
168
|
+
if (digitCount >= 4 && !hasSelection(input)) {
|
|
169
|
+
event.preventDefault()
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function handleInput(event: Event) {
|
|
174
|
+
const input = event.target as HTMLInputElement | null
|
|
175
|
+
if (!input) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const formattedValue = formatTimeInput(input.value)
|
|
180
|
+
input.value = formattedValue
|
|
181
|
+
displayValue.value = formattedValue
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function handlePaste(event: ClipboardEvent) {
|
|
185
|
+
event.preventDefault()
|
|
186
|
+
|
|
187
|
+
const pastedText = event.clipboardData?.getData('text') || ''
|
|
188
|
+
const formattedValue = formatTimeInput(pastedText)
|
|
189
|
+
|
|
190
|
+
displayValue.value = formattedValue
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function focusInput() {
|
|
194
|
+
inputRef.value?.focus()
|
|
195
|
+
isOpen.value = true
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function handleCloseTimePickers() {
|
|
199
|
+
isOpen.value = false
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
onMounted(() => {
|
|
203
|
+
document.addEventListener('click', handleClickOutside)
|
|
204
|
+
window.addEventListener('closeTimePickers', handleCloseTimePickers)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
onUnmounted(() => {
|
|
208
|
+
document.removeEventListener('click', handleClickOutside)
|
|
209
|
+
window.removeEventListener('closeTimePickers', handleCloseTimePickers)
|
|
210
|
+
})
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
<template>
|
|
214
|
+
<div class="relative">
|
|
215
|
+
<div ref="wrapperRef" @click="focusInput" class="relative inline-flex w-[132px] max-w-full">
|
|
216
|
+
<input
|
|
217
|
+
ref="inputRef"
|
|
218
|
+
:value="displayValue"
|
|
219
|
+
@input="handleInput"
|
|
220
|
+
@keydown="handleKeydown"
|
|
221
|
+
@paste="handlePaste"
|
|
222
|
+
@focus="handleFocus"
|
|
223
|
+
placeholder="HH:MM"
|
|
224
|
+
class="time-picker-field"
|
|
225
|
+
maxlength="5"
|
|
226
|
+
inputmode="numeric"
|
|
227
|
+
autocomplete="off"
|
|
228
|
+
/>
|
|
229
|
+
<button
|
|
230
|
+
type="button"
|
|
231
|
+
@click.stop="toggleDropdown"
|
|
232
|
+
class="absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500 hover:text-gray-700"
|
|
233
|
+
>
|
|
234
|
+
<FmIcon
|
|
235
|
+
class="text-[18px] transition-all duration-200"
|
|
236
|
+
name="chevron_right"
|
|
237
|
+
:class="{ 'rotate-[-90deg]': isOpen, 'rotate-[90deg]': !isOpen }"
|
|
238
|
+
/>
|
|
239
|
+
</button>
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<div
|
|
243
|
+
v-if="isOpen"
|
|
244
|
+
ref="dropdownRef"
|
|
245
|
+
class="absolute z-50 w-full mt-2 bg-white border border-gray-200 rounded-md shadow-lg max-h-[240px] overflow-hidden"
|
|
246
|
+
>
|
|
247
|
+
<div class="max-h-[240px] overflow-y-auto scrollbar-thin">
|
|
248
|
+
<div
|
|
249
|
+
v-for="time in timeOptions"
|
|
250
|
+
:key="time"
|
|
251
|
+
@click.stop="selectTime(time)"
|
|
252
|
+
:data-selected="time === displayValue"
|
|
253
|
+
class="px-3 py-2 text-sm cursor-pointer transition-colors hover:bg-gray-50"
|
|
254
|
+
:class="{
|
|
255
|
+
'bg-orange-50 text-orange-600 font-medium': time === displayValue
|
|
256
|
+
}"
|
|
257
|
+
>
|
|
258
|
+
{{ time }}
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
</template>
|
|
264
|
+
|
|
265
|
+
<style scoped>
|
|
266
|
+
/* Custom scrollbar for dropdown - target the scrollable container */
|
|
267
|
+
.scrollbar-thin::-webkit-scrollbar {
|
|
268
|
+
width: 6px;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.scrollbar-thin::-webkit-scrollbar-track {
|
|
272
|
+
background: transparent;
|
|
273
|
+
border-radius: 3px;
|
|
274
|
+
margin: 4px 0;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.scrollbar-thin::-webkit-scrollbar-thumb {
|
|
278
|
+
background: #d1d5db;
|
|
279
|
+
border-radius: 3px;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.scrollbar-thin::-webkit-scrollbar-thumb:hover {
|
|
283
|
+
background: #9ca3af;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.time-picker-field {
|
|
287
|
+
width: 100%;
|
|
288
|
+
height: 40px;
|
|
289
|
+
border-width: 1.5px;
|
|
290
|
+
border-style: solid;
|
|
291
|
+
border-color: rgb(209 213 219);
|
|
292
|
+
border-radius: 0.625rem;
|
|
293
|
+
padding: 8px 36px 8px 12px;
|
|
294
|
+
font-size: 0.95rem;
|
|
295
|
+
line-height: 1.25rem;
|
|
296
|
+
font-weight: 500;
|
|
297
|
+
transition: all 0.2s;
|
|
298
|
+
background-color: white;
|
|
299
|
+
outline: none;
|
|
300
|
+
box-sizing: border-box;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.time-picker-field:hover {
|
|
304
|
+
border-color: rgb(156 163 175);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.time-picker-field:focus {
|
|
308
|
+
border-color: rgb(249 115 22) !important;
|
|
309
|
+
background-color: rgb(255 247 237) !important;
|
|
310
|
+
}
|
|
311
|
+
</style>
|