move function in calculation in child component

This commit is contained in:
faiztyanirh 2026-03-09 10:33:19 +07:00
parent ec5ebba12e
commit 4f5ba718e8
5 changed files with 133 additions and 203 deletions

View File

@ -794,39 +794,6 @@ export const refNumFormFields = [
}
]
}
// {
// title: "Flag & Interpretation",
// rows: [
// {
// type: "row",
// columns: [
// {
// key: "Flag",
// label: "Flag",
// required: false,
// type: "text",
// },
// {
// key: "Interpretation",
// label: "Interpretation",
// required: false,
// type: "text",
// },
// ]
// },
// {
// type: "row",
// columns: [
// {
// key: "Notes",
// label: "Notes",
// required: false,
// type: "textarea",
// },
// ]
// },
// ]
// },
];
export const refTxtFormFields = [
@ -1055,24 +1022,6 @@ export function getTestFormActions(handlers) {
];
}
// export function buildTestPayload({ mainForm, calForm, refForm, testType }) {
// let payload = {
// ...mainForm
// };
// if (testType === 'CALC') {
// payload.calculation = {
// ...calForm
// }
// } else if (testType === 'TEST' || testType === 'PARAM') {
// payload.reference = {
// ...refForm
// };
// }
// return cleanEmptyStrings(payload);
// }
export function buildTestPayload({ mainForm, activeFormStates, testType, refNumData, refTxtData }) {
let payload = {
...mainForm

View File

@ -81,22 +81,6 @@
modeOpt: 'cascade'
});
// 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 activeFormStates = $derived.by(() => {
const testType = formState.form.TestType ?? '';
const refType = formState.form.RefType ?? '';

View File

@ -9,11 +9,113 @@
import DictionaryFormRenderer from '$lib/components/reusable/form/dictionary-form-renderer.svelte';
let props = $props();
const operators = ['+', '-', '*', '/', '^', '(', ')'];
let expression = $state('');
let cursorPosition = $state(0);
function unselectAll(key) {
props.calFormState.form[key] = [];
props.calFormState.validateField?.(key, [], false);
}
function getErrorStatus(formulaCode = '') {
const selected = props.calFormState.form.FormulaInput;
if (!Array.isArray(selected)) return [];
return selected.map((item) => ({
value: item.value,
done: new RegExp(`\\b${item.value}\\b`, 'i').test(formulaCode)
}));
}
function addToExpression(text) {
const before = expression.slice(0, cursorPosition);
const after = expression.slice(cursorPosition);
expression = before + text + after;
cursorPosition += text.length;
}
function addOperator(op) {
addToExpression(op);
props.calFormState.form.FormulaCode = expression;
props.calFormState.validateField?.('FormulaCode', expression, false);
}
function addValue(val) {
addToExpression(val);
props.calFormState.form.FormulaCode = expression;
props.calFormState.validateField?.('FormulaCode', expression, false);
}
// function handleInput(e) {
// expression = e.target.value;
// cursorPosition = e.target.selectionStart;
// formState.form.FormulaCode = expression;
// formState.validateField?.('FormulaCode', expression, false);
// }
// function handleClick(e) {
// cursorPosition = e.target.selectionStart;
// }
function handleContainerClick(e) {
const rect = e.currentTarget.getBoundingClientRect();
const text = expression;
const charWidth = 8.5;
const padding = 12;
const clickX = e.clientX - rect.left - padding;
let newPos = Math.floor(clickX / charWidth);
newPos = Math.max(0, Math.min(newPos, text.length));
cursorPosition = newPos;
}
function moveCursorLeft() {
if (cursorPosition > 0) {
cursorPosition -= 1;
}
}
function moveCursorRight() {
if (cursorPosition < expression.length) {
cursorPosition += 1;
}
}
function deleteChar() {
if (cursorPosition > 0) {
const before = expression.slice(0, cursorPosition - 1);
const after = expression.slice(cursorPosition);
expression = before + after;
cursorPosition -= 1;
props.calFormState.form.FormulaCode = expression;
props.calFormState.validateField?.('FormulaCode', expression, false);
}
}
function clearExpression() {
expression = '';
cursorPosition = 0;
props.calFormState.form.FormulaCode = expression;
props.calFormState.validateField?.('FormulaCode', expression, false);
}
</script>
<div class="flex flex-col gap-4 w-full">
<DictionaryFormRenderer formState={props.calFormState} formFields={props.testCalFormFields}/>
</div>
<DictionaryFormRenderer
formState={props.calFormState}
formFields={props.testCalFormFields}
operators={operators}
expression={expression}
cursorPosition={cursorPosition}
onUnselectAll={unselectAll}
onGetErrorStatus={getErrorStatus}
onAddOperator={addOperator}
onAddValue={addValue}
onHandleContainerClick={handleContainerClick}
onMoveCursorLeft={moveCursorLeft}
onMoveCursorRight={moveCursorRight}
onDeleteChar={deleteChar}
onClearExpression={clearExpression}
/>
</div>

