diff --git a/public/mobile/modules/lager/shippingnote/SearchSelectModal.js b/public/mobile/modules/lager/shippingnote/SearchSelectModal.js new file mode 100644 index 000000000..ecb8c9a17 --- /dev/null +++ b/public/mobile/modules/lager/shippingnote/SearchSelectModal.js @@ -0,0 +1,254 @@ +/** + * SearchSelectModal Component + * + * Reusable bottom sheet modal for searching and selecting items. + * Works correctly with iPhone Dynamic Island by using bottom sheet pattern. + * + * Usage: + * + * + * + */ + +export default { + name: 'SearchSelectModal', + emits: ['select', 'close', 'update:modelValue'], + props: { + show: { + type: Boolean, + default: false + }, + title: { + type: String, + default: 'Auswählen' + }, + searchable: { + type: Boolean, + default: false + }, + searchPlaceholder: { + type: String, + default: 'Suchen...' + }, + modelValue: { + type: String, + default: '' + }, + items: { + type: Array, + default: () => [] + }, + loading: { + type: Boolean, + default: false + }, + emptyText: { + type: String, + default: 'Keine Ergebnisse gefunden' + }, + emptyIcon: { + type: String, + default: 'search' // search, users, box, list + }, + selectedId: { + type: [String, Number], + default: null + }, + itemKey: { + type: String, + default: 'id' + }, + showNoneOption: { + type: Boolean, + default: false + }, + noneOptionText: { + type: String, + default: 'Keine Auswahl' + } + }, + + setup(props, { emit, slots }) { + const { ref, computed, watch } = Vue; + + const searchInput = ref(null); + + // Focus search input when modal opens + watch(() => props.show, (newVal) => { + if (newVal && props.searchable) { + setTimeout(() => { + searchInput.value?.focus(); + }, 100); + } + }); + + const updateSearch = (event) => { + emit('update:modelValue', event.target.value); + }; + + const selectItem = (item) => { + emit('select', item); + }; + + const selectNone = () => { + emit('select', null); + }; + + const close = () => { + emit('close'); + }; + + const isSelected = (item) => { + if (props.selectedId === null || props.selectedId === undefined) return false; + return item[props.itemKey] === props.selectedId; + }; + + // Icons for empty states + const emptyIcons = { + search: ``, + users: ``, + box: ``, + list: `` + }; + + const getEmptyIcon = computed(() => { + return emptyIcons[props.emptyIcon] || emptyIcons.search; + }); + + return { + searchInput, + updateSearch, + selectItem, + selectNone, + close, + isSelected, + getEmptyIcon + }; + }, + + template: ` + + +
+ +
+ + + +
+ +
+
+
+ + +
+

+ {{ title }} +

+
+ + +
+
+ + + + +
+
+ + +
+ +
+
+
+ + +
+ +

{{ emptyText }}

+
+ + +
+ + + + + +
+
+ + +
+
+
+
+
+
+ ` +}; diff --git a/public/mobile/modules/lager/shippingnote/ShippingNoteForm.js b/public/mobile/modules/lager/shippingnote/ShippingNoteForm.js index ad884ca5f..c0735ea9a 100644 --- a/public/mobile/modules/lager/shippingnote/ShippingNoteForm.js +++ b/public/mobile/modules/lager/shippingnote/ShippingNoteForm.js @@ -11,6 +11,7 @@ import { shippingNoteApi } from '/mobile/modules/lager/shippingnote/ShippingNoteModule.js'; import DatePicker from '/mobile/modules/lager/shippingnote/DatePicker.js'; import EmployeeSelector from '/mobile/modules/lager/shippingnote/EmployeeSelector.js'; +import SearchSelectModal from '/mobile/modules/lager/shippingnote/SearchSelectModal.js'; export default { name: 'ShippingNoteForm', @@ -20,7 +21,8 @@ export default { }, components: { DatePicker, - EmployeeSelector + EmployeeSelector, + SearchSelectModal }, setup(props, { emit }) { @@ -455,8 +457,8 @@ export default { const selectCar = (car) => { if (hoursEntries.value[carSelectEntryIndex.value]) { - hoursEntries.value[carSelectEntryIndex.value].carId = car.id; - hoursEntries.value[carSelectEntryIndex.value].carName = car.name; + hoursEntries.value[carSelectEntryIndex.value].carId = car?.id || null; + hoursEntries.value[carSelectEntryIndex.value].carName = car?.name || ''; } showCarSelect.value = false; navigator.vibrate?.([30]); @@ -951,114 +953,123 @@ export default { /> - - -
-
- -

Kunde suchen

-
-
- -
-
-
Suche...
-
Keine Kunden gefunden
-
- -
-
+ + + - - -
-
- -

Artikel suchen

-
-
- -
-
-
Suche...
-
Keine Artikel gefunden
-
- -
-
+ + + - - -
-
- -

Fahrzeug wählen

-
-
- - -
+ + + - - -
-
- -

Stundenart wählen

-
-
- -
+ + +
` };