diff --git a/src/pages/tools/string/create-palindrome/index.tsx b/src/pages/tools/string/create-palindrome/index.tsx index 5a45556..ff00f2b 100644 --- a/src/pages/tools/string/create-palindrome/index.tsx +++ b/src/pages/tools/string/create-palindrome/index.tsx @@ -1,11 +1,115 @@ import { Box } from '@mui/material'; -import React from 'react'; -import * as Yup from 'yup'; +import React, { useState, useRef } from 'react'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions'; +import { createPalindromeList } from './service'; +import CheckboxWithDesc from '@components/options/CheckboxWithDesc'; +import ToolInputAndResult from '@components/ToolInputAndResult'; +import ToolExamples, { + CardExampleType +} from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { FormikProps } from 'formik'; -const initialValues = {}; -const validationSchema = Yup.object({ - // splitSeparator: Yup.string().required('The separator is required') -}); -export default function CreatePalindrome() { - return Lorem ipsum; +const initialValues = { + lastChar: true, + multiLine: false +}; + +const exampleCards: CardExampleType[] = [ + { + title: 'Create Simple Palindrome', + description: + 'Creates a palindrome by repeating the text in reverse order, including the last character.', + sampleText: 'level', + sampleResult: 'levellevel', + sampleOptions: { + ...initialValues, + lastChar: true + } + }, + { + title: 'Create Palindrome Without Last Character Duplication', + description: + 'Creates a palindrome without repeating the last character in the reverse part.', + sampleText: 'radar', + sampleResult: 'radarada', + sampleOptions: { + ...initialValues, + lastChar: false + } + }, + { + title: 'Multi-line Palindrome Creation', + description: 'Creates palindromes for each line independently.', + sampleText: 'mom\ndad\nwow', + sampleResult: 'mommom\ndaddad\nwowwow', + sampleOptions: { + ...initialValues, + lastChar: true, + multiLine: true + } + } +]; + +export default function CreatePalindrome({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + const formRef = useRef>(null); + + const computeExternal = ( + optionsValues: typeof initialValues, + input: string + ) => { + const { lastChar, multiLine } = optionsValues; + setResult(createPalindromeList(input, lastChar, multiLine)); + }; + + const getGroups: GetGroupsType = ({ + values, + updateField + }) => [ + { + title: 'Palindrome options', + component: [ + updateField('lastChar', val)} + />, + updateField('multiLine', val)} + /> + ] + } + ]; + + return ( + + } + result={} + /> + + + + ); } diff --git a/src/pages/tools/string/extract-substring/index.tsx b/src/pages/tools/string/extract-substring/index.tsx index bbd3e7d..8cd8974 100644 --- a/src/pages/tools/string/extract-substring/index.tsx +++ b/src/pages/tools/string/extract-substring/index.tsx @@ -1,11 +1,151 @@ import { Box } from '@mui/material'; -import React from 'react'; -import * as Yup from 'yup'; +import React, { useState, useRef } from 'react'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions'; +import { extractSubstring } from './service'; +import TextFieldWithDesc from '@components/options/TextFieldWithDesc'; +import CheckboxWithDesc from '@components/options/CheckboxWithDesc'; +import ToolInputAndResult from '@components/ToolInputAndResult'; +import ToolExamples, { + CardExampleType +} from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { FormikProps } from 'formik'; -const initialValues = {}; -const validationSchema = Yup.object({ - // splitSeparator: Yup.string().required('The separator is required') -}); -export default function ExtractSubstring() { - return Lorem ipsum; +const initialValues = { + start: '1', + length: '5', + multiLine: false, + reverse: false +}; + +const exampleCards: CardExampleType[] = [ + { + title: 'Extract First 5 Characters', + description: 'This example extracts the first 5 characters from the text.', + sampleText: 'The quick brown fox jumps over the lazy dog.', + sampleResult: 'The q', + sampleOptions: { + ...initialValues, + start: '1', + length: '5' + } + }, + { + title: 'Extract Words from the Middle', + description: + 'Extract a substring starting from position 11 with a length of 10 characters.', + sampleText: 'The quick brown fox jumps over the lazy dog.', + sampleResult: 'brown fox', + sampleOptions: { + ...initialValues, + start: '11', + length: '10' + } + }, + { + title: 'Multi-line Extraction with Reversal', + description: 'Extract characters 1-3 from each line and reverse them.', + sampleText: 'First line\nSecond line\nThird line', + sampleResult: 'riF\neS\nihT', + sampleOptions: { + ...initialValues, + start: '1', + length: '3', + multiLine: true, + reverse: true + } + } +]; + +export default function ExtractSubstring({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + const formRef = useRef>(null); + + const computeExternal = ( + optionsValues: typeof initialValues, + input: string + ) => { + const { start, length, multiLine, reverse } = optionsValues; + try { + setResult( + extractSubstring( + input, + parseInt(start, 10), + parseInt(length, 10), + multiLine, + reverse + ) + ); + } catch (error) { + if (error instanceof Error) { + setResult(`Error: ${error.message}`); + } else { + setResult('An unknown error occurred'); + } + } + }; + + const getGroups: GetGroupsType = ({ + values, + updateField + }) => [ + { + title: 'Extraction options', + component: [ + updateField('start', value)} + description="Start position (1-based index)" + type="number" + />, + updateField('length', value)} + description="Number of characters to extract" + type="number" + />, + updateField('multiLine', val)} + />, + updateField('reverse', val)} + /> + ] + } + ]; + + return ( + + } + result={} + /> + + + + ); } diff --git a/src/pages/tools/string/index.ts b/src/pages/tools/string/index.ts index 632cab2..24f6939 100644 --- a/src/pages/tools/string/index.ts +++ b/src/pages/tools/string/index.ts @@ -20,11 +20,11 @@ export const stringTools = [ stringRemoveDuplicateLines, stringToMorse, stringReplace, - stringRepeat - // stringReverse, - // stringRandomizeCase, - // stringUppercase, - // stringExtractSubstring, - // stringCreatePalindrome, - // stringPalindrome + stringRepeat, + stringReverse, + stringRandomizeCase, + stringUppercase, + stringExtractSubstring, + stringCreatePalindrome, + stringPalindrome ]; diff --git a/src/pages/tools/string/palindrome/index.tsx b/src/pages/tools/string/palindrome/index.tsx index 9b5d8ad..c7a9f85 100644 --- a/src/pages/tools/string/palindrome/index.tsx +++ b/src/pages/tools/string/palindrome/index.tsx @@ -1,11 +1,132 @@ import { Box } from '@mui/material'; -import React from 'react'; -import * as Yup from 'yup'; +import React, { useState, useRef } from 'react'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions'; +import { palindromeList, SplitOperatorType } from './service'; +import RadioWithTextField from '@components/options/RadioWithTextField'; +import ToolInputAndResult from '@components/ToolInputAndResult'; +import ToolExamples, { + CardExampleType +} from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { FormikProps } from 'formik'; -const initialValues = {}; -const validationSchema = Yup.object({ - // splitSeparator: Yup.string().required('The separator is required') -}); -export default function Palindrome() { - return Lorem ipsum; +const initialValues = { + splitOperatorType: 'symbol' as SplitOperatorType, + symbolValue: ' ', + regexValue: '\\s+' +}; + +const splitOperators: { + title: string; + description: string; + type: SplitOperatorType; +}[] = [ + { + title: 'Use a Symbol for Splitting', + description: + 'Character that will be used to split text into parts for palindrome checking.', + type: 'symbol' + }, + { + title: 'Use a Regex for Splitting', + type: 'regex', + description: + 'Regular expression that will be used to split text into parts for palindrome checking.' + } +]; + +const exampleCards: CardExampleType[] = [ + { + title: 'Check for Word Palindromes', + description: + 'Checks if each word in the text is a palindrome. Returns "true" for palindromes and "false" for non-palindromes.', + sampleText: 'radar level hello anna', + sampleResult: 'true true false true', + sampleOptions: { + ...initialValues, + symbolValue: ' ' + } + }, + { + title: 'Check CSV Words', + description: 'Checks palindrome status for comma-separated words.', + sampleText: 'mom,dad,wow,test', + sampleResult: 'true true true false', + sampleOptions: { + ...initialValues, + symbolValue: ',' + } + }, + { + title: 'Check with Regular Expression', + description: + 'Use a regular expression to split text and check for palindromes.', + sampleText: 'level:madam;noon|test', + sampleResult: 'true true true false', + sampleOptions: { + ...initialValues, + splitOperatorType: 'regex', + regexValue: '[:|;]|\\|' + } + } +]; + +export default function Palindrome({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + const formRef = useRef>(null); + + const computeExternal = ( + optionsValues: typeof initialValues, + input: string + ) => { + const { splitOperatorType, symbolValue, regexValue } = optionsValues; + const separator = splitOperatorType === 'symbol' ? symbolValue : regexValue; + setResult(palindromeList(splitOperatorType, input, separator)); + }; + + const getGroups: GetGroupsType = ({ + values, + updateField + }) => [ + { + title: 'Splitting options', + component: splitOperators.map(({ title, description, type }) => ( + updateField('splitOperatorType', type)} + onTextChange={(val) => updateField(`${type}Value`, val)} + /> + )) + } + ]; + + return ( + + } + result={} + /> + + + + ); } diff --git a/src/pages/tools/string/randomize-case/index.tsx b/src/pages/tools/string/randomize-case/index.tsx index 33f6b00..1c7a149 100644 --- a/src/pages/tools/string/randomize-case/index.tsx +++ b/src/pages/tools/string/randomize-case/index.tsx @@ -1,11 +1,80 @@ import { Box } from '@mui/material'; -import React from 'react'; -import * as Yup from 'yup'; +import React, { useState, useRef } from 'react'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import ToolOptions from '@components/options/ToolOptions'; +import { randomizeCase } from './service'; +import ToolInputAndResult from '@components/ToolInputAndResult'; +import ToolExamples, { + CardExampleType +} from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { FormikProps } from 'formik'; const initialValues = {}; -const validationSchema = Yup.object({ - // splitSeparator: Yup.string().required('The separator is required') -}); -export default function RandomizeCase() { - return Lorem ipsum; + +const exampleCards: CardExampleType[] = [ + { + title: 'Randomize Text Case', + description: + 'This example turns normal text into a random mix of uppercase and lowercase letters.', + sampleText: 'The quick brown fox jumps over the lazy dog.', + sampleResult: 'tHe qUIcK BrOWn fOx JuMPs ovEr ThE LaZy Dog.', + sampleOptions: {} + }, + { + title: 'Randomize Code Case', + description: + 'Transform code identifiers with randomized case for a chaotic look.', + sampleText: + 'function calculateTotal(price, quantity) { return price * quantity; }', + sampleResult: + 'FuNcTIon cAlCuLAtEtOtaL(pRicE, qUaNTiTy) { rETuRn PrICe * QuAnTiTY; }', + sampleOptions: {} + }, + { + title: 'Randomize a Famous Quote', + description: + 'Give a unique randomized case treatment to a well-known quote.', + sampleText: 'To be or not to be, that is the question.', + sampleResult: 'tO Be oR NoT To bE, ThAt iS ThE QueStIoN.', + sampleOptions: {} + } +]; + +export default function RandomizeCase({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + const formRef = useRef>(null); + + const computeExternal = ( + _optionsValues: typeof initialValues, + input: string + ) => { + setResult(randomizeCase(input)); + }; + + const getGroups = () => []; + + return ( + + } + result={} + /> + + + + ); } diff --git a/src/pages/tools/string/reverse/index.tsx b/src/pages/tools/string/reverse/index.tsx index 1e40781..83c3872 100644 --- a/src/pages/tools/string/reverse/index.tsx +++ b/src/pages/tools/string/reverse/index.tsx @@ -1,11 +1,125 @@ import { Box } from '@mui/material'; -import React from 'react'; -import * as Yup from 'yup'; +import React, { useState, useRef } from 'react'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions'; +import { stringReverser } from './service'; +import CheckboxWithDesc from '@components/options/CheckboxWithDesc'; +import ToolInputAndResult from '@components/ToolInputAndResult'; +import ToolExamples, { + CardExampleType +} from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { FormikProps } from 'formik'; -const initialValues = {}; -const validationSchema = Yup.object({ - // splitSeparator: Yup.string().required('The separator is required') -}); -export default function Reverse() { - return Lorem ipsum; +const initialValues = { + multiLine: true, + emptyItems: false, + trim: false +}; + +const exampleCards: CardExampleType[] = [ + { + title: 'Simple Text Reversal', + description: + 'Reverses each character in the text. Perfect for creating mirror text.', + sampleText: 'Hello World', + sampleResult: 'dlroW olleH', + sampleOptions: { + ...initialValues, + multiLine: false + } + }, + { + title: 'Multi-line Reversal', + description: + 'Reverses each line independently while preserving the line breaks.', + sampleText: 'First line\nSecond line\nThird line', + sampleResult: 'enil tsriF\nenil dnoceS\nenil drihT', + sampleOptions: { + ...initialValues, + multiLine: true + } + }, + { + title: 'Clean Reversed Text', + description: + 'Trims whitespace and skips empty lines before reversing the text.', + sampleText: ' Spaces removed \n\nEmpty line skipped', + sampleResult: 'devomer secapS\ndeppiks enil ytpmE', + sampleOptions: { + ...initialValues, + multiLine: true, + emptyItems: true, + trim: true + } + } +]; + +export default function Reverse({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + const formRef = useRef>(null); + + const computeExternal = ( + optionsValues: typeof initialValues, + input: string + ) => { + const { multiLine, emptyItems, trim } = optionsValues; + setResult(stringReverser(input, multiLine, emptyItems, trim)); + }; + + const getGroups: GetGroupsType = ({ + values, + updateField + }) => [ + { + title: 'Reversal options', + component: [ + updateField('multiLine', val)} + />, + updateField('emptyItems', val)} + />, + updateField('trim', val)} + /> + ] + } + ]; + + return ( + + } + result={} + /> + + + + ); } diff --git a/src/pages/tools/string/uppercase/index.tsx b/src/pages/tools/string/uppercase/index.tsx index c9ee21f..305c4d7 100644 --- a/src/pages/tools/string/uppercase/index.tsx +++ b/src/pages/tools/string/uppercase/index.tsx @@ -1,11 +1,77 @@ import { Box } from '@mui/material'; -import React from 'react'; -import * as Yup from 'yup'; +import React, { useState, useRef } from 'react'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import ToolOptions from '@components/options/ToolOptions'; +import { UppercaseInput } from './service'; +import ToolInputAndResult from '@components/ToolInputAndResult'; +import ToolExamples, { + CardExampleType +} from '@components/examples/ToolExamples'; +import { ToolComponentProps } from '@tools/defineTool'; +import { FormikProps } from 'formik'; const initialValues = {}; -const validationSchema = Yup.object({ - // splitSeparator: Yup.string().required('The separator is required') -}); -export default function Uppercase() { - return Lorem ipsum; + +const exampleCards: CardExampleType[] = [ + { + title: 'Convert Text to Uppercase', + description: 'This example transforms any text to ALL UPPERCASE format.', + sampleText: 'The quick brown fox jumps over the lazy dog.', + sampleResult: 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.', + sampleOptions: {} + }, + { + title: 'Uppercase Code', + description: + 'Convert code to uppercase format. Note that this is for display only and would not maintain code functionality.', + sampleText: 'function example() { return "hello world"; }', + sampleResult: 'FUNCTION EXAMPLE() { RETURN "HELLO WORLD"; }', + sampleOptions: {} + }, + { + title: 'Mixed Case to Uppercase', + description: + 'Transform text with mixed casing to consistent all uppercase format.', + sampleText: 'ThIs Is MiXeD CaSe TeXt!', + sampleResult: 'THIS IS MIXED CASE TEXT!', + sampleOptions: {} + } +]; + +export default function Uppercase({ title }: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + const formRef = useRef>(null); + + const computeExternal = ( + _optionsValues: typeof initialValues, + input: string + ) => { + setResult(UppercaseInput(input)); + }; + + const getGroups = () => []; + + return ( + + } + result={} + /> + + + + ); }