clqms-shadcn-v1/src/lib/components/composable/use-form-option.svelte.js
2026-03-31 18:14:03 +07:00

130 lines
3.6 KiB
JavaScript

const optionsMode = {
default: async (field, selectOptions, loadingOptions) => {
if (selectOptions[field.key]?.length > 0) return;
loadingOptions[field.key] = true;
try {
const res = await fetch(field.optionsEndpoint);
const json = await res.json();
// selectOptions[field.key] = json?.data ?? [];
const data = json?.data ?? [];
const valueKey = field.valueKey ?? 'value';
const labelKey = field.labelKey ?? 'label';
selectOptions[field.key] = data.map((item) => {
const baseOption = {
value: item[valueKey],
label: typeof labelKey === 'function' ? labelKey(item) : item[labelKey],
};
if (field.key === 'FormulaInput') {
return {
...baseOption,
testid: item.TestSiteID,
level: item.isCountStat,
};
}
return baseOption;
});
} catch (err) {
console.error("Failed to fetch options for", field.key, err);
selectOptions[field.key] = [];
} finally {
loadingOptions[field.key] = false;
}
},
cascade: async (field, selectOptions, loadingOptions, form, lastFetched) => {
const parentValue = field.dependsOn ? form?.[field.dependsOn] : null;
// console.log(parentValue);
// If has dependency and parent changed, or not fetched yet
if (field.dependsOn) {
// If parent value exists and already fetched for this parent value, skip
if (selectOptions[field.key]?.length > 0 &&
lastFetched[field.key] === parentValue) {
return;
}
// If no parent value, clear options
if (!parentValue) {
selectOptions[field.key] = [];
return;
}
} else {
// Non-dependent field, only fetch once
if (selectOptions[field.key]?.length > 0) return;
}
let endpoint = field.optionsEndpoint;
// Add parent parameter if exists
if (parentValue && field.endpointParamKey) {
endpoint += `?${field.endpointParamKey}=${parentValue}`;
}
loadingOptions[field.key] = true;
try {
const res = await fetch(endpoint);
const json = await res.json();
// selectOptions[field.key] = json?.data ?? [];
const data = json?.data ?? [];
const valueKey = field.valueKey ?? 'value';
const labelKey = field.labelKey ?? 'label';
selectOptions[field.key] = data.map((item) => ({
value: item[valueKey],
label: typeof labelKey === 'function' ? labelKey(item) : item[labelKey],
}));
// Track last fetched parent value for dependent fields
if (field.dependsOn) {
lastFetched[field.key] = parentValue;
}
} catch (err) {
console.error("Failed to fetch options for", field.key, err);
selectOptions[field.key] = [];
} finally {
loadingOptions[field.key] = false;
}
}
};
export function useFormOptions(optMode = 'default') {
const selectOptions = $state({});
const loadingOptions = $state({});
const lastFetched = $state({});
async function fetchOptions(field, form = null) {
if (!field?.optionsEndpoint) return;
const modeFn = optionsMode[optMode];
if (!modeFn) return;
await modeFn(field, selectOptions, loadingOptions, form, lastFetched);
}
function clearDependentOptions(parentKey, dependentKeys, form) {
dependentKeys.forEach(key => {
selectOptions[key] = [];
if (form) form[key] = '';
lastFetched[key] = null;
});
}
return {
selectOptions,
loadingOptions,
lastFetched,
fetchOptions,
clearDependentOptions,
};
}