From b02c9d61698e42b44c8df71d56bcade897a169c4 Mon Sep 17 00:00:00 2001 From: rusconn Date: Thu, 24 Mar 2022 01:53:39 +0000 Subject: [PATCH] feat: add all tools page mock --- README.md | 2 +- package.json | 1 + src/components/common/Main.tsx | 25 ++++ src/components/common/index.ts | 3 + src/components/pages/home/Card.tsx | 96 ++++++++++++++++ src/components/pages/home/Content.tsx | 158 ++++++++++++++++++++++++++ src/components/pages/home/index.ts | 3 + src/pages/index.tsx | 4 +- yarn.lock | 5 + 9 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 src/components/common/Main.tsx create mode 100644 src/components/common/index.ts create mode 100644 src/components/pages/home/Card.tsx create mode 100644 src/components/pages/home/Content.tsx create mode 100644 src/components/pages/home/index.ts diff --git a/README.md b/README.md index a140263..038a7a5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A web clone of [DevToys](https://github.com/veler/DevToys) ## Todo - [x] Add site layout -- [ ] Add all tools page mock +- [x] Add all tools page mock - [ ] Implement tools - [ ] Converters - [ ] Encoders / Decoders diff --git a/package.json b/package.json index dd9a0a9..62c8d26 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@mui/icons-material": "^5.5.1", "@mui/material": "^5.5.1", "fast-deep-equal": "^3.1.3", + "fuse.js": "^6.5.3", "next": "12.1.0", "react": "17.0.2", "react-dom": "17.0.2", diff --git a/src/components/common/Main.tsx b/src/components/common/Main.tsx new file mode 100644 index 0000000..bd56341 --- /dev/null +++ b/src/components/common/Main.tsx @@ -0,0 +1,25 @@ +import { Box, css, Stack, Theme, Typography } from "@mui/material"; +import { memo, PropsWithChildren } from "react"; + +type Props = PropsWithChildren<{ + title: string; +}>; + +const mainTitle = (theme: Theme) => css` + font-size: ${theme.typography.fontSize * 3}px; + font-weight: 400; + margin-bottom: ${theme.spacing(2)}; +`; + +const StyledComponent = ({ children, title }: Props) => ( + + + {title} + + {children} + +); + +export const Component = memo(StyledComponent); + +export default Component; diff --git a/src/components/common/index.ts b/src/components/common/index.ts new file mode 100644 index 0000000..c5caf67 --- /dev/null +++ b/src/components/common/index.ts @@ -0,0 +1,3 @@ +import Main from "./Main"; + +export { Main }; diff --git a/src/components/pages/home/Card.tsx b/src/components/pages/home/Card.tsx new file mode 100644 index 0000000..f6a8ed2 --- /dev/null +++ b/src/components/pages/home/Card.tsx @@ -0,0 +1,96 @@ +import { + Box, + Card, + CardActionArea, + CardContent, + CardMedia, + css, + Theme, + Tooltip, + Typography, +} from "@mui/material"; +import NextLink, { LinkProps } from "next/link"; +import { memo, ReactNode } from "react"; + +type Props = { + icon: ReactNode; + title: string; + description: string; + disabled?: boolean; +} & Pick; + +const cardStyle = css` + text-align: left; + width: 160px; + height: 300px; +`; + +const cardActionArea = css` + height: 100%; +`; + +const cardMedia = (theme: Theme) => css` + text-align: center; + padding: ${theme.spacing(4)}; +`; + +const cardMediaIconWrapper = (theme: Theme) => css` + padding: ${theme.spacing(2)}; + height: 96px; + > * { + width: 100%; + height: 100%; + } +`; + +const cardContent = css` + padding-top: 0; +`; + +const cardTitle = css` + font-size: 14px; + font-weight: 500; +`; + +const cardDescription = (theme: Theme) => css` + font-size: 12px; + color: ${theme.palette.grey[600]}; +`; + +const StyledComponent = ({ icon, title, description, href, disabled }: Props) => { + const card = ( + + + + + {icon} + + + + {title} + + + {description} + + + + + + ); + + return disabled ? ( + + {card} + + ) : ( + card + ); +}; + +export const Component = memo(StyledComponent); + +export default Component; diff --git a/src/components/pages/home/Content.tsx b/src/components/pages/home/Content.tsx new file mode 100644 index 0000000..b41e6f4 --- /dev/null +++ b/src/components/pages/home/Content.tsx @@ -0,0 +1,158 @@ +import CodeIcon from "@mui/icons-material/Code"; +import DataObjectIcon from "@mui/icons-material/DataObject"; +import DragHandleIcon from "@mui/icons-material/DragHandle"; +import FilterIcon from "@mui/icons-material/Filter"; +import FingerprintIcon from "@mui/icons-material/Fingerprint"; +import KeyIcon from "@mui/icons-material/Key"; +import LinkIcon from "@mui/icons-material/Link"; +import NumbersIcon from "@mui/icons-material/Numbers"; +import TextIncreaseIcon from "@mui/icons-material/TextIncrease"; +import TransformIcon from "@mui/icons-material/Transform"; +import { Grid } from "@mui/material"; +import Fuse from "fuse.js"; +import { memo } from "react"; +import { selector, useRecoilValue } from "recoil"; + +import { Main } from "@/components/common"; +import { searchTextState } from "@/components/layout/states"; +import { pagesPath } from "@/libs/$path"; + +import Card from "./Card"; + +type Props = { + filteredTools: typeof tools; +}; + +const tools = [ + { + icon: , + title: "Json <> Yaml Converter", + description: "Convert Json data to Yaml and vice versa", + keywords: "json yaml converter", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "Number Base Converter", + description: "Convert numbers from one base to another", + keywords: "number base converter", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "HTML Encoder / Decoder", + description: + "Encode or decode all the applicable characters to their corresponding HTML entities", + keywords: "html encoder escaper decocder unescaper", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "URL Encoder / Decoder", + description: + "Encode or decode all the applicable characters to their corresponding URL entities", + keywords: "url encoder escaper decocder unescaper", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "Base 64 Encoder / Decoder", + description: "Encode and decode Base64 data", + keywords: "base64 encoder decocder", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "JWT Decoder", + description: "Decode a JWT header, payload and signature", + keywords: "jwt json web token decocder", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "JSON Formatter", + description: "Indent or minify JSON data", + keywords: "json formatter", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "Hash Generator", + description: "Calculate MD5, SHA1, SHA256 and SHA512 hash from text data", + keywords: "hash generator md5 sha1 sha256 sha512", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "UUID Generator", + description: "Generate UUIDs version 1 and 4", + keywords: "guid uuid1 uuid4 generator", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "Regex Tester", + description: "Validate and test regular expressions", + keywords: "regular expression regex validator tester", + href: pagesPath.$url(), + disabled: true, + }, + { + icon: , + title: "PNG / JPEG Compressor", + description: "Lossless PNG and JPEG optimizer", + keywords: "png jpeg compressor optimizer image", + href: pagesPath.$url(), + disabled: true, + }, +]; + +const StyledComponent = ({ filteredTools }: Props) => ( +
+ + {filteredTools.map(({ icon, title, description, href, disabled }) => ( + + + + ))} + +
+); + +export const Component = memo(StyledComponent); + +const filteredToolsState = selector({ + key: "filteredToolsState", + get: ({ get }) => { + const searchText = get(searchTextState).trim(); + + if (searchText === "") { + return { filteredTools: tools }; + } + + const searchWords = searchText.split(" ").map(word => ({ keywords: word })); + + const fuse = new Fuse(tools, { keys: ["keywords"], threshold: 0.5 }); + const result = fuse.search({ $and: searchWords }); + const filteredTools = result.map(({ item }) => item); + + return { filteredTools }; + }, +}); + +const Container = () => { + const { filteredTools } = useRecoilValue(filteredToolsState); + + return ; +}; + +export default Container; diff --git a/src/components/pages/home/index.ts b/src/components/pages/home/index.ts new file mode 100644 index 0000000..ae1b8af --- /dev/null +++ b/src/components/pages/home/index.ts @@ -0,0 +1,3 @@ +import Content from "./Content"; + +export { Content }; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 510d058..6c75db8 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,5 +1,7 @@ import type { NextPage } from "next"; -const Page: NextPage = () =>

hello

; +import { Content } from "@/components/pages/home"; + +const Page: NextPage = Content; export default Page; diff --git a/yarn.lock b/yarn.lock index 3ae8730..dc3c809 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1287,6 +1287,11 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +fuse.js@^6.5.3: + version "6.5.3" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.5.3.tgz#7446c0acbc4ab0ab36fa602e97499bdb69452b93" + integrity sha512-sA5etGE7yD/pOqivZRBvUBd/NaL2sjAu6QuSaFoe1H2BrJSkH/T/UXAJ8CdXdw7DvY3Hs8CXKYkDWX7RiP5KOg== + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"