jws-frontend/src/components/shared/select/select.ts
2024-12-23 12:11:23 +07:00

97 lines
2.6 KiB
TypeScript

import { QSelect } from 'quasar';
import { Ref, watch } from 'vue';
export type SelectProps<T extends (...args: any[]) => any> = {
params?: Parameters<T>[0];
creatable?: boolean;
creatableDisabled?: boolean;
creatableDisabledText?: string;
label?: string;
placeholder?: string;
readonly?: boolean;
required?: boolean;
disabled?: boolean;
clearable?: boolean;
autoSelectOnSingle?: boolean;
};
export const createSelect = <T extends Record<string, any>>(
state: {
value: Ref<string | null | undefined>;
valueOption: Ref<T | undefined>;
selectOptions: Ref<T[]>;
getByValue: (id: string) => Promise<T | void> | T | void;
getList: (query?: string) => Promise<T[] | void> | 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) => {
if (!v || (cache && cache.find((opt) => opt[valueField] === v))) 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;
}
getSelectedOption();
}
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;
if (valueOption.value && valueOption.value[valueField] === currentValue) {
return selectOptions.value.unshift(valueOption.value);
}
const ret = await getByValue(currentValue);
if (ret) {
selectOptions.value.unshift(ret);
valueOption.value = ret;
}
}
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 };
};