mirror of
https://github.com/faiztyanirh/clqms-shadcn-v1.git
synced 2026-04-26 02:46:32 +07:00
move error calc, add preview syntax
This commit is contained in:
parent
05ee4617d5
commit
45c8d6969a
@ -18,9 +18,6 @@
|
|||||||
let cursorIndex = $state(0);
|
let cursorIndex = $state(0);
|
||||||
let showLiteralPopover = $state(false);
|
let showLiteralPopover = $state(false);
|
||||||
let literalPopoverType = $state(('string'));
|
let literalPopoverType = $state(('string'));
|
||||||
$inspect(tokens)
|
|
||||||
// let expression = $state('');
|
|
||||||
// let cursorPosition = $state(0);
|
|
||||||
|
|
||||||
function uid() {
|
function uid() {
|
||||||
return Math.random().toString(36).slice(2, 9);
|
return Math.random().toString(36).slice(2, 9);
|
||||||
@ -106,92 +103,6 @@ $inspect(tokens)
|
|||||||
props.calFormState.form[key] = [];
|
props.calFormState.form[key] = [];
|
||||||
props.calFormState.validateField?.(key, [], false);
|
props.calFormState.validateField?.(key, [], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4 w-full">
|
<div class="flex flex-col gap-4 w-full">
|
||||||
|
|||||||
@ -126,6 +126,20 @@
|
|||||||
{#if required}
|
{#if required}
|
||||||
<span class="text-destructive text-xl leading-none h-3.5">*</span>
|
<span class="text-destructive text-xl leading-none h-3.5">*</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if key === 'FormulaCode' && formState.form.FormulaInput?.length}
|
||||||
|
{@const inputStatus = onGetErrorStatus?.()}
|
||||||
|
<div class="flex items-center gap-2 text-sm text-destructive">
|
||||||
|
<span>Must included :</span>
|
||||||
|
|
||||||
|
<div class="flex gap-1 flex-wrap">
|
||||||
|
{#each inputStatus as item (item.value)}
|
||||||
|
<Badge class="px-1 text-[10px]" variant={item.done ? 'default' : 'destructive'}>
|
||||||
|
{item.value}
|
||||||
|
</Badge>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative flex flex-col items-center w-full">
|
<div class="relative flex flex-col items-center w-full">
|
||||||
@ -487,52 +501,49 @@
|
|||||||
<MoveLeftIcon class="w-4 h-4" />
|
<MoveLeftIcon class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<div
|
<div
|
||||||
class="relative flex-1 min-h-[2rem] rounded-md border bg-background px-3 py-2 font-mono text-sm cursor-text focus-within:ring-1 focus-within:ring-ring"
|
class="relative flex-1 min-h-[2rem] rounded-md border bg-background px-3 py-2 font-mono text-sm cursor-text focus-within:ring-1 focus-within:ring-ring"
|
||||||
role="textbox"
|
role="textbox"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
onkeydown={(e) => {
|
onkeydown={(e) => {
|
||||||
if (e.key === 'Backspace') { e.preventDefault(); onDeleteChar(); }
|
if (e.key === 'Backspace') { e.preventDefault(); onDeleteChar(); }
|
||||||
if (e.key === 'ArrowLeft') onMoveCursorLeft();
|
if (e.key === 'ArrowLeft') onMoveCursorLeft();
|
||||||
if (e.key === 'ArrowRight') onMoveCursorRight();
|
if (e.key === 'ArrowRight') onMoveCursorRight();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#if tokens.length === 0}
|
{#if tokens.length === 0}
|
||||||
<span class="text-muted-foreground text-xs italic">Click buttons below to build formula...</span>
|
<span class="text-muted-foreground text-xs italic">Select test then click buttons below to build formula</span>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Split tokens into lines -->
|
{@const lines = (() => {
|
||||||
{@const lines = (() => {
|
const result = [[]];
|
||||||
const result = [[]];
|
tokens.forEach((tok, idx) => {
|
||||||
tokens.forEach((tok, idx) => {
|
if (tok.type === 'newline') result.push([]);
|
||||||
if (tok.type === 'newline') result.push([]);
|
else result[result.length - 1].push({ tok, idx });
|
||||||
else result[result.length - 1].push({ tok, idx });
|
});
|
||||||
});
|
return result;
|
||||||
return result;
|
})()}
|
||||||
})()}
|
{#each lines as line, lineIdx}
|
||||||
{#each lines as line, lineIdx}
|
<div class="flex flex-wrap items-center gap-1 min-h-[28px] {lineIdx > 0 ? 'mt-1 pt-1 border-t border-dashed border-border' : ''}">
|
||||||
<div class="flex flex-wrap items-center gap-1 min-h-[28px] {lineIdx > 0 ? 'mt-1 pt-1 border-t border-dashed border-border' : ''}">
|
{#each line as { tok, idx }}
|
||||||
{#each line as { tok, idx }}
|
{#if cursorIndex === idx}
|
||||||
{#if cursorIndex === idx}
|
<span class="animate-cursor inline-block h-5 w-0.5 bg-primary rounded"></span>
|
||||||
<span class="animate-cursor inline-block h-5 w-0.5 bg-primary rounded"></span>
|
{/if}
|
||||||
{/if}
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold border transition-colors"
|
||||||
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold border transition-colors "
|
onclick={() => onSetCursor(idx + 1)}
|
||||||
onclick={() => onSetCursor(idx + 1)}
|
>
|
||||||
title="Click to move cursor here"
|
{tok.value}
|
||||||
>
|
</button>
|
||||||
{tok.value}
|
{/each}
|
||||||
</button>
|
{#if line.length > 0 && cursorIndex === line[line.length - 1].idx + 1}
|
||||||
|
<span class="animate-cursor inline-block h-5 w-0.5 bg-primary rounded"></span>
|
||||||
|
{:else if line.length === 0 && lineIdx === lines.length - 1}
|
||||||
|
<span class="animate-cursor inline-block h-5 w-0.5 bg-primary rounded"></span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{#if line.length > 0 && cursorIndex === line[line.length - 1].idx + 1}
|
{/if}
|
||||||
<span class="animate-cursor inline-block h-5 w-0.5 bg-primary rounded"></span>
|
</div>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
{#if cursorIndex === tokens.length && (tokens.length === 0 || tokens[tokens.length - 1].type === 'newline')}
|
|
||||||
<span class="animate-cursor inline-block h-5 w-0.5 bg-primary rounded mt-1"></span>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<Button type="button" variant="outline" size="icon" onclick={onMoveCursorRight}>
|
<Button type="button" variant="outline" size="icon" onclick={onMoveCursorRight}>
|
||||||
<MoveRightIcon class="w-4 h-4" />
|
<MoveRightIcon class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
@ -545,187 +556,184 @@
|
|||||||
<Button type="button" variant="outline" size="icon" onclick={onAddNewline} title="New line">
|
<Button type="button" variant="outline" size="icon" onclick={onAddNewline} title="New line">
|
||||||
<CornerDownLeftIcon class="w-4 h-4" />
|
<CornerDownLeftIcon class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{#if formState.form.FormulaInput?.length > 0}
|
{#if formState.form.FormulaInput?.length > 0}
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<!-- Selected Tests -->
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex flex-col gap-2">
|
<Label class="uppercase tracking-wide">Selected Tests</Label>
|
||||||
<span class="text-sm font-medium">Selected Tests</span>
|
<div class="flex flex-wrap gap-2">
|
||||||
<div class="flex flex-wrap gap-2">
|
{#each formState.form.FormulaInput as item (item)}
|
||||||
{#each formState.form.FormulaInput as item (item)}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
class="h-auto w-auto p-2"
|
|
||||||
onclick={() => onAddValue?.(item.value)}
|
|
||||||
>
|
|
||||||
{item.value}
|
|
||||||
</Button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Custom Literal Values -->
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<span class="text-sm font-medium">Custom Values</span>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
<!-- String literal popover -->
|
|
||||||
<Popover.Root bind:open={stringPopoverOpen}>
|
|
||||||
<Popover.Trigger>
|
|
||||||
{#snippet child({ props: triggerProps })}
|
|
||||||
<Button
|
|
||||||
{...triggerProps}
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
class="h-auto w-auto p-2"
|
|
||||||
>
|
|
||||||
"abc"
|
|
||||||
</Button>
|
|
||||||
{/snippet}
|
|
||||||
</Popover.Trigger>
|
|
||||||
<Popover.Content class="w-64" side="bottom" align="start">
|
|
||||||
<div>
|
|
||||||
<div class="flex flex-col gap-3">
|
|
||||||
<p class="text-sm font-semibold">Enter Text Value</p>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
placeholder='e.g. F, POS, NEG'
|
|
||||||
bind:value={stringLiteralInput}
|
|
||||||
onkeydown={(e) => {
|
|
||||||
if (e.key === 'Enter' && stringLiteralInput.trim()) {
|
|
||||||
onAddLiteral(`"${stringLiteralInput.trim()}"`);
|
|
||||||
stringLiteralInput = '';
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div class="flex justify-end gap-2">
|
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
variant="outline"
|
||||||
disabled={!stringLiteralInput.trim()}
|
class="h-auto w-auto p-2"
|
||||||
onclick={() => {
|
onclick={() => onAddValue?.(item.value)}
|
||||||
onAddLiteral(`"${stringLiteralInput.trim()}"`);
|
|
||||||
stringLiteralInput = '';
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Add
|
{item.value}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Custom Literal Values -->
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Label class="uppercase tracking-wide">Custom Values</Label>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<Popover.Root bind:open={stringPopoverOpen}>
|
||||||
|
<Popover.Trigger>
|
||||||
|
{#snippet child({ props: triggerProps })}
|
||||||
|
<Button
|
||||||
|
{...triggerProps}
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
class="h-auto w-auto p-2"
|
||||||
|
>
|
||||||
|
"abc"
|
||||||
|
</Button>
|
||||||
|
{/snippet}
|
||||||
|
</Popover.Trigger>
|
||||||
|
<Popover.Content class="w-64" side="bottom" align="start">
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<p class="text-sm font-semibold">Enter Text Value</p>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder='e.g. F, POS, NEG'
|
||||||
|
bind:value={stringLiteralInput}
|
||||||
|
onkeydown={(e) => {
|
||||||
|
if (e.key === 'Enter' && stringLiteralInput.trim()) {
|
||||||
|
onAddLiteral(`"${stringLiteralInput.trim()}"`);
|
||||||
|
stringLiteralInput = '';
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
disabled={!stringLiteralInput.trim()}
|
||||||
|
onclick={() => {
|
||||||
|
onAddLiteral(`"${stringLiteralInput.trim()}"`);
|
||||||
|
stringLiteralInput = '';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover.Root>
|
||||||
|
|
||||||
|
<Popover.Root bind:open={numberPopoverOpen}>
|
||||||
|
<Popover.Trigger>
|
||||||
|
{#snippet child({ props: triggerProps })}
|
||||||
|
<Button
|
||||||
|
{...triggerProps}
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
class="h-auto w-auto p-2"
|
||||||
|
>
|
||||||
|
123
|
||||||
|
</Button>
|
||||||
|
{/snippet}
|
||||||
|
</Popover.Trigger>
|
||||||
|
<Popover.Content class="w-64" side="bottom" align="start">
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<p class="text-sm font-semibold">Enter Number Value</p>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder='e.g. 142'
|
||||||
|
bind:value={numberLiteralInput}
|
||||||
|
onkeydown={(e) => {
|
||||||
|
if (e.key === 'Enter' && numberLiteralInput != null && !isNaN(numberLiteralInput)) {
|
||||||
|
onAddLiteral(String(numberLiteralInput));
|
||||||
|
numberLiteralInput = null;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
disabled={numberLiteralInput == null || isNaN(numberLiteralInput)}
|
||||||
|
onclick={() => {
|
||||||
|
onAddLiteral(String(numberLiteralInput));
|
||||||
|
numberLiteralInput = null;
|
||||||
|
numberPopoverOpen = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover.Root>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Label class="uppercase tracking-wide">Logical Operators</Label>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{#each logicalop as op}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
class="h-auto w-auto p-2"
|
||||||
|
onclick={() => onAddOperator?.(op)}
|
||||||
|
>
|
||||||
|
{op}
|
||||||
|
</Button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Comparison Operators -->
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Label class="uppercase tracking-wide">Comparison Operators</Label>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{#each comparisonop as op}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onclick={() => onAddOperator?.(op)}
|
||||||
|
>
|
||||||
|
{op}
|
||||||
|
</Button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Math Operators -->
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Label class="uppercase tracking-wide">Math Operators</Label>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{#each operators as op}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onclick={() => onAddOperator?.(op)}
|
||||||
|
>
|
||||||
|
{op}
|
||||||
|
</Button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if tokens.length > 0}
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Label class="uppercase tracking-wide">Preview</Label>
|
||||||
|
<div class="border-2 border-dashed border-muted-foreground/30 rounded-lg">
|
||||||
|
<pre class="font-mono text-sm bg-muted/50 p-2 rounded">{expressionString}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Popover.Content>
|
{/if}
|
||||||
</Popover.Root>
|
</div>
|
||||||
|
{/if}
|
||||||
<!-- Number literal popover -->
|
|
||||||
<Popover.Root bind:open={numberPopoverOpen}>
|
|
||||||
<Popover.Trigger>
|
|
||||||
{#snippet child({ props: triggerProps })}
|
|
||||||
<Button
|
|
||||||
{...triggerProps}
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
class="h-auto w-auto p-2"
|
|
||||||
>
|
|
||||||
123
|
|
||||||
</Button>
|
|
||||||
{/snippet}
|
|
||||||
</Popover.Trigger>
|
|
||||||
<Popover.Content class="w-64" side="bottom" align="start">
|
|
||||||
<div>
|
|
||||||
<div class="flex flex-col gap-3">
|
|
||||||
<p class="text-sm font-semibold">Enter Number Value</p>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
placeholder='e.g. 142'
|
|
||||||
bind:value={numberLiteralInput}
|
|
||||||
onkeydown={(e) => {
|
|
||||||
if (e.key === 'Enter' && numberLiteralInput != null && !isNaN(numberLiteralInput)) {
|
|
||||||
onAddLiteral(String(numberLiteralInput));
|
|
||||||
numberLiteralInput = null;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div class="flex justify-end gap-2">
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
size="sm"
|
|
||||||
disabled={numberLiteralInput == null || isNaN(numberLiteralInput)}
|
|
||||||
onclick={() => {
|
|
||||||
onAddLiteral(String(numberLiteralInput));
|
|
||||||
numberLiteralInput = null;
|
|
||||||
numberPopoverOpen = false;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Add
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Root>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Logical Operators (Keywords) -->
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<span class="text-sm font-medium">Logical Operators</span>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
{#each logicalop as op}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
class="h-auto w-auto p-2"
|
|
||||||
onclick={() => onAddOperator?.(op)}
|
|
||||||
>
|
|
||||||
{op}
|
|
||||||
</Button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Comparison Operators -->
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<span class="text-sm font-medium">Comparison Operators</span>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
{#each comparisonop as op}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
size="icon"
|
|
||||||
onclick={() => onAddOperator?.(op)}
|
|
||||||
>
|
|
||||||
{op}
|
|
||||||
</Button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Math Operators -->
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<span class="text-sm font-medium">Math Operators</span>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
{#each operators as op}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
size="icon"
|
|
||||||
onclick={() => onAddOperator?.(op)}
|
|
||||||
>
|
|
||||||
{op}
|
|
||||||
</Button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Preview -->
|
|
||||||
{#if tokens.length > 0}
|
|
||||||
<div class="section">
|
|
||||||
<label class="section-label">Preview</label>
|
|
||||||
<pre class="expression-preview">{expressionString}</pre>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{:else if type === 'members'}
|
{:else if type === 'members'}
|
||||||
{@const filteredOptions = getFilteredOptions(key)}
|
{@const filteredOptions = getFilteredOptions(key)}
|
||||||
@ -814,22 +822,6 @@
|
|||||||
{errorMessage}
|
{errorMessage}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if key === 'FormulaCode' && formState.form.FormulaInput?.length}
|
|
||||||
{@const inputStatus = onGetErrorStatus?.()}
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex items-center gap-2 text-sm text-destructive">
|
|
||||||
<span>Must included :</span>
|
|
||||||
|
|
||||||
<div class="flex gap-1 flex-wrap">
|
|
||||||
{#each inputStatus as item (item.value)}
|
|
||||||
<Badge variant={item.done ? 'default' : 'destructive'}>
|
|
||||||
{item.value}
|
|
||||||
</Badge>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user