mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-12-29 16:16:02 +00:00
refactor: tools folder inside pages
This commit is contained in:
113
src/pages/tools/number/sum/index.tsx
Normal file
113
src/pages/tools/number/sum/index.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React, { useState } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import ToolOptions from '@components/options/ToolOptions';
|
||||
import { compute, NumberExtractionType } from './service';
|
||||
import RadioWithTextField from '@components/options/RadioWithTextField';
|
||||
import SimpleRadio from '@components/options/SimpleRadio';
|
||||
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
|
||||
import ToolInputAndResult from '@components/ToolInputAndResult';
|
||||
|
||||
const initialValues = {
|
||||
extractionType: 'smart' as NumberExtractionType,
|
||||
separator: '\\n',
|
||||
printRunningSum: false
|
||||
};
|
||||
const extractionTypes: {
|
||||
title: string;
|
||||
description: string;
|
||||
type: NumberExtractionType;
|
||||
withTextField: boolean;
|
||||
textValueAccessor?: keyof typeof initialValues;
|
||||
}[] = [
|
||||
{
|
||||
title: 'Smart sum',
|
||||
description: 'Auto detect numbers in the input.',
|
||||
type: 'smart',
|
||||
withTextField: false
|
||||
},
|
||||
{
|
||||
title: 'Number Delimiter',
|
||||
type: 'delimiter',
|
||||
description:
|
||||
'Input SeparatorCustomize the number separator here. (By default a line break.)',
|
||||
withTextField: true,
|
||||
textValueAccessor: 'separator'
|
||||
}
|
||||
];
|
||||
|
||||
export default function SplitText() {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<ToolInputAndResult
|
||||
input={<ToolTextInput value={input} onChange={setInput} />}
|
||||
result={<ToolTextResult title={'Total'} value={result} />}
|
||||
/>
|
||||
<ToolOptions
|
||||
getGroups={({ values, updateField }) => [
|
||||
{
|
||||
title: 'Number extraction',
|
||||
component: extractionTypes.map(
|
||||
({
|
||||
title,
|
||||
description,
|
||||
type,
|
||||
withTextField,
|
||||
textValueAccessor
|
||||
}) =>
|
||||
withTextField ? (
|
||||
<RadioWithTextField
|
||||
key={type}
|
||||
checked={type === values.extractionType}
|
||||
title={title}
|
||||
fieldName={'extractionType'}
|
||||
description={description}
|
||||
value={
|
||||
textValueAccessor
|
||||
? values[textValueAccessor].toString()
|
||||
: ''
|
||||
}
|
||||
onRadioClick={() => updateField('extractionType', type)}
|
||||
onTextChange={(val) =>
|
||||
textValueAccessor
|
||||
? updateField(textValueAccessor, val)
|
||||
: null
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<SimpleRadio
|
||||
key={title}
|
||||
onClick={() => updateField('extractionType', type)}
|
||||
checked={values.extractionType === type}
|
||||
description={description}
|
||||
title={title}
|
||||
/>
|
||||
)
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Running Sum',
|
||||
component: (
|
||||
<CheckboxWithDesc
|
||||
title={'Print Running Sum'}
|
||||
description={"Display the sum as it's calculated step by step."}
|
||||
checked={values.printRunningSum}
|
||||
onChange={(value) => updateField('printRunningSum', value)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]}
|
||||
compute={(optionsValues, input) => {
|
||||
const { extractionType, printRunningSum, separator } = optionsValues;
|
||||
setResult(compute(input, extractionType, printRunningSum, separator));
|
||||
}}
|
||||
initialValues={initialValues}
|
||||
input={input}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
14
src/pages/tools/number/sum/meta.ts
Normal file
14
src/pages/tools/number/sum/meta.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
// import image from '@assets/text.png';
|
||||
|
||||
export const tool = defineTool('number', {
|
||||
name: 'Number Sum Calculator',
|
||||
path: 'sum',
|
||||
// image,
|
||||
description:
|
||||
'Quickly calculate the sum of numbers in your browser. To get your sum, just enter your list of numbers in the input field, adjust the separator between the numbers in the options below, and this utility will add up all these numbers.',
|
||||
shortDescription: 'Quickly sum numbers',
|
||||
keywords: ['sum'],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
||||
37
src/pages/tools/number/sum/service.ts
Normal file
37
src/pages/tools/number/sum/service.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export type NumberExtractionType = 'smart' | 'delimiter';
|
||||
|
||||
function getAllNumbers(text: string): number[] {
|
||||
const regex = /\d+/g;
|
||||
const matches = text.match(regex);
|
||||
return matches ? matches.map(Number) : [];
|
||||
}
|
||||
|
||||
export const compute = (
|
||||
input: string,
|
||||
extractionType: NumberExtractionType,
|
||||
printRunningSum: boolean,
|
||||
separator: string
|
||||
): string => {
|
||||
let numbers: number[] = [];
|
||||
if (extractionType === 'smart') {
|
||||
numbers = getAllNumbers(input);
|
||||
} else {
|
||||
const parts = input.split(separator);
|
||||
// Filter out and convert parts that are numbers
|
||||
numbers = parts
|
||||
.filter((part) => !isNaN(Number(part)) && part.trim() !== '')
|
||||
.map(Number);
|
||||
}
|
||||
if (printRunningSum) {
|
||||
let result: string = '';
|
||||
let sum: number = 0;
|
||||
for (const i of numbers) {
|
||||
sum = sum + i;
|
||||
result = result + sum + '\n';
|
||||
}
|
||||
return result;
|
||||
} else
|
||||
return numbers
|
||||
.reduce((previousValue, currentValue) => previousValue + currentValue, 0)
|
||||
.toString();
|
||||
};
|
||||
64
src/pages/tools/number/sum/sum.service.test.ts
Normal file
64
src/pages/tools/number/sum/sum.service.test.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { compute } from './service';
|
||||
|
||||
describe('compute function', () => {
|
||||
it('should correctly sum numbers in smart extraction mode', () => {
|
||||
const input = 'The 2 cats have 4 and 7 kittens';
|
||||
const result = compute(input, 'smart', false, ',');
|
||||
expect(result).toBe('13');
|
||||
});
|
||||
|
||||
it('should correctly sum numbers with custom delimiter', () => {
|
||||
const input = '2,4,7';
|
||||
const result = compute(input, 'delimiter', false, ',');
|
||||
expect(result).toBe('13');
|
||||
});
|
||||
|
||||
it('should return running sum in smart extraction mode', () => {
|
||||
const input = 'The 2 cats have 4 and 7 kittens';
|
||||
const result = compute(input, 'smart', true, ',');
|
||||
expect(result).toBe('2\n6\n13\n');
|
||||
});
|
||||
|
||||
it('should return running sum with custom delimiter', () => {
|
||||
const input = '2,4,7';
|
||||
const result = compute(input, 'delimiter', true, ',');
|
||||
expect(result).toBe('2\n6\n13\n');
|
||||
});
|
||||
|
||||
it('should handle empty input gracefully in smart mode', () => {
|
||||
const input = '';
|
||||
const result = compute(input, 'smart', false, ',');
|
||||
expect(result).toBe('0');
|
||||
});
|
||||
|
||||
it('should handle empty input gracefully in delimiter mode', () => {
|
||||
const input = '';
|
||||
const result = compute(input, 'delimiter', false, ',');
|
||||
expect(result).toBe('0');
|
||||
});
|
||||
|
||||
it('should handle input with no numbers in smart mode', () => {
|
||||
const input = 'There are no numbers here';
|
||||
const result = compute(input, 'smart', false, ',');
|
||||
expect(result).toBe('0');
|
||||
});
|
||||
|
||||
it('should handle input with no numbers in delimiter mode', () => {
|
||||
const input = 'a,b,c';
|
||||
const result = compute(input, 'delimiter', false, ',');
|
||||
expect(result).toBe('0');
|
||||
});
|
||||
|
||||
it('should ignore non-numeric parts in delimiter mode', () => {
|
||||
const input = '2,a,4,b,7';
|
||||
const result = compute(input, 'delimiter', false, ',');
|
||||
expect(result).toBe('13');
|
||||
});
|
||||
|
||||
it('should handle different separators', () => {
|
||||
const input = '2;4;7';
|
||||
const result = compute(input, 'delimiter', false, ';');
|
||||
expect(result).toBe('13');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user