diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index ca23a2a..3e13e70 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,26 +4,12 @@
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
@@ -415,14 +401,6 @@
-
-
- 1740619610168
-
-
-
- 1740619610169
-
1740620866551
@@ -807,7 +785,15 @@
1743355166426
-
+
+
+ 1743827787241
+
+
+
+ 1743827787241
+
+
@@ -854,7 +840,6 @@
-
@@ -879,7 +864,8 @@
-
+
+
diff --git a/src/components/ToolContent.tsx b/src/components/ToolContent.tsx
index 721035d..703128e 100644
--- a/src/components/ToolContent.tsx
+++ b/src/components/ToolContent.tsx
@@ -57,6 +57,7 @@ interface ToolContentProps extends ToolComponentProps {
setInput?: React.Dispatch>;
validationSchema?: any;
onValuesChange?: (values: T) => void;
+ verticalGroups?: boolean;
}
export default function ToolContent({
@@ -72,7 +73,8 @@ export default function ToolContent({
setInput,
validationSchema,
renderCustomInput,
- onValuesChange
+ onValuesChange,
+ verticalGroups
}: ToolContentProps) {
return (
@@ -97,7 +99,7 @@ export default function ToolContent({
input={input}
onValuesChange={onValuesChange}
/>
-
+
{toolInfo && toolInfo.title && toolInfo.description && (
{
handlePrefixChange(evt.target.value || '');
diff --git a/src/components/options/ToolOptions.tsx b/src/components/options/ToolOptions.tsx
index 15a1844..c145fca 100644
--- a/src/components/options/ToolOptions.tsx
+++ b/src/components/options/ToolOptions.tsx
@@ -13,10 +13,12 @@ export type GetGroupsType = (
export default function ToolOptions({
children,
- getGroups
+ getGroups,
+ vertical
}: {
children?: ReactNode;
getGroups: GetGroupsType | null;
+ vertical?: boolean;
}) {
const theme = useTheme();
const formikContext = useFormikContext();
@@ -49,6 +51,7 @@ export default function ToolOptions({
{children}
diff --git a/src/pages/tools/number/generic-calc/index.tsx b/src/pages/tools/number/generic-calc/index.tsx
index 3dc21f9..48ed78f 100644
--- a/src/pages/tools/number/generic-calc/index.tsx
+++ b/src/pages/tools/number/generic-calc/index.tsx
@@ -2,6 +2,7 @@ import {
Autocomplete,
Box,
Radio,
+ Stack,
Table,
TableBody,
TableCell,
@@ -24,6 +25,8 @@ import 'nerdamer-prime/Solve';
import 'nerdamer-prime/Calculus';
import Qty from 'js-quantities';
import { CustomSnackBarContext } from 'contexts/CustomSnackBarContext';
+import Typography from '@mui/material/Typography';
+import Grid from '@mui/material/Grid';
function numericSolveEquationFor(
equation: string,
@@ -59,14 +62,6 @@ export default async function makeTool(
return function GenericCalc({ title }: ToolComponentProps) {
const { showSnackBar } = useContext(CustomSnackBarContext);
- const [alternatesByVariable, setAlternatesByVariable] = useState<{
- [key: string]: {
- value: {
- value: number;
- unit: string;
- };
- }[];
- }>({});
// For UX purposes we need to track what vars are
const [valsBoundToPreset, setValsBoundToPreset] = useState<{
@@ -110,12 +105,17 @@ export default async function makeTool(
newPresets[selection] = preset;
updateFieldFunc('presets', newPresets);
- // Clear old selection
- for (const key in valsBoundToPreset) {
- if (valsBoundToPreset[key] === selection) {
- delete valsBoundToPreset[key];
- }
- }
+ // Clear old selection using setState callback pattern
+ setValsBoundToPreset((prevState) => {
+ const newState = { ...prevState };
+ // Remove all keys bound to this selection
+ Object.keys(newState).forEach((key) => {
+ if (newState[key] === selection) {
+ delete newState[key];
+ }
+ });
+ return newState;
+ });
const selectionData = calcData.presets?.find(
(sel) => sel.title === selection
@@ -123,8 +123,12 @@ export default async function makeTool(
if (preset && preset != '') {
if (selectionData) {
+ // Create an object with the new bindings
+ const newBindings: { [key: string]: string } = {};
+
for (const key in selectionData.bind) {
- valsBoundToPreset[key] = selection;
+ // Add to newBindings for later state update
+ newBindings[key] = selection;
if (currentValues.outputVariable === key) {
handleSelectedTargetChange('', updateFieldFunc);
@@ -142,6 +146,12 @@ export default async function makeTool(
updateFieldFunc
);
}
+
+ // Update state with new bindings
+ setValsBoundToPreset((prevState) => ({
+ ...prevState,
+ ...newBindings
+ }));
} else {
throw new Error(
`Preset "${preset}" is not valid for selection "${selection}"`
@@ -179,7 +189,7 @@ export default async function makeTool(
unit: selection.source.columns[selection.bind[key]]?.unit || ''
};
- valsBoundToPreset[key] = selection.title;
+ // We'll set this in useEffect instead of directly modifying state
}
});
@@ -219,25 +229,6 @@ export default async function makeTool(
});
}
- calcData.variables.forEach((variable) => {
- if (variable.alternates) {
- variable.alternates.forEach((alt) => {
- const altValue = getAlternate(
- alt,
- variable,
- initialValues.vars[variable.name]
- );
- if (alternatesByVariable[variable.name] === undefined) {
- alternatesByVariable[variable.name] = [];
- }
-
- alternatesByVariable[variable.name].push({
- value: { value: altValue, unit: variable.unit }
- });
- });
- }
- });
-
return (
[
...(calcData.presets?.length
? [
{
title: 'Presets',
component: (
-
-
-
-
- Option
- Value
-
-
-
- {calcData.presets?.map((preset) => (
-
- {preset.title}
-
- ',
- ...Object.keys(preset.source.data).sort()
- ]}
- sx={{ width: 300 }}
- onChange={(event, newValue) => {
- handleSelectedPresetChange(
- preset.title,
- newValue || '',
- values,
- updateField
- );
- }}
- renderInput={(params) => (
-
- )}
- >
-
-
- ))}
-
-
-
+
+ {calcData.presets?.map((preset) => (
+
+
+ {preset.title}
+ ',
+ ...Object.keys(preset.source.data).sort()
+ ]}
+ sx={{ width: 300 }}
+ onChange={(event, newValue) => {
+ handleSelectedPresetChange(
+ preset.title,
+ newValue || '',
+ values,
+ updateField
+ );
+ }}
+ renderInput={(params) => (
+
+ )}
+ />
+
+
+ ))}
+
)
}
]
@@ -400,8 +387,15 @@ export default async function makeTool(
))}
-
- {calcData.extraOutputs?.map((extraOutput) => (
+
+
+ )
+ },
+ ...(calcData.extraOutputs
+ ? [
+ {
+ title: 'Extra outputs',
+ component: calcData.extraOutputs?.map((extraOutput) => (
{extraOutput.title}
@@ -412,15 +406,14 @@ export default async function makeTool(
value: extraOutputs[extraOutput.title],
unit: extraOutput.unit
}}
- >
+ />
- ))}
-
-
- )
- }
+ ))
+ }
+ ]
+ : [])
]}
compute={(values) => {
if (values.outputVariable === '') {
@@ -429,10 +422,10 @@ export default async function makeTool(
}
let expr: nerdamer.Expression | null = null;
- for (const i of calcData.variables) {
- if (i.name === values.outputVariable) {
- if (i.formula !== undefined) {
- expr = nerdamer(i.formula);
+ for (const variable of calcData.variables) {
+ if (variable.name === values.outputVariable) {
+ if (variable.formula !== undefined) {
+ expr = nerdamer(variable.formula);
}
}
}
@@ -442,7 +435,6 @@ export default async function makeTool(
}
if (expr == null) {
throw new Error('No formula found');
- return;
}
Object.keys(values.vars).forEach((key) => {
@@ -463,10 +455,15 @@ export default async function makeTool(
if ((result as unknown as nerdamer.Expression[])?.length < 1) {
values.vars[values.outputVariable].value = NaN;
if (calcData.extraOutputs !== undefined) {
- for (let i = 0; i < calcData.extraOutputs.length; i++) {
- const extraOutput = calcData.extraOutputs[i];
- extraOutputs[extraOutput.title] = NaN;
- }
+ // Update extraOutputs using setState
+ setExtraOutputs((prevState) => {
+ const newState = { ...prevState };
+ for (let i = 0; i < calcData.extraOutputs!.length; i++) {
+ const extraOutput = calcData.extraOutputs![i];
+ newState[extraOutput.title] = NaN;
+ }
+ return newState;
+ });
}
throw new Error('No solution found for this input');
}
@@ -500,9 +497,11 @@ export default async function makeTool(
const result: nerdamer.Expression = expr.evaluate();
if (result) {
- extraOutputs[extraOutput.title] = parseFloat(
- result.toDecimal()
- );
+ // Update extraOutputs state properly
+ setExtraOutputs((prevState) => ({
+ ...prevState,
+ [extraOutput.title]: parseFloat(result.toDecimal())
+ }));
}
}
}