From c5d2aa6711f57213bcd4f3f5b5b206c15e2673bb Mon Sep 17 00:00:00 2001 From: faiztyanirh Date: Wed, 4 Mar 2026 15:32:57 +0700 Subject: [PATCH] add feature dynamic error multitab & continue dict test calc --- .../composable/use-dictionary-form.svelte.js | 26 +- .../test/config/test-form-config.js | 1 + .../dictionary/test/page/create-page.svelte | 36 +- .../form/dictionary-form-renderer.svelte | 1245 ++++++++--------- 4 files changed, 666 insertions(+), 642 deletions(-) diff --git a/src/lib/components/composable/use-dictionary-form.svelte.js b/src/lib/components/composable/use-dictionary-form.svelte.js index e5b8f7e..46d1931 100644 --- a/src/lib/components/composable/use-dictionary-form.svelte.js +++ b/src/lib/components/composable/use-dictionary-form.svelte.js @@ -1,10 +1,24 @@ -export function useDictionaryForm(formState) { - let uploadErrors = $state({}); - let isChecking = $state({}); +// export function useDictionaryForm(formState) { +// let uploadErrors = $state({}); +// let isChecking = $state({}); - let hasErrors = $derived( - Object.values(formState.errors).some(value => value !== null) - ); +// let hasErrors = $derived( +// Object.values(formState.errors).some(value => value !== null) +// ); + +// return { +// get hasErrors() { return hasErrors }, +// } +// } + +export function useDictionaryForm(formState, getActiveFormStates) { + let hasErrors = $derived.by(() => { + const mainHasError = Object.values(formState.errors).some(v => v !== null); + const activeHasError = getActiveFormStates().some(fs => + Object.values(fs.errors).some(v => v !== null) + ); + return mainHasError || activeHasError; + }); return { get hasErrors() { return hasErrors }, diff --git a/src/lib/components/dictionary/test/config/test-form-config.js b/src/lib/components/dictionary/test/config/test-form-config.js index 67ce2f1..7f52041 100644 --- a/src/lib/components/dictionary/test/config/test-form-config.js +++ b/src/lib/components/dictionary/test/config/test-form-config.js @@ -44,6 +44,7 @@ export const testCalSchema = z.object({ ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Formula must contain all selected input parameters:${data.FormulaInput.join(',')}`, + // message: `Formula must contain all selected input parameters:`, path: ['FormulaCode'] }); } diff --git a/src/lib/components/dictionary/test/page/create-page.svelte b/src/lib/components/dictionary/test/page/create-page.svelte index e28e194..70be7b8 100644 --- a/src/lib/components/dictionary/test/page/create-page.svelte +++ b/src/lib/components/dictionary/test/page/create-page.svelte @@ -55,7 +55,24 @@ modeOpt: 'cascade' }) - const helpers = useDictionaryForm(formState); + const activeFormStates = $derived.by(() => { + switch (formState.form.TestType) { + case "TEST": + case "PARAM": + return [refNumState, refTxtState, mapFormState]; + case "CALC": + return [calFormState, refNumState, refTxtState, mapFormState]; + case "GROUP": + return []; + case "TITLE": + return []; + default: + return []; + } + }); + + // const helpers = useDictionaryForm(formState); + const helpers = useDictionaryForm(formState, () => activeFormStates); const handlers = { clearForm: () => { @@ -269,18 +286,6 @@ })); }); - const activeFormState = $derived.by(() => { - switch (formState.form.TestType) { - case "TEST": - return formState; - case "PARAM": - return formState; - case "CALC": - return calFormState; - default: - return null; - } - }); // $inspect(activeFormState.errors) let activeTab = $state('definition'); @@ -391,6 +396,11 @@ refTxtState.form.TxtRefType = value; } } + + // $inspect({ + // definition: formState.errors, + // active: activeFormStates.map(fs => fs.errors) + // }); diff --git a/src/lib/components/reusable/form/dictionary-form-renderer.svelte b/src/lib/components/reusable/form/dictionary-form-renderer.svelte index cf610f8..3ea5d45 100644 --- a/src/lib/components/reusable/form/dictionary-form-renderer.svelte +++ b/src/lib/components/reusable/form/dictionary-form-renderer.svelte @@ -1,134 +1,127 @@ -{#snippet Fieldset({ key, label, required, type, optionsEndpoint, options, validateOn, dependsOn, endpointParamKey, valueKey, labelKey, txtKey })} -
-
- - {#if required} - * - {/if} -
+{#snippet Fieldset({ + key, + label, + required, + type, + optionsEndpoint, + options, + validateOn, + dependsOn, + endpointParamKey, + valueKey, + labelKey, + txtKey +})} +
+
+ + {#if required} + * + {/if} +
-
- {#if type === "text"} - { - // console.log(`key: ${key}, form: ${formState.form[key]}`); - if (validateOn?.includes("input")) { - formState.validateField(key, formState.form[key], false); - } - }} - onblur={() => { - if (validateOn?.includes("blur")) { - validateFieldAsync(key, mode, originalData?.[key]); - } - }} - readonly={key === "NumRefType" || key === "TxtRefType" || key === "Level"} - /> - {:else if type === "email"} - { - if (validateOn?.includes("input")) { - formState.validateField(key, formState.form[key], false); - } - }} - onblur={() => { - if (validateOn?.includes("blur")) { - formState.validateField(key, formState.form[key], false); - } - }} - /> - {:else if type === "number"} - { - if (validateOn?.includes("input")) { - formState.validateField(key, formState.form[key], false); - } - }} - onblur={() => { - if (validateOn?.includes("blur")) { - formState.validateField(key, formState.form[key], false); - } - }} - onkeydown={(e) => ['e', 'E', '+', '-'].includes(e.key) && e.preventDefault()} - /> - {:else if type === "textarea"} -