diff --git a/src/components/shared/select-muliple/SelectOffice.vue b/src/components/shared/select-muliple/SelectOffice.vue
new file mode 100644
index 00000000..24437cd1
--- /dev/null
+++ b/src/components/shared/select-muliple/SelectOffice.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+ {{ $t('general.add', { text: $t('quotation.newCustomer') }) }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/shared/select-muliple/select-multiple.ts b/src/components/shared/select-muliple/select-multiple.ts
new file mode 100644
index 00000000..f1f31bf7
--- /dev/null
+++ b/src/components/shared/select-muliple/select-multiple.ts
@@ -0,0 +1,110 @@
+import { QSelect } from 'quasar';
+import { ref, Ref, watch } from 'vue';
+
+export type SelectProps any> = {
+ params?: Parameters[0];
+ creatable?: boolean;
+ label?: string;
+ placeholder?: string;
+ readonly?: boolean;
+ required?: boolean;
+ disabled?: boolean;
+ clearable?: boolean;
+ autoSelectOnSingle?: boolean;
+};
+
+export const createSelect = >(
+ state: {
+ value: Ref;
+ valueOption: Ref;
+ selectOptions: Ref;
+ getByValue: (id: string) => Promise | T | void;
+ getList: (query?: string) => Promise | T[] | void;
+ },
+ opts?: {
+ valueField?: keyof T;
+ },
+) => {
+ const { value, valueOption, selectOptions, getList, getByValue } = state;
+
+ const valueField = opts?.valueField || 'value';
+
+ let cache: T[];
+ let previousSearch = '';
+
+ watch(value, (v) => {
+ console.log('UPDATED');
+ if (
+ !v ||
+ (cache && cache.find((opt) => v.find((val) => val === opt[valueField])))
+ ) {
+ return;
+ }
+ getSelectedOption();
+ });
+
+ async function getOptions(query?: string) {
+ if (cache && selectOptions.value.length > 0 && previousSearch === query) {
+ selectOptions.value = JSON.parse(JSON.stringify(cache));
+ return;
+ }
+ const ret = await getList(query);
+ if (ret) {
+ cache = ret;
+ selectOptions.value = JSON.parse(JSON.stringify(cache));
+ previousSearch = query || previousSearch;
+ }
+ }
+
+ async function setFirstValue() {
+ if (value.value) return;
+ const first = selectOptions.value.at(0);
+ if (first) value.value = first[valueField];
+ }
+
+ async function getSelectedOption() {
+ const currentValue = value.value;
+
+ if (!currentValue) return;
+ if (selectOptions.value.find((v) => v[valueField] === currentValue)) return;
+
+ const newValueOptions = currentValue.map(async (a) => {
+ const findValue = valueOption.value?.find((b) => b[valueField] === a);
+
+ if (findValue) {
+ selectOptions.value.unshift(findValue);
+ return findValue;
+ }
+
+ const ret = await getByValue(a);
+
+ if (ret) {
+ selectOptions.value.unshift(ret);
+ return ret;
+ }
+ });
+
+ const retValueOptions = await Promise.all(newValueOptions);
+
+ valueOption.value = retValueOptions.flatMap((v) => (!!v ? v : []));
+ }
+
+ type QuasarSelectUpdate = (
+ callback: () => void,
+ afterFn?: ((ref: QSelect) => void) | undefined,
+ ) => void;
+
+ function filter(value: string, update: QuasarSelectUpdate) {
+ update(
+ () => getOptions(value),
+ (ref) => {
+ if (!!value && ref.options && ref.options.length > 0) {
+ ref.setOptionIndex(-1);
+ ref.moveOptionSelection(1, true);
+ }
+ },
+ );
+ }
+
+ return { getOptions, setFirstValue, getSelectedOption, filter };
+};