🐛 fix(ui): Components

This commit is contained in:
web@ppanel
2024-11-15 01:39:47 +07:00
parent 727d779b84
commit a7927d701a
12 changed files with 170 additions and 171 deletions
+31 -12
View File
@@ -1,18 +1,15 @@
import { Button } from '@shadcn/ui/button';
import { CircleMinusIcon, CirclePlusIcon } from 'lucide-react';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Combobox } from './combobox';
import { EnhancedInput } from './enhanced-input';
import { EnhancedInput, EnhancedInputProps } from './enhanced-input';
interface FieldConfig {
interface FieldConfig extends Omit<EnhancedInputProps, 'type'> {
name: string;
type: 'text' | 'number' | 'select';
placeholder?: string;
prefix?: string;
suffix?: string;
min?: number;
max?: number;
options?: { label: string; value: string }[];
internal?: boolean;
calculateValue?: (value: Record<string, any>) => any;
}
interface ObjectInputProps<T> {
@@ -26,8 +23,31 @@ export function ObjectInput<T extends Record<string, any>>({
onChange,
fields,
}: ObjectInputProps<T>) {
const [internalState, setInternalState] = useState<T>(value);
useEffect(() => {
setInternalState(value);
}, [value]);
const updateField = (key: keyof T, fieldValue: string | number) => {
onChange({ ...value, [key]: fieldValue });
let updatedInternalState = { ...internalState, [key]: fieldValue };
fields.forEach((field) => {
if (field.calculateValue && field.name === key) {
const newValue = field.calculateValue(updatedInternalState);
updatedInternalState = newValue;
}
});
setInternalState(updatedInternalState);
const filteredValue = Object.keys(updatedInternalState).reduce((acc, fieldKey) => {
const field = fields.find((f) => f.name === fieldKey);
if (field && !field.internal) {
acc[fieldKey as keyof T] = updatedInternalState[fieldKey as keyof T];
}
return acc;
}, {} as T);
onChange(filteredValue);
};
return (
@@ -38,14 +58,14 @@ export function ObjectInput<T extends Record<string, any>>({
<Combobox<string, false>
placeholder={fieldProps.placeholder}
options={options}
value={value[name]}
value={internalState[name]}
onChange={(fieldValue) => {
updateField(name, fieldValue);
}}
/>
) : (
<EnhancedInput
value={value[name]}
value={internalState[name]}
onValueChange={(fieldValue) => updateField(name, fieldValue)}
type={type}
{...fieldProps}
@@ -56,7 +76,6 @@ export function ObjectInput<T extends Record<string, any>>({
</div>
);
}
interface ArrayInputProps<T> {
value?: T[];
onChange: (value: T[]) => void;
+3 -2
View File
@@ -2,7 +2,8 @@ import { Input } from '@shadcn/ui/input';
import { cn } from '@shadcn/ui/lib/utils';
import { ChangeEvent, ReactNode, useEffect, useState } from 'react';
interface EnhancedInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
export interface EnhancedInputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
prefix?: ReactNode;
suffix?: ReactNode;
formatInput?: (value: string | number) => string;
@@ -39,7 +40,7 @@ export function EnhancedInput({
}, [initialValue, formatInput]);
const processValue = (inputValue: string) => {
let processedValue: number | string = inputValue?.trim();
let processedValue: number | string = inputValue?.toString().trim();
if (processedValue && props.type === 'number') processedValue = Number(processedValue);
return formatOutput ? formatOutput(processedValue) : processedValue;
};
+9 -1
View File
@@ -1,4 +1,4 @@
import { evaluate } from 'mathjs';
import { evaluate, format } from 'mathjs';
export function unitConversion(
type: 'centsToDollars' | 'dollarsToCents' | 'bitsToMb' | 'mbToBits' | 'bytesToGb' | 'gbToBytes',
@@ -22,3 +22,11 @@ export function unitConversion(
throw new Error('Invalid conversion type');
}
}
export function evaluateWithPrecision(expression: string) {
const result = evaluate(expression);
const formatted = format(result, { notation: 'fixed', precision: 2 });
return Number(formatted);
}