@feedmepos/mf-order-setting 0.0.52-dev.0 → 0.0.52-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.
@@ -3121,7 +3121,7 @@ const E = { class: "flex-1 overflow-auto" }, H = /* @__PURE__ */ b({
3121
3121
  {
3122
3122
  path: u.OrderSettingView,
3123
3123
  name: "Order Setting View",
3124
- component: () => import("./OrderSettingsView-C4aEpC1j.js")
3124
+ component: () => import("./OrderSettingsView-DYWlafIW.js")
3125
3125
  }
3126
3126
  ], j = {
3127
3127
  "en-US": C,
package/dist/app.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as a, i as e, r as o } from "./app-CwYXsqxX.js";
1
+ import { _ as a, i as e, r as o } from "./app-DDFI8Stx.js";
2
2
  export {
3
3
  a as FmApp,
4
4
  e as i18nMessages,
@@ -1,6 +1,7 @@
1
1
  type __VLS_Props = {
2
2
  modelValue: string;
3
3
  minTime?: string;
4
+ isEndTime?: boolean;
4
5
  };
5
6
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
7
  "update:modelValue": (value: string) => any;
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .scrollbar-thin[data-v-fc459980]::-webkit-scrollbar{width:6px}.scrollbar-thin[data-v-fc459980]::-webkit-scrollbar-track{background:transparent;border-radius:3px;margin:4px 0}.scrollbar-thin[data-v-fc459980]::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:3px}.scrollbar-thin[data-v-fc459980]::-webkit-scrollbar-thumb:hover{background:#9ca3af}.time-picker-field[data-v-fc459980] .fm-text-field-input{border-width:2px;border-radius:.75rem;padding:12px 16px;font-size:1.125rem;transition:all .2s}.time-picker-field[data-v-fc459980] .fm-text-field-input:not(:focus):not(:focus-within){border-color:#d1d5db;background-color:#fff}.time-picker-field[data-v-fc459980] .fm-text-field-input:not(:focus):not(:focus-within):hover{border-color:#9ca3af}.time-picker-field.focused[data-v-fc459980] .fm-text-field-input,.time-picker-field[data-v-fc459980] .fm-text-field-input:focus,.time-picker-field[data-v-fc459980] .fm-text-field-input:focus-within{border-color:#f97316!important;background-color:#fff7ed!important}.fm-text-field-input[data-v-6a4bdab2]{font-size:1.125rem;line-height:1.75rem}
1
+ .scrollbar-thin[data-v-cf197fa9]::-webkit-scrollbar{width:6px}.scrollbar-thin[data-v-cf197fa9]::-webkit-scrollbar-track{background:transparent;border-radius:3px;margin:4px 0}.scrollbar-thin[data-v-cf197fa9]::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:3px}.scrollbar-thin[data-v-cf197fa9]::-webkit-scrollbar-thumb:hover{background:#9ca3af}.time-picker-field[data-v-cf197fa9] .fm-text-field-input{width:140px!important;border-width:2px;border-radius:.75rem;padding:12px 16px;font-size:1.125rem;transition:all .2s}.time-picker-field[data-v-cf197fa9] .fm-text-field-input:not(:focus):not(:focus-within){border-color:#d1d5db;background-color:#fff}.time-picker-field[data-v-cf197fa9] .fm-text-field-input:not(:focus):not(:focus-within):hover{border-color:#9ca3af}.time-picker-field.focused[data-v-cf197fa9] .fm-text-field-input,.time-picker-field[data-v-cf197fa9] .fm-text-field-input:focus,.time-picker-field[data-v-cf197fa9] .fm-text-field-input:focus-within{border-color:#f97316!important;background-color:#fff7ed!important}.fm-text-field-input[data-v-6a4bdab2]{font-size:1.125rem;line-height:1.75rem}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feedmepos/mf-order-setting",
3
- "version": "0.0.52-dev.0",
3
+ "version": "0.0.52-dev.2",
4
4
  "type": "module",
5
5
  "module": "./dist/app.js",
6
6
  "license": "UNLICENSED",
@@ -19,7 +19,7 @@
19
19
  <div>
20
20
  <div class="fm-typo-en-title-sm-600 mb-16">Configuration</div>
21
21
 
22
- <div class="flex flex-col gap-12">
22
+ <div class="flex flex-col gap-12 pl-8">
23
23
  <!-- All Checkbox -->
24
24
  <FmCheckbox label="All" :model-value="isAllSelected" value="all" @update:model-value="toggleAll" />
25
25
 
@@ -52,9 +52,13 @@
52
52
  </template>
53
53
 
54
54
  <template #side-sheet-footer>
55
- <div class="flex items-center justify-start gap-8">
56
- <FmButton label="Apply" @click="handleApply" :disabled="!canApply" :loading="isLoading" />
57
- <FmButton label="Cancel" variant="tertiary" @click="handleCancel" />
55
+ <div class="flex flex-col gap-16 w-full">
56
+ <FmSnackbar variant="warning" class="!shadow-none"
57
+ :description="`This will overwrite all reservation settings for ${targetRestaurantName}`" />
58
+ <div class="flex items-center justify-start gap-8">
59
+ <FmButton label="Apply" @click="handleApply" :disabled="!canApply" :loading="isLoading" />
60
+ <FmButton label="Cancel" variant="tertiary" @click="handleCancel" />
61
+ </div>
58
62
  </div>
59
63
  </template>
60
64
  </FmSideSheet>
@@ -62,7 +66,7 @@
62
66
 
63
67
  <script setup lang="ts">
64
68
  import { useCoreStore, useI18n } from '@feedmepos/mf-common'
65
- import { computed, ref } from 'vue'
69
+ import { computed, ref, watch } from 'vue'
66
70
  import { ReservationApi } from '@/api/reservation'
67
71
  import { useSnackbarFunctions } from '@/components/snackbar'
68
72
  import type { FdoOrderReservationSettingsV2 } from '@entity'
@@ -105,8 +109,18 @@ const availableRestaurants = computed(() => {
105
109
  .map((r) => ({ label: r.profile.name, value: r._id }))
106
110
  })
107
111
 
108
- const selectedRestaurantId = ref<string>(availableRestaurants.value[0]?.value)
112
+ const selectedRestaurantId = ref<string>('')
109
113
 
114
+ // Watch to set initial value when availableRestaurants loads
115
+ watch(availableRestaurants, (newRestaurants) => {
116
+ if (newRestaurants.length > 0 && !selectedRestaurantId.value) {
117
+ selectedRestaurantId.value = newRestaurants[0].value
118
+ }
119
+ }, { immediate: true })
120
+
121
+ const targetRestaurantName = computed(() => {
122
+ return currentRestaurant.value?.profile.name ?? ''
123
+ })
110
124
 
111
125
  const isAllSelected = computed(() => {
112
126
  return Object.values(configOptions.value).every((v) => v === true)
@@ -205,6 +219,10 @@ async function handleApply() {
205
219
  // Emit the updated settings to parent
206
220
  emit('apply', updatedSettings)
207
221
 
222
+ // Show success with source outlet name
223
+ const sourceName = availableRestaurants.value.find(r => r.value === selectedRestaurantId.value)?.label ?? 'selected outlet'
224
+ showSuccess(`Settings from "${sourceName}" have been applied. Please review and save changes.`)
225
+
208
226
  // Close the side sheet
209
227
  showSheet.value = false
210
228
 
@@ -1,9 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, onMounted, onUnmounted } from 'vue'
2
+ import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
3
3
 
4
4
  const props = defineProps<{
5
5
  modelValue: string
6
6
  minTime?: string // Optional minimum time (HH:MM format)
7
+ isEndTime?: boolean // Whether this is an end time picker
7
8
  }>()
8
9
 
9
10
  const emit = defineEmits<{
@@ -23,6 +24,7 @@ const timeOptions = computed(() => {
23
24
  options.push(timeString)
24
25
  }
25
26
  }
27
+
26
28
  options.push('23:59')
27
29
 
28
30
  // Filter out times earlier than minTime if provided
@@ -76,7 +78,28 @@ function handleFocus() {
76
78
 
77
79
  function toggleDropdown(event?: Event) {
78
80
  event?.stopPropagation()
81
+ // Close all other open dropdowns by dispatching a global event
82
+ if (!isOpen.value) {
83
+ window.dispatchEvent(new CustomEvent('closeTimePickers'))
84
+ }
79
85
  isOpen.value = !isOpen.value
86
+
87
+ // Scroll to selected time when opening
88
+ if (isOpen.value) {
89
+ nextTick(() => {
90
+ scrollToSelectedTime()
91
+ })
92
+ }
93
+ }
94
+
95
+ function scrollToSelectedTime() {
96
+ const scrollContainer = dropdownRef.value?.querySelector('.overflow-y-auto')
97
+ if (!scrollContainer) return
98
+
99
+ const selectedElement = scrollContainer.querySelector('[data-selected="true"]')
100
+ if (selectedElement) {
101
+ selectedElement.scrollIntoView({ block: 'center' })
102
+ }
80
103
  }
81
104
 
82
105
  function handleInputValue(value: string) {
@@ -97,10 +120,16 @@ function handleInputValue(value: string) {
97
120
 
98
121
  onMounted(() => {
99
122
  document.addEventListener('click', handleClickOutside)
123
+ window.addEventListener('closeTimePickers', () => {
124
+ isOpen.value = false
125
+ })
100
126
  })
101
127
 
102
128
  onUnmounted(() => {
103
129
  document.removeEventListener('click', handleClickOutside)
130
+ window.removeEventListener('closeTimePickers', () => {
131
+ isOpen.value = false
132
+ })
104
133
  })
105
134
  </script>
106
135
 
@@ -137,6 +166,7 @@ onUnmounted(() => {
137
166
  v-for="time in timeOptions"
138
167
  :key="time"
139
168
  @click.stop="selectTime(time)"
169
+ :data-selected="time === displayValue"
140
170
  class="px-3 py-2 text-sm cursor-pointer transition-colors hover:bg-gray-50"
141
171
  :class="{
142
172
  'bg-orange-50 text-orange-600 font-medium': time === displayValue
@@ -172,6 +202,7 @@ onUnmounted(() => {
172
202
 
173
203
  /* Override FmTextField styling for orange theme */
174
204
  .time-picker-field :deep(.fm-text-field-input) {
205
+ width: 140px !important;
175
206
  border-width: 2px;
176
207
  border-radius: 0.75rem;
177
208
  padding: 12px 16px;
@@ -25,10 +25,22 @@ import notfound from '@/assets/images/not-found.png'
25
25
 
26
26
  const { t } = useI18n()
27
27
  const { showSuccess } = useSnackbarFunctions()
28
- const { currentRestaurant } = useCoreStore()
28
+ const { currentRestaurant, restaurants } = useCoreStore()
29
29
  const { isLoading, startAsyncCallWithErr } = useLoading()
30
30
  const dialog = useDialog()
31
31
 
32
+ // Check if multi-outlet
33
+ const isMultiOutlet = computed(() => (restaurants.value?.length ?? 0) > 1)
34
+
35
+ // Helper function to generate unique IDs and names for reservation ranges
36
+ const generateRangeDefaults = (index = 0) => ({
37
+ _id: new Date().toISOString() + '-' + index, // Add index to ensure uniqueness
38
+ name: `Dining Area ${index + 1}`
39
+ })
40
+
41
+ // Helper function to generate unique capacity tier ID
42
+ const generateCapacityTierId = () => new Date().toISOString() + '-' + Math.random().toString(36).substr(2, 9)
43
+
32
44
  const DEFAULT_GUEST_MESSAGE = `Please take note of the following important details before making a reservation:
33
45
 
34
46
  1. Dining Time Limit
@@ -44,9 +56,9 @@ Free cancellation up to 24 hours before your reservation. Please contact the out
44
56
  const reservationSettings = ref<FdoOrderReservationSettingsV2>({
45
57
  ranges: [
46
58
  {
47
- _id: '',
59
+ ...generateRangeDefaults(0),
48
60
  enable: false,
49
- bookingDuration: 60,
61
+ bookingDuration: 90,
50
62
  enablePreorder: true,
51
63
  minLeadDuration: {
52
64
  value: 0,
@@ -56,7 +68,6 @@ const reservationSettings = ref<FdoOrderReservationSettingsV2>({
56
68
  value: 30,
57
69
  unit: 'day'
58
70
  },
59
- name: '',
60
71
  operatingHours: {
61
72
  0: {
62
73
  enable: false,
@@ -103,9 +114,9 @@ const reservationSettings = ref<FdoOrderReservationSettingsV2>({
103
114
  })
104
115
 
105
116
  const rangeSetting = ref<FdoReservationRange>({
106
- _id: '',
107
- enable: true,
108
- bookingDuration: 60,
117
+ ...generateRangeDefaults(0),
118
+ enable: false,
119
+ bookingDuration: 90,
109
120
  enablePreorder: true,
110
121
  minLeadDuration: {
111
122
  value: 0,
@@ -115,7 +126,6 @@ const rangeSetting = ref<FdoReservationRange>({
115
126
  value: 30,
116
127
  unit: 'day'
117
128
  },
118
- name: '',
119
129
  operatingHours: {
120
130
  0: {
121
131
  enable: true,
@@ -164,25 +174,25 @@ const rangeSetting = ref<FdoReservationRange>({
164
174
  preferences: [],
165
175
  capacityTiers: [
166
176
  {
167
- _id: '1',
177
+ _id: generateCapacityTierId(),
168
178
  minPax: 1,
169
179
  maxPax: 2,
170
180
  capacity: 10
171
181
  },
172
182
  {
173
- _id: '2',
183
+ _id: generateCapacityTierId(),
174
184
  minPax: 3,
175
185
  maxPax: 4,
176
186
  capacity: 8
177
187
  },
178
188
  {
179
- _id: '3',
189
+ _id: generateCapacityTierId(),
180
190
  minPax: 5,
181
191
  maxPax: 6,
182
192
  capacity: 5
183
193
  },
184
194
  {
185
- _id: '4',
195
+ _id: generateCapacityTierId(),
186
196
  minPax: 7,
187
197
  maxPax: null,
188
198
  capacity: 3
@@ -533,7 +543,7 @@ function addPreference() {
533
543
  rangeSetting.value.preferences.push({
534
544
  name: '',
535
545
  type: 'radio',
536
- options: ['Option 1']
546
+ options: []
537
547
  })
538
548
  }
539
549
 
@@ -674,8 +684,6 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
674
684
 
675
685
  // Reset custom mode when copying settings - let computed property determine state
676
686
  isCustomMode.value = false
677
-
678
- showSuccess('Settings copied successfully. Please review and save changes.')
679
687
  }
680
688
  </script>
681
689
 
@@ -684,7 +692,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
684
692
  <div v-if="isLoading" class="flex justify-center items-center min-h-[400px]">
685
693
  <FmCircularProgress size="xxl" />
686
694
  </div>
687
- <div v-else class="p-[1.5rem] flex flex-col gap-24 w-full max-w-4xl">
695
+ <div v-else class="p-[1.5rem] flex flex-col gap-48 w-full max-w-4xl">
688
696
  <!-- <FmCard variant="outlined" class="p-5">
689
697
  <div class="mb-5">
690
698
  <FmSwitch
@@ -732,7 +740,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
732
740
  :sublabel="'Enable this to make the outlet available for reservations. This setting does not impact walk-in dining.'"
733
741
  :model-value="rangeSetting.enable ?? false" @update:model-value="(v: boolean) => (rangeSetting.enable = v)" />
734
742
 
735
- <div class="ml-56 my-8">
743
+ <div v-if="rangeSetting.enable && isMultiOutlet" class="ml-56 my-8">
736
744
  <CopySettingsSheet :current-settings="reservationSettings" @apply="handleCopySettings" />
737
745
  </div>
738
746
  </div>
@@ -745,10 +753,16 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
745
753
  </div>
746
754
  <FmCard variant="outlined" class="p-5">
747
755
  <div class="mb-5">
756
+ <div class="mb-8 fm-typo-en-body-md-600 flex items-center gap-8">
757
+ {{ t('order.draftHoldTimeMinutes') }}
758
+ <FmTooltip :content="'The amount of time a reservation is held before it is automatically released.'">
759
+ <FmIcon name="info" outline size="sm" class="cursor-pointer" />
760
+ </FmTooltip>
761
+ </div>
748
762
  <FmTextField type="number" :model-value="reservationSettings.draftHoldTimeMinutes" @update:model-value="
749
763
  (v: string | number) =>
750
764
  updateSetting('draftHoldTimeMinutes', v === '' ? 15 : Number(v))
751
- " :label="t('order.draftHoldTimeMinutes')" suffix="minutes" :hint="t('order.draftHoldTimeDescription')"
765
+ " suffix="minutes"
752
766
  class="max-w-md" />
753
767
  </div>
754
768
  <div class="mb-5">
@@ -860,11 +874,11 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
860
874
 
861
875
  <div class="flex flex-col">
862
876
  <div class="flex-grow fm-typo-en-title-sm-600 mb-4">
863
- {{ t('order.operatingWindows') }}
877
+ Time Settings
864
878
  </div>
865
879
  <div class="fm-typo-en-body-lg-400 text-fm-color-typo-secondary mb-12">
866
- Set the hours your outlet is open for business. Reservations and walk-ins outside these
867
- hours will not be allowed.
880
+ Choose the start and end time for reservations, and the interval between each time slot.
881
+ Available time slots will be generated automatically.
868
882
  </div>
869
883
 
870
884
  <!-- Operating hour setting -->
@@ -877,7 +891,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
877
891
  Open / Closed
878
892
  </div>
879
893
  <div class="p-12 fm-typo-en-body-md-600 text-fm-color-typo-secondary bg-fm-color-neutral-gray-100">
880
- Hours
894
+ Reservation Time Range
881
895
  </div>
882
896
  <template v-for="day in [1, 2, 3, 4, 5, 6, 0] as const" :key="day">
883
897
  <div class="fm-typo-en-body-md-400 py-12 px-12">
@@ -910,7 +924,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
910
924
  <CustomTimePicker v-model="hour.start" :min-time="hours.hours[hi - 1]?.end ?? '00:00'"
911
925
  class="grow" />
912
926
  <div class="text-center w-16 flex-shrink-0">to</div>
913
- <CustomTimePicker v-model="hour.end" :min-time="hour.start" class="grow" />
927
+ <CustomTimePicker v-model="hour.end" :min-time="hour.start" :is-end-time="true" class="grow" />
914
928
  </div>
915
929
  <div class="mr-8 w-32 flex-shrink">
916
930
  <FmButton variant="plain" icon="add" v-if="hi == 0" :disabled="hours.hours.length >= 2"
@@ -935,7 +949,12 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
935
949
  <FmCard variant="outlined" class="grid grid-cols-[1fr_2fr]">
936
950
  <div class="border-r py-[24px] px-16">
937
951
  <div class="mb-24">
938
- <div class="mb-8 fm-typo-en-body-lg-600">Time Interval</div>
952
+ <div class="mb-8 fm-typo-en-body-lg-600 flex items-center gap-8">
953
+ Time Interval
954
+ <FmTooltip :content="'How often guests can start a reservation'">
955
+ <FmIcon name="info" outline size="sm" class="cursor-pointer" />
956
+ </FmTooltip>
957
+ </div>
939
958
  <FmRadioGroup :model-value="rangeSetting.slotInterval"
940
959
  @update:model-value="(v: number) => updateSlotInterval(v)">
941
960
  <FmRadio label="15 min" :value="15" />
@@ -947,7 +966,12 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
947
966
  </div>
948
967
 
949
968
  <div class="mb-24">
950
- <div class="mb-8 fm-typo-en-body-lg-600">Dining Duration</div>
969
+ <div class="mb-8 fm-typo-en-body-lg-600 flex items-center gap-8">
970
+ Dining Duration
971
+ <FmTooltip :content="'How long a table is reserved for each booking'">
972
+ <FmIcon name="info" outline size="sm" class="cursor-pointer" />
973
+ </FmTooltip>
974
+ </div>
951
975
  <FmRadioGroup :model-value="rangeSetting.bookingDuration"
952
976
  @update:model-value="(v: number) => updateBookingDuration(v)">
953
977
  <FmRadio label="60 min" :value="60" />
@@ -975,7 +999,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
975
999
  </div>
976
1000
 
977
1001
  <template v-if="availableSlots.morning.length > 0">
978
- <div class="fm-typo-en-body-md-600">Morning</div>
1002
+ <div class="fm-typo-en-body-md-600 text-[#4B4B4B]">Morning</div>
979
1003
  <div class="grid grid-cols-5 gap-8">
980
1004
  <div v-for="slot in displayedSlots.morning" :key="slot.time"
981
1005
  class="border-1 rounded-md text-center p-8 transition-colors" :class="{
@@ -993,7 +1017,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
993
1017
  </template>
994
1018
 
995
1019
  <template v-if="availableSlots.afternoon.length > 0">
996
- <div class="fm-typo-en-body-md-600">Afternoon</div>
1020
+ <div class="fm-typo-en-body-md-600 text-[#4B4B4B]">Afternoon</div>
997
1021
  <div class="grid grid-cols-5 gap-8">
998
1022
  <div v-for="slot in displayedSlots.afternoon" :key="slot.time"
999
1023
  class="border-1 rounded-md text-center p-8 transition-colors" :class="{
@@ -1011,7 +1035,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
1011
1035
  </template>
1012
1036
 
1013
1037
  <template v-if="availableSlots.evening.length > 0">
1014
- <div class="fm-typo-en-body-md-600">Evening</div>
1038
+ <div class="fm-typo-en-body-md-600 text-[#4B4B4B]">Evening</div>
1015
1039
  <div class="grid grid-cols-5 gap-8">
1016
1040
  <div v-for="slot in displayedSlots.evening" :key="slot.time"
1017
1041
  class="border-1 rounded-md text-center p-8 transition-colors" :class="{
@@ -1042,10 +1066,10 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
1042
1066
 
1043
1067
  <div class="flex flex-col">
1044
1068
  <div class="flex-grow fm-typo-en-title-sm-600 mb-4">
1045
- {{ t('order.capacity') }}
1069
+ Table Capacity Settings
1046
1070
  </div>
1047
1071
  <div class="fm-typo-en-body-lg-400 text-fm-color-typo-secondary mb-24">
1048
- Set the maximum number of guests allowed for each time slot.
1072
+ Set how many tables are available for reservation per time slot. You can reduce availability to keep tables for walk-ins.
1049
1073
  </div>
1050
1074
 
1051
1075
  <!-- Table Capacity Settings -->
@@ -1053,21 +1077,26 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
1053
1077
  <div class="grid grid-cols-[4fr_4fr_4fr_1fr]">
1054
1078
  <div class="bg-fm-color-neutral-gray-100 p-12">Table Type</div>
1055
1079
  <div class="bg-fm-color-neutral-gray-100 p-12">Guest Range</div>
1056
- <div class="bg-fm-color-neutral-gray-100 p-12">Available Table Count</div>
1080
+ <div class="bg-fm-color-neutral-gray-100 p-12 flex items-center gap-4">
1081
+ Available Table Count
1082
+ <FmTooltip :content="'Adjust how many tables can be booked for each time slot'">
1083
+ <FmIcon name="info" outline size="sm" class="cursor-pointer" />
1084
+ </FmTooltip>
1085
+ </div>
1057
1086
  <div class="bg-fm-color-neutral-gray-100 p-12"></div>
1058
1087
  </div>
1059
1088
  <div class="grid grid-cols-[4fr_4fr_4fr_1fr] items-center gap-8" v-for="tier in rangeSetting.capacityTiers"
1060
1089
  :key="tier._id">
1061
1090
  <div class="p-8">{{ tier.minPax }}{{ tier.maxPax ? `-${tier.maxPax}` : '+' }} pax</div>
1062
1091
  <div class="flex items-center gap-4">
1063
- <FmStepperField v-model="tier.minPax" />
1092
+ <FmStepperField v-model="tier.minPax" :min="1" />
1064
1093
  <div>to</div>
1065
- <FmStepperField :model-value="tier.maxPax ?? null" @update:model-value="(v) => (tier.maxPax = v)" />
1094
+ <FmStepperField :model-value="tier.maxPax ?? null" @update:model-value="(v) => (tier.maxPax = v)" :min="tier.minPax" />
1066
1095
  </div>
1067
1096
  <div class="flex items-center gap-8">
1068
- <FmButton variant="tertiary" icon="remove" @click="tier.capacity--" :disabled="tier.capacity <= 1" />
1097
+ <FmButton variant="tertiary" icon="remove" @click="tier.capacity--" :disabled="tier.capacity <= 1" class="!rounded-full !w-10 !h-10 !bg-fm-color-neutral-gray-100" />
1069
1098
  <div class="w-32 text-center">{{ tier.capacity }}</div>
1070
- <FmButton variant="tertiary" icon="add" @click="tier.capacity++" />
1099
+ <FmButton variant="tertiary" icon="add" @click="tier.capacity++" class="!rounded-full !w-10 !h-10 !bg-fm-color-neutral-gray-100" />
1071
1100
 
1072
1101
  <!-- <FmStepperField :model-value="tier.capacity ?? null" @update:model-value="(v) => (tier.capacity = v)" /> -->
1073
1102
  </div>
@@ -1078,7 +1107,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
1078
1107
  <div>
1079
1108
  <FmButton label="Add table type" icon="add" variant="plain" @click="
1080
1109
  rangeSetting.capacityTiers.push({
1081
- _id: new Date().toISOString(),
1110
+ _id: generateCapacityTierId(),
1082
1111
  minPax: ([...rangeSetting.capacityTiers].pop()?.maxPax ?? 0) + 1,
1083
1112
  maxPax: null,
1084
1113
  capacity: 0
@@ -1111,7 +1140,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
1111
1140
  {
1112
1141
  name: '',
1113
1142
  type: 'radio',
1114
- options: ['Option 1']
1143
+ options: []
1115
1144
  }
1116
1145
  ]
1117
1146
  } else {
@@ -1125,7 +1154,7 @@ function handleCopySettings(copiedSettings: Partial<FdoOrderReservationSettingsV
1125
1154
  <div class="fm-typo-en-body-lg-600 mb-8">Category title</div>
1126
1155
  <div class="grid grid-cols-[6fr_3fr_1fr] items-start gap-24 mb-24">
1127
1156
  <div>
1128
- <FmTextField v-model="preference.name" />
1157
+ <FmTextField v-model="preference.name" placeholder="Enter a name" />
1129
1158
  <div class="fm-typo-en-body-md-400 text-fm-color-typo-tertiary mt-8">
1130
1159
  This title will be shown to guests during reservation.
1131
1160
  </div>