View File

@ -3,10 +3,6 @@
let props = $props();
// function addMember() {
// members = [...members, { id: Date.now(), value: '' }];
// }
function addMember() {
props.groupFormState.form.Members = [
...(props.groupFormState.form.Members ?? []),
@ -14,10 +10,6 @@
];
}
// function removeMember(id) {
// members = members.filter((m) => m.id !== id);
// }
// $inspect(props.groupFormState.form.Members)
function removeMember(id) {
props.groupFormState.form.Members = props.groupFormState.form.Members.filter((m) => m.id !== id);
props.groupFormState.validateField?.("Members", props.groupFormState.form.Members, false);

View File

@ -31,32 +31,25 @@
handleResultTypeChange,
handleRefTypeChange,
onAddMember,
onRemoveMember
onRemoveMember,
operators,
expression,
cursorPosition,
onUnselectAll,
onGetErrorStatus,
onAddOperator,
onAddValue,
onHandleContainerClick,
onMoveCursorLeft,
onMoveCursorRight,
onDeleteChar,
onClearExpression,
} = $props();
// $effect(() => {
// if (!formFields) return;
// const hasMembersField = formFields.some((group) =>
// group.rows?.some((row) => row.columns?.some((col) => col.type === 'members'))
// );
// if (hasMembersField) {
// if (members.length > 0) {
// formState.form.Member = members.map((m) => m.value).filter((v) => v);
// } else {
// formState.form.Member = '';
// }
// }
// });
const operators = ['+', '-', '*', '/', '^', '(', ')'];
let searchQuery = $state({});
let dropdownOpen = $state({});
let expression = $state('');
let cursorPosition = $state(0);
// $inspect(expression)
function getFilteredOptions(key) {
const query = searchQuery[key] || '';
if (!query) return formState.selectOptions?.[key] ?? [];
@ -66,10 +59,6 @@
);
}
$effect(() => {
initializeDefaultValues();
});
async function initializeDefaultValues() {
for (const group of formFields) {
for (const row of group.rows) {
@ -96,90 +85,9 @@
}
}
function unselectAll(key) {
formState.form[key] = [];
formState.validateField?.(key, [], false);
}
function getErrorStatus(formulaCode = '') {
const selected = formState.form.FormulaInput;
if (!Array.isArray(selected)) return [];
return selected.map((item) => ({
value: item.value,
done: new RegExp(`\\b${item.value}\\b`, 'i').test(formulaCode)
}));
}
function addToExpression(text) {
const before = expression.slice(0, cursorPosition);
const after = expression.slice(cursorPosition);
expression = before + text + after;
cursorPosition += text.length;
}
function addOperator(op) {
addToExpression(op);
formState.form.FormulaCode = expression;
formState.validateField?.('FormulaCode', expression, false);
}
function addValue(val) {
addToExpression(val);
formState.form.FormulaCode = expression;
formState.validateField?.('FormulaCode', expression, false);
}
function handleInput(e) {
expression = e.target.value;
cursorPosition = e.target.selectionStart;
formState.form.FormulaCode = expression;
formState.validateField?.('FormulaCode', expression, false);
}
function handleClick(e) {
cursorPosition = e.target.selectionStart;
}
function handleContainerClick(e) {
const rect = e.currentTarget.getBoundingClientRect();
const text = expression;
const charWidth = 8.5;
const padding = 12;
const clickX = e.clientX - rect.left - padding;
let newPos = Math.floor(clickX / charWidth);
newPos = Math.max(0, Math.min(newPos, text.length));
cursorPosition = newPos;
}
function moveCursorLeft() {
if (cursorPosition > 0) {
cursorPosition -= 1;
}
}
function moveCursorRight() {
if (cursorPosition < expression.length) {
cursorPosition += 1;
}
}
function deleteChar() {
if (cursorPosition > 0) {
const before = expression.slice(0, cursorPosition - 1);
const after = expression.slice(cursorPosition);
expression = before + after;
cursorPosition -= 1;
formState.form.FormulaCode = expression;
formState.validateField?.('FormulaCode', expression, false);
}
}
function clearExpression() {
expression = '';
cursorPosition = 0;
formState.form.FormulaCode = expression;
formState.validateField?.('FormulaCode', expression, false);
}
$effect(() => {
initializeDefaultValues();
});
</script>
{#snippet Fieldset({
@ -210,7 +118,6 @@
type="text"
bind:value={formState.form[key]}
oninput={() => {
// console.log(`key: ${key}, form: ${formState.form[key]}`);
if (validateOn?.includes('input')) {
formState.validateField(key, formState.form[key], false);
}
@ -415,7 +322,7 @@
<Select.Separator />
<button
class="w-full px-2 py-1.5 text-left text-sm hover:bg-accent hover:text-accent-foreground"
onclick={() => unselectAll(key)}
onclick={() => onUnselectAll?.(key)}
>
Unselect All
</button>
@ -517,7 +424,6 @@
bind:value={joinFields[key].YY}
oninput={() => {
if (validateOn?.includes('input')) {
// formState.validateField(key, formState.form[key], false);
formState.validateField('AgeStart');
formState.validateField('AgeEnd');
}
@ -533,7 +439,6 @@
bind:value={joinFields[key].MM}
oninput={() => {
if (validateOn?.includes('input')) {
// formState.validateField(key, formState.form[key], false);
formState.validateField('AgeStart');
formState.validateField('AgeEnd');
}
@ -549,7 +454,6 @@
bind:value={joinFields[key].DD}
oninput={() => {
if (validateOn?.includes('input')) {
// formState.validateField(key, formState.form[key], false);
formState.validateField('AgeStart');
formState.validateField('AgeEnd');
}
@ -563,7 +467,7 @@
{:else if type === 'formulabuilder'}
<div class="flex flex-col gap-8 w-full">
<div class="flex gap-1 w-full">
<Button type="button" variant="outline" size="icon" onclick={moveCursorLeft}>
<Button type="button" variant="outline" size="icon" onclick={onMoveCursorLeft}>
<MoveLeftIcon class="w-4 h-4" />
</Button>
<div class="relative flex-1">
@ -571,7 +475,7 @@
class="flex flex-1 h-9 w-full min-w-0 items-center rounded-md border bg-background px-3 py-2 font-mono text-sm whitespace-nowrap"
role="textbox"
tabindex="0"
onclick={handleContainerClick}
onclick={onHandleContainerClick}
>
{#each expression.split('') as char, i}
{#if i === cursorPosition}
@ -584,14 +488,14 @@
{/if}
</button>
</div>
<Button type="button" variant="outline" size="icon" onclick={moveCursorRight}>
<Button type="button" variant="outline" size="icon" onclick={onMoveCursorRight}>
<MoveRightIcon class="w-4 h-4" />
</Button>
<Button type="button" variant="outline" size="icon" onclick={deleteChar}>
<Button type="button" variant="outline" size="icon" onclick={onDeleteChar}>
<DeleteIcon class="w-4 h-4" />
</Button>
<Button type="button" variant="outline" size="icon" onclick={clearExpression}>
<Button type="button" variant="outline" size="icon" onclick={onClearExpression}>
<BrushCleaningIcon class="w-4 h-4" />
</Button>
</div>
@ -605,7 +509,7 @@
type="button"
variant="outline"
class="h-auto w-auto p-2"
onclick={() => addValue(item.value)}
onclick={() => onAddValue?.(item.value)}
>
{item.value}
</Button>
@ -619,7 +523,7 @@
type="button"
variant="outline"
size="icon"
onclick={() => addOperator(op)}
onclick={() => onAddOperator?.(op)}
>
{op}
</Button>
@ -655,7 +559,6 @@
}
}}
onValueChange={() => {
console.log(key);
if (validateOn?.includes('input')) {
formState.validateField?.(key, formState.form[key], false);
}
@ -719,7 +622,7 @@
</div>
{/if}
{#if key === 'FormulaCode' && formState.form.FormulaInput?.length}
{@const inputStatus = getErrorStatus(expression)}
{@const inputStatus = onGetErrorStatus?.(expression)}
<div class="flex items-center gap-2 text-sm text-destructive">
<span>Must included :</span>