From 09a0e434e873392b1ee0c626fd2f4e906cee83b4 Mon Sep 17 00:00:00 2001 From: Made4Uo Date: Mon, 24 Jun 2024 20:09:16 -0700 Subject: [PATCH 1/5] Add information, examples, and all tools sections --- src/components/ToolsExamples.tsx | 0 src/components/allTools/AllTools.tsx | 36 +++++++ src/components/allTools/ToolCard.tsx | 40 +++++++ src/components/examples/ExampleCard.tsx | 108 +++++++++++++++++++ src/components/examples/Examples.tsx | 57 ++++++++++ src/components/examples/RequiredOptions.tsx | 80 ++++++++++++++ src/components/options/CheckboxWithDesc.tsx | 11 +- src/pages/string/join/Info.tsx | 19 ++++ src/pages/string/join/index.tsx | 110 ++++++++++++++++++++ src/tools/Separator.tsx | 23 ++++ 10 files changed, 482 insertions(+), 2 deletions(-) delete mode 100644 src/components/ToolsExamples.tsx create mode 100644 src/components/allTools/AllTools.tsx create mode 100644 src/components/allTools/ToolCard.tsx create mode 100644 src/components/examples/ExampleCard.tsx create mode 100644 src/components/examples/Examples.tsx create mode 100644 src/components/examples/RequiredOptions.tsx create mode 100644 src/pages/string/join/Info.tsx create mode 100644 src/tools/Separator.tsx diff --git a/src/components/ToolsExamples.tsx b/src/components/ToolsExamples.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/allTools/AllTools.tsx b/src/components/allTools/AllTools.tsx new file mode 100644 index 0000000..d909e7a --- /dev/null +++ b/src/components/allTools/AllTools.tsx @@ -0,0 +1,36 @@ +import { Box, Grid, Stack, Typography } from '@mui/material'; +import ToolCard from './ToolCard'; + +export interface ToolCardProps { + title: string; + description: string; + link: string; +} + +interface AllToolsProps { + title: string; + toolCards: ToolCardProps[]; +} + +export default function AllTools({ title, toolCards }: AllToolsProps) { + return ( + + + {title} + + + + {toolCards.map((card) => ( + + + + ))} + + + + ); +} diff --git a/src/components/allTools/ToolCard.tsx b/src/components/allTools/ToolCard.tsx new file mode 100644 index 0000000..ca62b26 --- /dev/null +++ b/src/components/allTools/ToolCard.tsx @@ -0,0 +1,40 @@ +import { Box, Link, Card, CardContent, Typography } from '@mui/material'; +import { ToolCardProps } from './AllTools'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; + +export default function ToolCard({ title, description, link }: ToolCardProps) { + return ( + + + + + {title} + + + + + + + {description} + + + + ); +} diff --git a/src/components/examples/ExampleCard.tsx b/src/components/examples/ExampleCard.tsx new file mode 100644 index 0000000..28dc89e --- /dev/null +++ b/src/components/examples/ExampleCard.tsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { ExampleCardProps } from './Examples'; +import { + Box, + Stack, + Card, + CardContent, + Typography, + TextField +} from '@mui/material'; +import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; +import RequiredOptions from './RequiredOptions'; + +export default function ExampleCard({ + title, + description, + sampleText, + sampleResult, + requiredOptions +}: ExampleCardProps) { + const handleSampleTextClick = () => { + console.log('TextField clicked'); + }; + + const handleSampleResultClick = () => { + console.log('TextField clicked'); + }; + + return ( + + + + + {title} + + + + + {description} + + + + + + + + + + + + + + ); +} diff --git a/src/components/examples/Examples.tsx b/src/components/examples/Examples.tsx new file mode 100644 index 0000000..1aee760 --- /dev/null +++ b/src/components/examples/Examples.tsx @@ -0,0 +1,57 @@ +import { Box, Grid, Stack, Typography } from '@mui/material'; +import ExampleCard from './ExampleCard'; + +export interface ExampleCardProps { + title: string; + description: string; + sampleText: string; + sampleResult: string; + requiredOptions: RequiredOptionsProps; +} + +export interface RequiredOptionsProps { + joinCharacter: string; + deleteBlankLines: boolean; + deleteTrailingSpaces: boolean; +} + +interface ExampleProps { + title: string; + subtitle: string; + exampleCards: ExampleCardProps[]; +} + +export default function Examples({ + title, + subtitle, + exampleCards +}: ExampleProps) { + return ( + + + + {title} + + + {subtitle} + + + + + + {exampleCards.map((card) => ( + + + + ))} + + + + ); +} diff --git a/src/components/examples/RequiredOptions.tsx b/src/components/examples/RequiredOptions.tsx new file mode 100644 index 0000000..6e76646 --- /dev/null +++ b/src/components/examples/RequiredOptions.tsx @@ -0,0 +1,80 @@ +import { Box, Stack, TextField, Typography } from '@mui/material'; +import { RequiredOptionsProps } from '../../../components/examples/Examples'; +import CheckboxWithDesc from 'components/options/CheckboxWithDesc'; + +export default function RequiredOptions({ + options +}: { + options: RequiredOptionsProps; +}) { + const { joinCharacter, deleteBlankLines, deleteTrailingSpaces } = options; + + const handleBoxClick = () => { + const toolsElement = document.getElementById('tool'); + if (toolsElement) { + toolsElement.scrollIntoView({ behavior: 'smooth' }); + } + console.log('tool clicked'); + }; + + return ( + + + Required options + + + These options will be used automatically if you select this example. + + + + + + + {deleteBlankLines ? ( + + {}} + description="Delete lines that don't have text symbols." + /> + + ) : ( + '' + )} + {deleteTrailingSpaces ? ( + + {}} + description="Remove spaces and tabs at the end of the lines." + /> + + ) : ( + '' + )} + + ); +} diff --git a/src/components/options/CheckboxWithDesc.tsx b/src/components/options/CheckboxWithDesc.tsx index ec49d28..5ad9877 100644 --- a/src/components/options/CheckboxWithDesc.tsx +++ b/src/components/options/CheckboxWithDesc.tsx @@ -5,12 +5,14 @@ const CheckboxWithDesc = ({ title, description, checked, - onChange + onChange, + disabled }: { title: string; description: string; checked: boolean; onChange: (value: boolean) => void; + disabled?: boolean; }) => { const handleChange = (event: React.ChangeEvent) => { onChange(event.target.checked); @@ -20,7 +22,12 @@ const CheckboxWithDesc = ({ + } label={title} /> diff --git a/src/pages/string/join/Info.tsx b/src/pages/string/join/Info.tsx new file mode 100644 index 0000000..a6d01a7 --- /dev/null +++ b/src/pages/string/join/Info.tsx @@ -0,0 +1,19 @@ +import { Box, Stack, Typography } from '@mui/material'; + +interface ExampleProps { + title: string; + description: string; +} + +export default function Example({ title, description }: ExampleProps) { + return ( + + + + {title} + + {description} + + + ); +} diff --git a/src/pages/string/join/index.tsx b/src/pages/string/join/index.tsx index bb4792f..0429ce6 100644 --- a/src/pages/string/join/index.tsx +++ b/src/pages/string/join/index.tsx @@ -10,6 +10,11 @@ import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext'; import TextFieldWithDesc from '../../../components/options/TextFieldWithDesc'; import CheckboxWithDesc from '../../../components/options/CheckboxWithDesc'; +import Info from './Info'; +import Separator from '../../../tools/Separator'; +import AllTools from '../../../components/allTools/AllTools'; +import Examples from '../../../components/examples/Examples'; + const initialValues = { joinCharacter: '', deleteBlank: true, @@ -46,6 +51,99 @@ const blankTrailingOptions: { } ]; +const exampleCards = [ + { + title: 'Merge a To-Do List', + description: + "In this example, we merge a bullet point list into one sentence, separating each item by the word 'and'. We also remove all empty lines and trailing spaces. If we didn't remove the empty lines, then they'd be joined with the separator word, making the separator word appear multiple times. If we didn't remove the trailing tabs and spaces, then they'd create extra spacing in the joined text and it wouldn't look nice.", + sampleText: `clean the house + +go shopping +feed the cat + +make dinner +build a rocket ship and fly away`, + sampleResult: `clean the house and go shopping and feed the cat and make dinner and build a rocket ship and fly away`, + requiredOptions: { + joinCharacter: 'and', + deleteBlankLines: true, + deleteTrailingSpaces: true + } + }, + { + title: 'Comma Separated List', + description: + 'This example joins a column of words into a comma separated list of words.', + sampleText: `computer +memory +processor +mouse +keyboard`, + sampleResult: `computer, memory, processor, mouse, keyboard`, + requiredOptions: { + joinCharacter: ',', + deleteBlankLines: false, + deleteTrailingSpaces: false + } + }, + { + title: 'Vertical Word to Horizontal', + description: + 'This example rotates words from a vertical position to horizontal. An empty separator is used for this purpose.', + sampleText: `T +e +x +t +a +b +u +l +o +u +s +!`, + sampleResult: `Textabulous!`, + requiredOptions: { + joinCharacter: '', + deleteBlankLines: false, + deleteTrailingSpaces: false + } + } +]; + +const toolCards = [ + { + title: 'Split Text', + description: 'Quickly split text into chunks.', + link: '/string/split' + }, + { + title: 'Join Text', + description: 'Quickly merge lines of text together via a delimiter.', + link: '/string/join' + }, + { + title: 'Join Text', + description: 'Quickly merge lines of text together via a delimiter.', + link: '/string/join' + }, + { + title: 'Join Text', + description: 'Quickly merge lines of text together via a delimiter.', + link: '/string/join' + }, + { + title: 'Join Text', + description: 'Quickly merge lines of text together via a delimiter.', + link: '/string/join' + }, + { + title: 'Join Text', + description: 'Quickly merge lines of text together via a delimiter.', + link: '/string/join' + } +]; + export default function JoinText() { const [input, setInput] = useState(''); const { showSnackBar } = useContext(CustomSnackBarContext); @@ -119,6 +217,18 @@ export default function JoinText() { )} + + + + + ); } diff --git a/src/tools/Separator.tsx b/src/tools/Separator.tsx new file mode 100644 index 0000000..ec93302 --- /dev/null +++ b/src/tools/Separator.tsx @@ -0,0 +1,23 @@ +import { Divider } from '@mui/material'; +import React from 'react'; + +type SeparatorProps = { + backgroundColor: string; + margin: string; +}; + +export default function Separator({ backgroundColor, margin }: SeparatorProps) { + return ( + + ); +} From 865bd23e03d0c7fbc65640478a2cb8856a2e3e5e Mon Sep 17 00:00:00 2001 From: Made4Uo Date: Mon, 24 Jun 2024 20:19:49 -0700 Subject: [PATCH 2/5] Fix the ExampleCard Textfields style --- src/components/examples/ExampleCard.tsx | 16 ++++++++++++++-- src/components/examples/RequiredOptions.tsx | 3 +-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/components/examples/ExampleCard.tsx b/src/components/examples/ExampleCard.tsx index 28dc89e..8fee10a 100644 --- a/src/components/examples/ExampleCard.tsx +++ b/src/components/examples/ExampleCard.tsx @@ -50,13 +50,18 @@ export default function ExampleCard({ {description} + @@ -67,6 +72,7 @@ export default function ExampleCard({ multiline sx={{ '& .MuiOutlinedInput-root': { + zIndex: '-1', '& fieldset': { border: 'none' } @@ -74,14 +80,19 @@ export default function ExampleCard({ }} /> + @@ -92,6 +103,7 @@ export default function ExampleCard({ multiline sx={{ '& .MuiOutlinedInput-root': { + zIndex: '-1', '& fieldset': { border: 'none' } diff --git a/src/components/examples/RequiredOptions.tsx b/src/components/examples/RequiredOptions.tsx index 6e76646..3a5c94e 100644 --- a/src/components/examples/RequiredOptions.tsx +++ b/src/components/examples/RequiredOptions.tsx @@ -1,5 +1,5 @@ import { Box, Stack, TextField, Typography } from '@mui/material'; -import { RequiredOptionsProps } from '../../../components/examples/Examples'; +import { RequiredOptionsProps } from './Examples'; import CheckboxWithDesc from 'components/options/CheckboxWithDesc'; export default function RequiredOptions({ @@ -27,7 +27,6 @@ export default function RequiredOptions({ Date: Mon, 24 Jun 2024 21:00:42 -0700 Subject: [PATCH 3/5] Fix the textfield exampls --- src/components/allTools/AllTools.tsx | 4 ++-- src/components/examples/ExampleCard.tsx | 16 ++++------------ src/components/examples/Examples.tsx | 6 ++++-- src/components/examples/RequiredOptions.tsx | 1 - src/components/options/CheckboxWithDesc.tsx | 1 - src/pages/string/join/index.tsx | 19 ++++++++++++++++--- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/components/allTools/AllTools.tsx b/src/components/allTools/AllTools.tsx index d909e7a..e0a5e1f 100644 --- a/src/components/allTools/AllTools.tsx +++ b/src/components/allTools/AllTools.tsx @@ -20,8 +20,8 @@ export default function AllTools({ title, toolCards }: AllToolsProps) { - {toolCards.map((card) => ( - + {toolCards.map((card, index) => ( + { - console.log('TextField clicked'); - }; - - const handleSampleResultClick = () => { - console.log('TextField clicked'); - }; - return ( changeInputResult(sampleText, sampleResult)} sx={{ display: 'flex', zIndex: '2', @@ -83,7 +75,7 @@ export default function ExampleCard({ changeInputResult(sampleText, sampleResult)} sx={{ display: 'flex', zIndex: '2', diff --git a/src/components/examples/Examples.tsx b/src/components/examples/Examples.tsx index 1aee760..26f2930 100644 --- a/src/components/examples/Examples.tsx +++ b/src/components/examples/Examples.tsx @@ -7,6 +7,7 @@ export interface ExampleCardProps { sampleText: string; sampleResult: string; requiredOptions: RequiredOptionsProps; + changeInputResult: (input: string, result: string) => void; } export interface RequiredOptionsProps { @@ -39,14 +40,15 @@ export default function Examples({ - {exampleCards.map((card) => ( - + {exampleCards.map((card, index) => ( + ))} diff --git a/src/components/examples/RequiredOptions.tsx b/src/components/examples/RequiredOptions.tsx index 3a5c94e..d79a325 100644 --- a/src/components/examples/RequiredOptions.tsx +++ b/src/components/examples/RequiredOptions.tsx @@ -14,7 +14,6 @@ export default function RequiredOptions({ if (toolsElement) { toolsElement.scrollIntoView({ behavior: 'smooth' }); } - console.log('tool clicked'); }; return ( diff --git a/src/components/options/CheckboxWithDesc.tsx b/src/components/options/CheckboxWithDesc.tsx index 5ad9877..3f39c77 100644 --- a/src/components/options/CheckboxWithDesc.tsx +++ b/src/components/options/CheckboxWithDesc.tsx @@ -23,7 +23,6 @@ const CheckboxWithDesc = ({ @@ -203,9 +213,9 @@ export default function JoinText() { Blank Lines and Trailing Spaces - {blankTrailingOptions.map((option) => ( + {blankTrailingOptions.map((option, index) => ( setFieldValue(option.accessor, value)} @@ -225,7 +235,10 @@ export default function JoinText() { ({ + ...card, + changeInputResult + }))} /> From 2b8dcdbd64b03d8ec291699788697c8aeba0919c Mon Sep 17 00:00:00 2001 From: "Ibrahima G. Coulibaly" Date: Tue, 25 Jun 2024 08:39:29 +0100 Subject: [PATCH 4/5] feat: shortDescription --- .idea/workspace.xml | 84 +++++++++++-------- scripts/create-tool.mjs | 1 + src/components/ToolInputAndResult.tsx | 2 +- src/components/ToolLayout.tsx | 19 ++++- src/components/allTools/ToolCard.tsx | 6 +- src/components/examples/ExampleCard.tsx | 6 +- src/components/examples/Examples.tsx | 2 +- src/components/input/ToolTextInput.tsx | 2 +- src/pages/home/index.tsx | 2 +- .../image/png/change-colors-in-png/meta.ts | 1 + .../image/png/create-transparent/meta.ts | 1 + src/pages/number/sum/meta.ts | 1 + src/pages/string/join/index.tsx | 35 -------- src/pages/string/join/meta.ts | 1 + src/pages/string/split/meta.ts | 1 + src/pages/string/to-morse/meta.ts | 1 + src/tools/defineTool.tsx | 20 ++++- src/tools/index.ts | 3 + 18 files changed, 110 insertions(+), 78 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 142bd3f..0f9921a 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,8 +6,23 @@ + + + + + + + + + - + + + + + + + ); diff --git a/src/components/allTools/ToolCard.tsx b/src/components/allTools/ToolCard.tsx index ca62b26..7a2dc98 100644 --- a/src/components/allTools/ToolCard.tsx +++ b/src/components/allTools/ToolCard.tsx @@ -1,17 +1,21 @@ import { Box, Link, Card, CardContent, Typography } from '@mui/material'; import { ToolCardProps } from './AllTools'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import { useNavigate } from 'react-router-dom'; export default function ToolCard({ title, description, link }: ToolCardProps) { + const navigate = useNavigate(); return ( navigate(link)} raised sx={{ borderRadius: 2, bgcolor: '#5581b5', borderColor: '#5581b5', color: '#fff', - boxShadow: '6px 6px 12px #b8b9be, -6px -6px 12px #fff' + boxShadow: '6px 6px 12px #b8b9be, -6px -6px 12px #fff', + cursor: 'pointer' }} > diff --git a/src/components/examples/ExampleCard.tsx b/src/components/examples/ExampleCard.tsx index abde54d..e756fa5 100644 --- a/src/components/examples/ExampleCard.tsx +++ b/src/components/examples/ExampleCard.tsx @@ -5,7 +5,8 @@ import { Card, CardContent, Typography, - TextField + TextField, + useTheme } from '@mui/material'; import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; import RequiredOptions from './RequiredOptions'; @@ -18,11 +19,12 @@ export default function ExampleCard({ requiredOptions, changeInputResult }: ExampleCardProps) { + const theme = useTheme(); return ( + {title} diff --git a/src/components/input/ToolTextInput.tsx b/src/components/input/ToolTextInput.tsx index d5a666d..cc2d344 100644 --- a/src/components/input/ToolTextInput.tsx +++ b/src/components/input/ToolTextInput.tsx @@ -46,7 +46,7 @@ export default function ToolTextInput({ fileInputRef.current?.click(); }; return ( - + {option.name} - {option.description} + {option.shortDescription} )} diff --git a/src/pages/image/png/change-colors-in-png/meta.ts b/src/pages/image/png/change-colors-in-png/meta.ts index dd87e03..bdf461c 100644 --- a/src/pages/image/png/change-colors-in-png/meta.ts +++ b/src/pages/image/png/change-colors-in-png/meta.ts @@ -8,6 +8,7 @@ export const tool = defineTool('png', { image, description: "World's simplest online Portable Network Graphics (PNG) color changer. Just import your PNG image in the editor on the left, select which colors to change, and you'll instantly get a new PNG with the new colors on the right. Free, quick, and very powerful. Import a PNG – replace its colors.", + shortDescription: 'Quickly swap colors in a PNG image', keywords: ['change', 'colors', 'in', 'png'], component: lazy(() => import('./index')) }); diff --git a/src/pages/image/png/create-transparent/meta.ts b/src/pages/image/png/create-transparent/meta.ts index 8362377..af2daf3 100644 --- a/src/pages/image/png/create-transparent/meta.ts +++ b/src/pages/image/png/create-transparent/meta.ts @@ -6,6 +6,7 @@ export const tool = defineTool('png', { name: 'Create transparent PNG', path: 'create-transparent', image, + shortDescription: 'Quickly make a PNG image transparent', description: "World's simplest online Portable Network Graphics transparency maker. Just import your PNG image in the editor on the left and you will instantly get a transparent PNG on the right. Free, quick, and very powerful. Import a PNG – get a transparent PNG.", keywords: ['create', 'transparent'], diff --git a/src/pages/number/sum/meta.ts b/src/pages/number/sum/meta.ts index ffc8520..fc96799 100644 --- a/src/pages/number/sum/meta.ts +++ b/src/pages/number/sum/meta.ts @@ -8,6 +8,7 @@ export const tool = defineTool('number', { // 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')) }); diff --git a/src/pages/string/join/index.tsx b/src/pages/string/join/index.tsx index 8ff3f9d..33fa5df 100644 --- a/src/pages/string/join/index.tsx +++ b/src/pages/string/join/index.tsx @@ -113,39 +113,6 @@ s } ]; -const toolCards = [ - { - title: 'Split Text', - description: 'Quickly split text into chunks.', - link: '/string/split' - }, - { - title: 'Join Text', - description: 'Quickly merge lines of text together via a delimiter.', - link: '/string/join' - }, - { - title: 'Join Text', - description: 'Quickly merge lines of text together via a delimiter.', - link: '/string/join' - }, - { - title: 'Join Text', - description: 'Quickly merge lines of text together via a delimiter.', - link: '/string/join' - }, - { - title: 'Join Text', - description: 'Quickly merge lines of text together via a delimiter.', - link: '/string/join' - }, - { - title: 'Join Text', - description: 'Quickly merge lines of text together via a delimiter.', - link: '/string/join' - } -]; - export default function JoinText() { const [input, setInput] = useState(''); const { showSnackBar } = useContext(CustomSnackBarContext); @@ -246,8 +213,6 @@ export default function JoinText() { changeInputResult }))} /> - - ); } diff --git a/src/pages/string/join/meta.ts b/src/pages/string/join/meta.ts index 1686be5..aedfe3f 100644 --- a/src/pages/string/join/meta.ts +++ b/src/pages/string/join/meta.ts @@ -8,6 +8,7 @@ export const tool = defineTool('string', { image, description: "World's Simplest Text Tool World's simplest browser-based utility for joining text. Load your text in the input form on the left and you'll automatically get merged text on the right. Powerful, free, and fast. Load text – get joined lines", + shortDescription: 'Quickly merge texts', keywords: ['text', 'join'], component: lazy(() => import('./index')) }); diff --git a/src/pages/string/split/meta.ts b/src/pages/string/split/meta.ts index 09b4f40..01acca2 100644 --- a/src/pages/string/split/meta.ts +++ b/src/pages/string/split/meta.ts @@ -8,6 +8,7 @@ export const tool = defineTool('string', { image, description: "World's simplest browser-based utility for splitting text. Load your text in the input form on the left and you'll automatically get pieces of this text on the right. Powerful, free, and fast. Load text – get chunks.", + shortDescription: 'Quickly split a text', keywords: ['text', 'split'], component: lazy(() => import('./index')) }); diff --git a/src/pages/string/to-morse/meta.ts b/src/pages/string/to-morse/meta.ts index 80b2b4d..78774f5 100644 --- a/src/pages/string/to-morse/meta.ts +++ b/src/pages/string/to-morse/meta.ts @@ -8,6 +8,7 @@ export const tool = defineTool('string', { // image, description: "World's simplest browser-based utility for converting text to Morse code. Load your text in the input form on the left and you'll instantly get Morse code in the output area. Powerful, free, and fast. Load text – get Morse code.", + shortDescription: 'Quickly encode text to morse', keywords: ['to', 'morse'], component: lazy(() => import('./index')) }); diff --git a/src/tools/defineTool.tsx b/src/tools/defineTool.tsx index 91d489c..c05729c 100644 --- a/src/tools/defineTool.tsx +++ b/src/tools/defineTool.tsx @@ -8,6 +8,7 @@ interface ToolOptions { image?: string; name: string; description: string; + shortDescription: string; } export interface DefinedTool { @@ -15,6 +16,7 @@ export interface DefinedTool { path: string; name: string; description: string; + shortDescription: string; image?: string; keywords: string[]; component: () => JSX.Element; @@ -24,7 +26,15 @@ export const defineTool = ( basePath: string, options: ToolOptions ): DefinedTool => { - const { image, path, name, description, keywords, component } = options; + const { + image, + path, + name, + description, + keywords, + component, + shortDescription + } = options; const Component = component; return { type: basePath, @@ -32,10 +42,16 @@ export const defineTool = ( name, image, description, + shortDescription, keywords, component: () => { return ( - + ); diff --git a/src/tools/index.ts b/src/tools/index.ts index f460aa9..e0f645a 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -38,6 +38,7 @@ export const filterTools = ( (tool) => tool.name.toLowerCase().includes(lowerCaseQuery) || tool.description.toLowerCase().includes(lowerCaseQuery) || + tool.shortDescription.toLowerCase().includes(lowerCaseQuery) || tool.keywords.some((keyword) => keyword.toLowerCase().includes(lowerCaseQuery) ) @@ -49,6 +50,7 @@ export const getToolsByCategory = (): { description: string; type: string; example: { title: string; path: string }; + tools: DefinedTool[]; }[] => { const grouped: Partial> = Object.groupBy( tools, @@ -60,6 +62,7 @@ export const getToolsByCategory = (): { description: categoriesDescriptions.find((desc) => desc.type === type)?.value ?? '', type, + tools: tls ?? [], example: tls ? { title: tls[0].name, path: tls[0].path } : { title: '', path: '' } From 429ca0968618636f40c52ce56c21d129b1ff6f9f Mon Sep 17 00:00:00 2001 From: "Ibrahima G. Coulibaly" Date: Tue, 25 Jun 2024 09:35:44 +0100 Subject: [PATCH 5/5] feat: tools by category --- .idea/workspace.xml | 44 +++---- src/assets/tools.png | Bin 0 -> 22504 bytes src/components/Hero.tsx | 100 +++++++++++++++ src/components/ToolLayout.tsx | 6 +- src/config/routesConfig.tsx | 5 + src/pages/home/index.tsx | 173 ++++++-------------------- src/pages/tools-by-category/index.tsx | 74 +++++++++++ src/utils/string.ts | 3 +- 8 files changed, 239 insertions(+), 166 deletions(-) create mode 100644 src/assets/tools.png create mode 100644 src/components/Hero.tsx create mode 100644 src/pages/tools-by-category/index.tsx diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 0f9921a..e28bb3a 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,25 +4,15 @@ ); diff --git a/src/config/routesConfig.tsx b/src/config/routesConfig.tsx index 54f2445..a68b548 100644 --- a/src/config/routesConfig.tsx +++ b/src/config/routesConfig.tsx @@ -3,12 +3,17 @@ import { Navigate } from 'react-router-dom'; import { lazy } from 'react'; const Home = lazy(() => import('../pages/home')); +const ToolsByCategory = lazy(() => import('../pages/tools-by-category')); const routes: RouteObject[] = [ { path: '/', element: }, + { + path: '/categories/:categoryName', + element: + }, { path: '*', element: diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 8d3cae7..5a1c51b 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -1,45 +1,14 @@ -import { - Autocomplete, - Box, - Card, - CardContent, - Stack, - TextField -} from '@mui/material'; +import { Box, Card, CardContent, Stack } from '@mui/material'; import Grid from '@mui/material/Grid'; import Typography from '@mui/material/Typography'; -import SearchIcon from '@mui/icons-material/Search'; import { Link, useNavigate } from 'react-router-dom'; -import { filterTools, getToolsByCategory, tools } from '../../tools'; -import { useState } from 'react'; -import { DefinedTool } from '@tools/defineTool'; +import { getToolsByCategory } from '../../tools'; import Button from '@mui/material/Button'; +import Hero from 'components/Hero'; -const exampleTools: { label: string; url: string }[] = [ - { - label: 'Create a transparent image', - url: '/png/create-transparent' - }, - { label: 'Convert text to morse code', url: '/string/to-morse' }, - { label: 'Change GIF speed', url: '' }, - { label: 'Pick a random item', url: '' }, - { label: 'Find and replace text', url: '' }, - { label: 'Convert emoji to image', url: '' }, - { label: 'Split a string', url: '/string/split' }, - { label: 'Calculate number sum', url: '/number/sum' }, - { label: 'Pixelate an image', url: '' } -]; export default function Home() { const navigate = useNavigate(); - const [inputValue, setInputValue] = useState(''); - const [filteredTools, setFilteredTools] = useState(tools); - const handleInputChange = ( - event: React.ChangeEvent<{}>, - newInputValue: string - ) => { - setInputValue(newInputValue); - setFilteredTools(filterTools(tools, newInputValue)); - }; + return ( - - - Transform Your Workflow with - - Omni Tools - - - - Boost your productivity with Omni Tools, the ultimate toolkit for - getting things done quickly! Access thousands of user-friendly - utilities for editing images, text, lists, and data, all directly from - your browser. - - - option.name} - renderInput={(params) => ( - - }} - onChange={(event) => handleInputChange(event, event.target.value)} - /> - )} - renderOption={(props, option) => ( - navigate(option.path)} - > - - {option.name} - {option.shortDescription} - - - )} - /> - - {exampleTools.map((tool) => ( - navigate(tool.url)} - item - xs={4} - key={tool.label} - > - - {tool.label} - - - ))} - - - {getToolsByCategory().map((category) => ( - - - - - {category.title} - - {category.description} - - - - - - - - ))} - - + + + {getToolsByCategory().map((category) => ( + + + + + {category.title} + + {category.description} + + + + + + + + ))} + ); } diff --git a/src/pages/tools-by-category/index.tsx b/src/pages/tools-by-category/index.tsx new file mode 100644 index 0000000..658151f --- /dev/null +++ b/src/pages/tools-by-category/index.tsx @@ -0,0 +1,74 @@ +import { + Box, + Card, + CardContent, + Divider, + Stack, + useTheme +} from '@mui/material'; +import Grid from '@mui/material/Grid'; +import Typography from '@mui/material/Typography'; +import { Link, useNavigate, useParams } from 'react-router-dom'; +import { getToolsByCategory, tools } from '../../tools'; +import Button from '@mui/material/Button'; +import Hero from 'components/Hero'; +import AllTools from '../../components/allTools/AllTools'; +import { capitalizeFirstLetter } from '../../utils/string'; +import toolsPng from '@assets/tools.png'; + +export default function Home() { + const navigate = useNavigate(); + const theme = useTheme(); + const { categoryName } = useParams(); + return ( + + + + + + + {`All ${capitalizeFirstLetter(categoryName)} Tools`} + + {getToolsByCategory() + .find(({ type }) => type === categoryName) + ?.tools?.map((tool) => ( + + navigate('/' + tool.path)} + direction={'row'} + spacing={2} + padding={2} + border={1} + borderRadius={2} + > + + + {tool.name} + + {tool.shortDescription} + + + + + ))} + + + + ); +} diff --git a/src/utils/string.ts b/src/utils/string.ts index 2d08599..7662701 100644 --- a/src/utils/string.ts +++ b/src/utils/string.ts @@ -1,3 +1,4 @@ -export function capitalizeFirstLetter(string: string) { +export function capitalizeFirstLetter(string: string | undefined) { + if (!string) return ''; return string.charAt(0).toUpperCase() + string.slice(1); }