mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-21 23:19:30 +02:00
fix: misc
This commit is contained in:
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
@@ -71,10 +71,12 @@ export default function Hero() {
|
||||
{...params}
|
||||
fullWidth
|
||||
placeholder={'Search all tools'}
|
||||
sx={{ borderRadius: 2 }}
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: <SearchIcon />
|
||||
endAdornment: <SearchIcon />,
|
||||
sx: {
|
||||
borderRadius: 4
|
||||
}
|
||||
}}
|
||||
onChange={(event) => handleInputChange(event, event.target.value)}
|
||||
/>
|
||||
@@ -112,7 +114,8 @@ export default function Hero() {
|
||||
borderRadius: 3,
|
||||
borderColor: 'grey',
|
||||
borderStyle: 'solid',
|
||||
cursor: 'pointer'
|
||||
cursor: 'pointer',
|
||||
'&:hover': { backgroundColor: '#FAFAFD' }
|
||||
}}
|
||||
>
|
||||
<Typography>{tool.label}</Typography>
|
||||
|
@@ -1,12 +1,11 @@
|
||||
import React, { useState } from 'react';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Button from '@mui/material/Button';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import githubIcon from '@assets/github-mark.png'; // Adjust the path to your GitHub icon
|
||||
import logo from 'assets/logo.png';
|
||||
import {
|
||||
Drawer,
|
||||
List,
|
||||
@@ -22,7 +21,6 @@ const Navbar: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
|
||||
const toggleDrawer = (open: boolean) => () => {
|
||||
setDrawerOpen(open);
|
||||
};
|
||||
@@ -55,17 +53,12 @@ const Navbar: React.FC = () => {
|
||||
style={{ backgroundColor: 'white', color: 'black' }}
|
||||
>
|
||||
<Toolbar sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography
|
||||
<img
|
||||
onClick={() => navigate('/')}
|
||||
fontSize={25}
|
||||
sx={{
|
||||
cursor: 'pointer',
|
||||
textShadow: '1px 1px 2px rgba(0,0,0,0.2)'
|
||||
}}
|
||||
color={'primary'}
|
||||
>
|
||||
OmniTools
|
||||
</Typography>
|
||||
style={{ cursor: 'pointer' }}
|
||||
src={logo}
|
||||
width={isMobile ? '80px' : '150px'}
|
||||
/>
|
||||
{isMobile ? (
|
||||
<>
|
||||
<IconButton
|
||||
|
86
src/pages/home/Categories.tsx
Normal file
86
src/pages/home/Categories.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import { getToolsByCategory } from '@tools/index';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import { Card, CardContent, Stack } from '@mui/material';
|
||||
import { HugeiconsIcon } from '@hugeicons/react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Button from '@mui/material/Button';
|
||||
import { useState } from 'react';
|
||||
|
||||
type ArrayElement<ArrayType extends readonly unknown[]> =
|
||||
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
||||
|
||||
const SingleCategory = function ({
|
||||
category,
|
||||
index
|
||||
}: {
|
||||
category: ArrayElement<ReturnType<typeof getToolsByCategory>>;
|
||||
index: number;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const [hovered, setHovered] = useState<boolean>(false);
|
||||
const Icon = category.icon;
|
||||
const toggleHover = () => setHovered((prevState) => !prevState);
|
||||
return (
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={6}
|
||||
onMouseEnter={toggleHover}
|
||||
onMouseLeave={toggleHover}
|
||||
>
|
||||
<Card
|
||||
sx={{
|
||||
height: '100%',
|
||||
backgroundColor: hovered ? '#FAFAFD' : 'white'
|
||||
}}
|
||||
>
|
||||
<CardContent>
|
||||
<Stack direction={'row'} spacing={2} alignItems={'center'}>
|
||||
<HugeiconsIcon
|
||||
icon={Icon}
|
||||
style={{
|
||||
transform: `scale(${hovered ? 1.1 : 1}`
|
||||
}}
|
||||
color={categoriesColors[index % categoriesColors.length]}
|
||||
/>
|
||||
<Link
|
||||
style={{ fontSize: 20, fontWeight: 700, color: 'black' }}
|
||||
to={'/categories/' + category.type}
|
||||
>
|
||||
{category.title}
|
||||
</Link>
|
||||
</Stack>
|
||||
<Typography sx={{ mt: 2 }}>{category.description}</Typography>
|
||||
<Grid mt={1} container spacing={2}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={() => navigate('/categories/' + category.type)}
|
||||
variant={'contained'}
|
||||
>{`See all ${category.title}`}</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Button
|
||||
sx={{ backgroundColor: 'white' }}
|
||||
fullWidth
|
||||
onClick={() => navigate(category.example.path)}
|
||||
variant={'outlined'}
|
||||
>{`Try ${category.example.title}`}</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
const categoriesColors: string[] = ['#8FBC5D', '#3CB6E2', '#FFD400', '#AB6993'];
|
||||
export default function Categories() {
|
||||
return (
|
||||
<Grid width={'80%'} container mt={2} spacing={2}>
|
||||
{getToolsByCategory().map((category, index) => (
|
||||
<SingleCategory key={category.type} category={category} index={index} />
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
}
|
@@ -1,14 +1,8 @@
|
||||
import { Box, Card, CardContent } from '@mui/material';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { getToolsByCategory } from '../../tools';
|
||||
import Button from '@mui/material/Button';
|
||||
import { Box } from '@mui/material';
|
||||
import Hero from 'components/Hero';
|
||||
import Categories from './Categories';
|
||||
|
||||
export default function Home() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Box
|
||||
padding={{ xs: 1, md: 3, lg: 5 }}
|
||||
@@ -19,39 +13,7 @@ export default function Home() {
|
||||
width={'100%'}
|
||||
>
|
||||
<Hero />
|
||||
<Grid width={'80%'} container mt={2} spacing={2}>
|
||||
{getToolsByCategory().map((category) => (
|
||||
<Grid key={category.type} item xs={12} md={6}>
|
||||
<Card sx={{ height: '100%' }}>
|
||||
<CardContent>
|
||||
<Link
|
||||
style={{ fontSize: 20 }}
|
||||
to={'/categories/' + category.type}
|
||||
>
|
||||
{category.title}
|
||||
</Link>
|
||||
<Typography sx={{ mt: 2 }}>{category.description}</Typography>
|
||||
<Grid mt={1} container spacing={2}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={() => navigate('/categories/' + category.type)}
|
||||
variant={'contained'}
|
||||
>{`See all ${category.title}`}</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={() => navigate(category.example.path)}
|
||||
variant={'outlined'}
|
||||
>{`Try ${category.example.title}`}</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
<Categories />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@@ -17,9 +17,9 @@ export const listTools = [
|
||||
listFindUnique,
|
||||
listFindMostPopular,
|
||||
listGroup,
|
||||
listWrap,
|
||||
// listWrap,
|
||||
listRotate,
|
||||
listShuffle,
|
||||
listTruncate,
|
||||
listDuplicate
|
||||
listShuffle
|
||||
// listTruncate,
|
||||
// listDuplicate
|
||||
];
|
||||
|
@@ -11,11 +11,11 @@ import { tool as stringJoin } from './join/meta';
|
||||
export const stringTools = [
|
||||
stringSplit,
|
||||
stringJoin,
|
||||
stringToMorse,
|
||||
stringReverse,
|
||||
stringRandomizeCase,
|
||||
stringUppercase,
|
||||
stringExtractSubstring,
|
||||
stringCreatePalindrome,
|
||||
stringPalindrome
|
||||
stringToMorse
|
||||
// stringReverse,
|
||||
// stringRandomizeCase,
|
||||
// stringUppercase,
|
||||
// stringExtractSubstring,
|
||||
// stringCreatePalindrome,
|
||||
// stringPalindrome
|
||||
];
|
||||
|
@@ -6,42 +6,56 @@ import { numberTools } from '../pages/tools/number';
|
||||
import { videoTools } from '../pages/tools/video';
|
||||
import { listTools } from '../pages/tools/list';
|
||||
import { Entries } from 'type-fest';
|
||||
import {
|
||||
ArrangeByNumbers19Icon,
|
||||
Gif01Icon,
|
||||
HugeiconsIcon,
|
||||
LeftToRightListBulletIcon,
|
||||
Png01Icon,
|
||||
TextIcon
|
||||
} from '@hugeicons/core-free-icons';
|
||||
|
||||
export const tools: DefinedTool[] = [
|
||||
...imageTools,
|
||||
...stringTools,
|
||||
...numberTools,
|
||||
...listTools,
|
||||
...videoTools,
|
||||
...listTools
|
||||
...numberTools
|
||||
];
|
||||
const categoriesConfig: {
|
||||
type: ToolCategory;
|
||||
value: string;
|
||||
title?: string;
|
||||
icon: typeof HugeiconsIcon;
|
||||
}[] = [
|
||||
{
|
||||
type: 'string',
|
||||
title: 'Text',
|
||||
icon: TextIcon,
|
||||
value:
|
||||
'Tools for working with text – convert text to images, find and replace text, split text into fragments, join text lines, repeat text, and much more.'
|
||||
},
|
||||
{
|
||||
type: 'png',
|
||||
icon: Png01Icon,
|
||||
value:
|
||||
'Tools for working with PNG images – convert PNGs to JPGs, create transparent PNGs, change PNG colors, crop, rotate, resize PNGs, and much more.'
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
icon: ArrangeByNumbers19Icon,
|
||||
value:
|
||||
'Tools for working with numbers – generate number sequences, convert numbers to words and words to numbers, sort, round, factor numbers, and much more.'
|
||||
},
|
||||
{
|
||||
type: 'gif',
|
||||
icon: Gif01Icon,
|
||||
value:
|
||||
'Tools for working with GIF animations – create transparent GIFs, extract GIF frames, add text to GIF, crop, rotate, reverse GIFs, and much more.'
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
icon: LeftToRightListBulletIcon,
|
||||
value:
|
||||
'Tools for working with lists – sort, reverse, randomize lists, find unique and duplicate list items, change list item separators, and much more.'
|
||||
}
|
||||
@@ -68,6 +82,7 @@ export const filterTools = (
|
||||
export const getToolsByCategory = (): {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: typeof HugeiconsIcon;
|
||||
type: string;
|
||||
example: { title: string; path: string };
|
||||
tools: DefinedTool[];
|
||||
@@ -76,14 +91,14 @@ export const getToolsByCategory = (): {
|
||||
Object.groupBy(tools, ({ type }) => type);
|
||||
return (Object.entries(groupedByType) as Entries<typeof groupedByType>).map(
|
||||
([type, tools]) => {
|
||||
const categoryConfig = categoriesConfig.find(
|
||||
(config) => config.type === type
|
||||
);
|
||||
return {
|
||||
title: `${
|
||||
categoriesConfig.find((config) => config.type === type)?.title ??
|
||||
capitalizeFirstLetter(type)
|
||||
} Tools`,
|
||||
description:
|
||||
categoriesConfig.find((desc) => desc.type === type)?.value ?? '',
|
||||
title: `${categoryConfig?.title ?? capitalizeFirstLetter(type)} Tools`,
|
||||
description: categoryConfig?.value ?? '',
|
||||
type,
|
||||
icon: categoryConfig!.icon,
|
||||
tools: tools ?? [],
|
||||
example: tools
|
||||
? { title: tools[0].name, path: tools[0].path }
|
||||
|
Reference in New Issue
Block a user