diff --git a/components/core/App.js b/components/core/App.js
new file mode 100644
index 0000000..0869b81
--- /dev/null
+++ b/components/core/App.js
@@ -0,0 +1,59 @@
+import React, { useEffect, useState } from "react";
+import dynamic from "next/dynamic";
+
+// harperDb fetch call
+import { harperFetch } from "../../utils/HarperFetch";
+
+// Dummy Shape Data
+// import { shapes } from "../../data/shapes";
+// loader
+import Loader from "react-loader-spinner";
+
+// ShapeListing
+import { ShapeList } from '..';
+
+const App = (props) => {
+ const [data, setData] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(async () => {
+ setData([]);
+ setLoading(true);
+
+ // fetching the shape data
+ const shapes = await harperFetch({
+ operation: "sql",
+ sql: "SELECT * FROM tryshape.shapes",
+ });
+ console.log(shapes);
+ let modifiedShapes = shapes.map((shape, index) => {
+ shape.showAdvanced = false;
+ return shape;
+ });
+
+ console.log(modifiedShapes);
+
+ await setData(modifiedShapes);
+ setLoading(false);
+ }, []);
+
+
+
+ return (
+ <>
+ {loading ? (
+
+ ) : (
+
+ )}
+ >
+ );
+};
+
+export default App;
diff --git a/components/index.js b/components/index.js
new file mode 100644
index 0000000..b259ebd
--- /dev/null
+++ b/components/index.js
@@ -0,0 +1,3 @@
+export { default as App } from "./core/App";
+
+export { default as ShapeList } from './utils/ShapeList';
\ No newline at end of file
diff --git a/components/utils/ShapeList.js b/components/utils/ShapeList.js
new file mode 100644
index 0000000..54cf3d8
--- /dev/null
+++ b/components/utils/ShapeList.js
@@ -0,0 +1,133 @@
+import React, { useState } from "react";
+import dynamic from "next/dynamic";
+
+// Toast
+import toast from "react-hot-toast";
+
+// Clip-Path
+const Shape = dynamic(import("react-clip-path"), { ssr: false });
+
+// Switch
+import Switch from "react-switch";
+
+// Shape Listing Styled-Componentns
+import {
+ ShapeCards,
+ ShapeCard,
+ ShapeName,
+ ShapePallete,
+ ShapeDetailsItems,
+ ShapeCardSwitch,
+ ShapeActions,
+ ShapeCardHeader,
+ CopyIcon,
+ DownloadIcon,
+ LikeIcon,
+ } from './StyledComponents';
+
+const ShapeList = ({ data }) => {
+
+ const [shapes, setShapes] = useState(data);
+
+ const handleSwicth = (shapeName) => {
+ console.log(shapeName);
+
+ let modifiedShapes = shapes.map((shape, index) => {
+ if (shape.name === shapeName) {
+ return {
+ ...shape,
+ showAdvanced: !shape.showAdvanced,
+ };
+ }
+ return shape;
+ });
+ console.log(modifiedShapes);
+ setShapes(...[modifiedShapes]);
+ };
+
+ const getShapeFileName = (name) => {
+ return name.split(" ").join("-");
+ };
+
+ async function performCopy(event, formula) {
+ event.preventDefault();
+ try {
+ await navigator.clipboard.writeText(formula);
+ toast.success("Successfully Copied!");
+ console.log("The clip-path formula copied to clipboard");
+ } catch (err) {
+ console.error("Failed to copy: ", err);
+ }
+ }
+
+ return (
+
+
+ {shapes.map((shape, index) => (
+
+
+
+ {shape.name}
+
+
+
+ {" "}
+
+
+ saveAsPng(
+ event,
+ `${getShapeFileName(shape.name)}-id`,
+ getShapeFileName(shape.name)
+ )
+ }
+ />
+
+
+
+
+
+
+
+
+
+ {shape.showAdvanced && (
+
+
+ Clip-Path:{" "}
+
+ {shape.formula}
+
+ {" "}
+
+ performCopy(event, shape.formula)}
+ />
+
+
+ )}
+
+
+ ))}
+
+
+ );
+};
+
+export default ShapeList;
diff --git a/components/utils/StyledComponents.js b/components/utils/StyledComponents.js
new file mode 100644
index 0000000..9c98d73
--- /dev/null
+++ b/components/utils/StyledComponents.js
@@ -0,0 +1,92 @@
+import styled from "styled-components";
+import { FiCopy, FiDownload, FiHeart } from 'react-icons/fi';
+
+const ShapeCards = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+`;
+
+const ShapeCard = styled.div`
+ width: 400px;
+ min-height: 456px;
+ border: 1px solid #ececec;
+ border-radius: 4px;
+ padding: 5px;
+ margin: 5px;
+ background-color: #ebebeb;
+`;
+
+const ShapeActions = styled.div`
+ float: right;
+`;
+
+const ShapeName = styled.span`
+ font-weight: bold;
+ font-size: 20px;
+`;
+
+const Playground = styled.div`
+ width: 100%;
+`;
+
+const ShapeDetails = styled.ul`
+ background-color: #ebebeb;
+ border-radius: 4px;
+ padding: 10px;
+ width: 100%;
+`;
+
+const ShapeDetailsItems = styled.li`
+ word-wrap: break-word;
+`;
+
+const ShapePallete = styled.div`
+ margin-top: 5px;
+`;
+
+const ShapeCardHeader = styled.div`
+ padding: 5px;
+ margin: 5px;
+`;
+
+const ShapeCardSwitch = styled.div`
+ margin: 5px auto auto 9px;
+`;
+
+const CopyIcon = styled(FiCopy)`
+ cursor: pointer;
+ &:hover {
+ color: #f71b76;
+ }
+`;
+
+const DownloadIcon = styled(FiDownload)`
+ cursor: pointer;
+ &:hover {
+ color: #f71b76;
+ }
+`;
+
+const LikeIcon = styled(FiHeart)`
+ cursor: pointer;
+ &:hover {
+ color: #f71b6f;
+ }
+`;
+
+export {
+ ShapeCards,
+ ShapeCard,
+ ShapeName,
+ Playground,
+ ShapeDetails,
+ ShapeDetailsItems,
+ ShapeCardSwitch,
+ ShapePallete,
+ CopyIcon,
+ DownloadIcon,
+ LikeIcon,
+ ShapeActions,
+ ShapeCardHeader };
\ No newline at end of file
diff --git a/data/shapes.js b/data/shapes.js
new file mode 100644
index 0000000..58e930d
--- /dev/null
+++ b/data/shapes.js
@@ -0,0 +1,146 @@
+const shapes = [
+ {
+ name: "Circle",
+ type: "circle",
+ formula: "circle(50% at 50% 50%)",
+ vertices: 0,
+ edges: 0,
+ notes: "A circle is a round shaped figure that has no corners or edges. In geometry, a circle can be defined as a closed, two-dimensional curved shape.",
+ },
+ {
+ name: "Square",
+ type: "polygon",
+ formula: "polygon(10% 10%, 90% 10%, 90% 90%, 10% 90%)",
+ vertices: 4,
+ edges: 4,
+ notes: "A square is closed, two-dimensional shape with 4 equal sides. A square is a quadrilateral.",
+ },
+ {
+ name: "Rectangle",
+ type: "polygon",
+ formula: "polygon(10% 25%, 90% 25%, 90% 75%, 10% 75%)",
+ vertices: 4,
+ edges: 4,
+ notes: "A Rectangle is a four sided-polygon, having all the internal angles equal to 90 degrees. The two sides at each corner or vertex, meet at right angles. The opposite sides of the rectangle are equal in length which makes it different from a square.",
+ },
+ {
+ name: "Rhombus",
+ type: "polygon",
+ formula: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",
+ vertices: 4,
+ edges: 4,
+ notes: "A rhombus is a quadrilateral whose four sides all have the same length. A square and a rhombus both have sides equal in length. But square has all its angles equal to 90 degrees, but a rhombus only has its opposite angles equal.",
+ },
+ {
+ name: "Ellipse",
+ type: "ellipse",
+ formula: "ellipse(25% 40% at 50% 50%);",
+ vertices: 0,
+ edges: 0,
+ notes: "An ellipse is a shape that looks like an oval or a flattened circle.",
+ },
+ {
+ name: "Triangle",
+ type: "polygon",
+ formula: "polygon(50% 0%, 0% 100%, 100% 100%)",
+ vertices: 3,
+ edges: 3,
+ notes: " a triangle is a three-sided polygon that consists of three edges and three vertices. The most important property of a triangle is that the sum of the internal angles of a triangle is equal to 180 degrees.",
+ },
+ {
+ name: "Parallelogram",
+ type: "polygon",
+ formula: "polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%)",
+ vertices: 4,
+ edges: 4,
+ notes: "A parallelogram is a quadrilateral that has its opposite sides parallel and equal to each other. It has its interior opposite angles equal. Also, the angles on the same side of transversal sum up to 180 degrees or supplementary to each other.",
+ },
+ {
+ name: "Trapezoid",
+ type: "polygon",
+ formula: "polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%)",
+ vertices: 4,
+ edges: 4,
+ notes: "A trapezoid(also called, trapezium) is a quadrilateral with at least one pair of parallel sides. No other features matter. The parallel sides may be vertical , horizontal , or slanting .",
+ },
+ {
+ name: "Pentagon",
+ type: "polygon",
+ formula: "polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)",
+ vertices: 5,
+ edges: 5,
+ notes: "A pentagon is a geometrical shape, which has five sides and five angles. Here, “Penta” denotes five and “gon” denotes angle. An equilateral pentagon is a polygon with five sides of equal length.",
+ },
+ {
+ name: "Hexagon",
+ type: "polygon",
+ formula:
+ "polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)",
+ vertices: 6,
+ edges: 6,
+ notes: "A hexagon can be defined as a polygon with six sides. The two-dimensional shape has 6 sides, 6 vertices and 6 angles.",
+ },
+ {
+ name: "Heptagon",
+ type: "polygon",
+ formula:
+ "polygon(50% 0%, 90% 20%, 100% 60%, 75% 100%, 25% 100%, 0% 60%, 10% 20%)",
+ vertices: 7,
+ edges: 7,
+ notes: "Heptagon is a polygon ( a closed shape made up of line segments) made up of 7 sides and 7 angles. The word heptagon is made up of two words, hepta meaning seven and gon meaning sides.",
+ },
+ {
+ name: "Octagon",
+ type: "polygon",
+ formula:
+ "polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%)",
+ vertices: 8,
+ edges: 8,
+ notes: "An octagon is a polygon made up of 8 sides. It has eight angles. Octagon = Octa + gon where octa means eight and gon means sides. ",
+ },
+ {
+ name: "Nonagon",
+ type: "polygon",
+ formula:
+ "polygon(50% 0%, 83% 12%, 100% 43%, 94% 78%, 68% 100%, 32% 100%, 6% 78%, 0% 43%, 17% 12%)",
+ vertices: 9,
+ edges: 9,
+ notes: "A nonagon or enneagon is a nine-sided polygon or 9-gon.",
+ },
+ {
+ name: "Decagon",
+ type: "polygon",
+ formula:
+ "polygon(50% 0%, 80% 10%, 100% 35%, 100% 70%, 80% 90%, 50% 100%, 20% 90%, 0% 70%, 0% 35%, 20% 10%)",
+ vertices: 10,
+ edges: 10,
+ notes: "A decagon is a ten-sided polygon or 10-gon. The total sum of the interior angles of a simple decagon is 1440°. A self-intersecting regular decagon is known as a decagram.",
+ },
+ {
+ name: "Cross",
+ type: "polygon",
+ formula:
+ "polygon(30% 0%, 70% 0%, 70% 30%, 100% 30%, 100% 60%, 70% 60%, 70% 100%, 30% 100%, 30% 60%, 0% 60%, 0% 30%, 30% 30%)",
+ vertices: 12,
+ edges: 12,
+ notes: "A cross is a geometrical figure consisting of two intersecting lines or bars, usually perpendicular to each other. The lines usually run vertically and horizontally.",
+ },
+ {
+ name: "Star",
+ type: "polygon",
+ formula: "polygon(10% 100%,50% 0%,90% 100%,0% 40%,100% 40%)",
+ vertices: 5,
+ edges: 5,
+ notes: "A regular star pentagon, has five corner vertices and intersecting edges.",
+ },
+ {
+ name: "Tag",
+ type: "polygon",
+ formula: "polygon(68% 0%,0% 0%,0% 100%,68% 100%,100% 50%)",
+ vertices: 5,
+ edges: 5,
+ notes: "A custom structure that usually represents a Tag.",
+ },
+];
+
+export { shapes };
diff --git a/package.json b/package.json
index 6bc2ddc..7889cdc 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,12 @@
"dependencies": {
"next": "^10.0.0",
"react": "17.0.1",
+ "react-clip-path": "^0.0.6",
"react-dom": "17.0.1",
+ "react-hot-toast": "^2.0.0",
+ "react-icons": "^4.2.0",
+ "react-loader-spinner": "^4.0.0",
+ "react-switch": "^6.0.0",
"styled-components": "^5.3.0"
},
"devDependencies": {
diff --git a/pages/_app.js b/pages/_app.js
new file mode 100644
index 0000000..2121428
--- /dev/null
+++ b/pages/_app.js
@@ -0,0 +1,15 @@
+
+// styles
+import '../styles/global.css';
+
+// toaster
+import { Toaster } from "react-hot-toast";
+
+export default function App({ Component, pageProps }) {
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/pages/_document.js b/pages/_document.js
index 4baa7dd..ca99567 100644
--- a/pages/_document.js
+++ b/pages/_document.js
@@ -1,4 +1,4 @@
-import Document, { Head, Main, NextScript } from 'next/document';
+import Document, { Html, Head, Main, NextScript } from 'next/document';
// Import styled components ServerStyleSheet
import { ServerStyleSheet } from 'styled-components';
@@ -21,7 +21,7 @@ export default class MyDocument extends Document {
render() {
return (
-
+
{/* Step 5: Output the styles in the head */}
{this.props.styleTags}
@@ -30,7 +30,7 @@ export default class MyDocument extends Document {
-
+
);
}
}
\ No newline at end of file
diff --git a/pages/index.js b/pages/index.js
index 5272e9b..eb27a4d 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,11 +1,12 @@
-import styled from 'styled-components';
+import React from "react";
+import { App } from "../components";
-export default () => (
-
-
My First Next.js Page
-
-);
+const index = (props) => {
+ return (
+
+
+
+ );
+};
-const Title = styled.h1`
- color: #3700ff;
-`;
\ No newline at end of file
+export default index;
\ No newline at end of file
diff --git a/styles/global.css b/styles/global.css
new file mode 100644
index 0000000..c2308ae
--- /dev/null
+++ b/styles/global.css
@@ -0,0 +1,39 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
+ Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ line-height: 1.6;
+ font-size: 18px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+img {
+ max-width: 100%;
+ display: block;
+}
+
+li {
+ list-style: none;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ monospace;
+ font-size: 87.5%;
+ color: #e83e8c;
+ word-wrap: break-word;
+}
\ No newline at end of file
diff --git a/utils/HarperFetch.js b/utils/HarperFetch.js
new file mode 100644
index 0000000..7801f0f
--- /dev/null
+++ b/utils/HarperFetch.js
@@ -0,0 +1,12 @@
+export const harperFetch = async (body) => {
+ const request = await fetch(process.env.NEXT_PUBLIC_DB_URL, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Basic ${process.env.NEXT_PUBLIC_DB_AUTHORIZATION}`,
+ },
+ body: JSON.stringify(body),
+ });
+
+ return request.json();
+};
diff --git a/yarn.lock b/yarn.lock
index 3effb4c..510c4c7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -882,6 +882,11 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+goober@^2.0.35:
+ version "2.0.37"
+ resolved "https://registry.yarnpkg.com/goober/-/goober-2.0.37.tgz#5598c41f4c19bc1fca2c926e876a58a685faffb8"
+ integrity sha512-wgj5C7IJX2+MyHZ4TgOA+hLL1mCDW+jGorQ5KCMLF1ofE9gQkfbo1s8txIrzIsAX65XRTm0qaipolId2KMYUkw==
+
graceful-fs@^4.1.2:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
@@ -1500,7 +1505,7 @@ process@0.11.10, process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
-prop-types@15.7.2:
+prop-types@15.7.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -1576,6 +1581,13 @@ raw-body@2.4.1:
iconv-lite "0.4.24"
unpipe "1.0.0"
+react-clip-path@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/react-clip-path/-/react-clip-path-0.0.6.tgz#d9181cf89166d472470207fc2bb4ca059feed207"
+ integrity sha512-q3uU3GfqKBMzGzSsMYy1g550ctosfGm8+leNJlQTxA2oSqdzrid0lbLEaXrsP7uU01mT6HjYrFxQO6b5uqwHFg==
+ dependencies:
+ styled-components "^5.2.1"
+
react-dom@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
@@ -1585,16 +1597,42 @@ react-dom@17.0.1:
object-assign "^4.1.1"
scheduler "^0.20.1"
+react-hot-toast@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.0.0.tgz#6e83b2937a20b040acb2d5fd08bcf32561b7832a"
+ integrity sha512-J0J2rcSvKetlziVquwESgk85pV9JB0Dz3RJIZcAEv7CWU2y2z8BQqxmZHZUxjPKIBGPqXAocZch4Kj4oUdX4+w==
+ dependencies:
+ goober "^2.0.35"
+
+react-icons@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.2.0.tgz#6dda80c8a8f338ff96a1851424d63083282630d0"
+ integrity sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==
+
react-is@16.13.1, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+react-loader-spinner@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/react-loader-spinner/-/react-loader-spinner-4.0.0.tgz#43d9e71b0574219f64216933c28ef5faa12262f6"
+ integrity sha512-RU2vpEej6G4ECei0h3q6bgLU10of9Lw5O+4AwF/mtkrX5oY20Sh/AxoPJ7etbrs/7Q3u4jN5qwCwGLRKCHpk6g==
+ dependencies:
+ prop-types "^15.7.2"
+
react-refresh@0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
+react-switch@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/react-switch/-/react-switch-6.0.0.tgz#bd4a2dea08f211b8a32e55e8314fd44bc1ec947e"
+ integrity sha512-QV3/6eRK5/5epdQzIqvDAHRoGLbCv/wDpHUi6yBMXY1Xco5XGuIZxvB49PHoV1v/SpEgOCJLD/Zo43iic+aEIw==
+ dependencies:
+ prop-types "^15.7.2"
+
react@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
@@ -1821,7 +1859,7 @@ strip-ansi@6.0.0:
dependencies:
ansi-regex "^5.0.0"
-styled-components@^5.3.0:
+styled-components@^5.2.1, styled-components@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.0.tgz#e47c3d3e9ddfff539f118a3dd0fd4f8f4fb25727"
integrity sha512-bPJKwZCHjJPf/hwTJl6TbkSZg/3evha+XPEizrZUGb535jLImwDUdjTNxXqjjaASt2M4qO4AVfoHJNe3XB/tpQ==