diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..2939b25 --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,6 @@ + +NEXT_PUBLIC_RPC_URL= +RPC_URL= + +DATABASE_URL= + diff --git a/frontend/src/app/manufacturer/page.tsx b/frontend/src/app/manufacturer/account/page.tsx similarity index 73% rename from frontend/src/app/manufacturer/page.tsx rename to frontend/src/app/manufacturer/account/page.tsx index 95d8b62..0f7eac4 100644 --- a/frontend/src/app/manufacturer/page.tsx +++ b/frontend/src/app/manufacturer/account/page.tsx @@ -1,4 +1,4 @@ -import ManufacturerForm from '../components/ManufacturerForm'; +import ManufacturerForm from '@/components/manufacturer/ManufacturerForm'; export default function ManufacturerPage() { return ( diff --git a/frontend/src/app/producers/page.tsx b/frontend/src/app/producers/page.tsx deleted file mode 100644 index 29d4fbf..0000000 --- a/frontend/src/app/producers/page.tsx +++ /dev/null @@ -1,150 +0,0 @@ -'use client'; -import { - DiscordIcon, - ScanIcon, - TelegramIcon, - TwitterIcon, -} from '../../assets/icons'; -import Link from 'next/link'; - -export default function Home() { - return ( -
-
- - -
-
-

- Your products can be here too! -

-

- follow the simple steps to upload your products for proofing that - you sell the best and realest product. -

-
-
-
- -
-
-

- Your products can be here too -

-

- If you are a producer and you have a product you will like to - register with ScanGuard, this is for you. With ScanGuard, you are in - control of the information of the production, distribution, and - sales of your products. You products will be recognized as - explicitly yours and any counterfeit will be flagged as dangerous - and unfit to be used. -

- -
-

- Step 1: Connect your wallet address -

-

- Step 2: Input all required information of your product -

-

- Step 3: Submit for recording -

-

- Step 4: Save the product token -

-
- -
- - Get Started - -
-
- -
- bottles -
-
- - -
- ); -} diff --git a/frontend/src/app/scan/[product]/page.tsx b/frontend/src/app/scan/[product]/page.tsx index a3e6533..6c90bab 100644 --- a/frontend/src/app/scan/[product]/page.tsx +++ b/frontend/src/app/scan/[product]/page.tsx @@ -1,17 +1,6 @@ 'use client'; - -import Link from 'next/link'; -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import { useAccount } from '@starknet-react/core'; -import { - DiscordIcon, - LearnmoreIcon, - MenuIcon, - ScanIcon, - TelegramIcon, - TwitterIcon, -} from '@/assets/icons'; -import AddressBar from '@/components/Addressbar'; import ScanProduct from '@/components/Scan'; import ConnectModal from '@/components/ConnectModal'; import { useParams } from 'next/navigation'; @@ -37,10 +26,6 @@ export default function ScanPage() { return (
- {/* Product Preview - //TODO: center, add background, make it responsive and pixel perfect - //TODO: https://www.figma.com/design/dwXPww5jcUl55azC9EQ8H0/SCANGUARD?node-id=14-13&node-type=canvas&t=Q8gtO0EqfOBYEqke-0 - */} {open && } diff --git a/frontend/src/components/ConnectModal.tsx b/frontend/src/components/ConnectModal.tsx index 4ede6b0..9fc191d 100644 --- a/frontend/src/components/ConnectModal.tsx +++ b/frontend/src/components/ConnectModal.tsx @@ -23,26 +23,26 @@ const Wallet = ({ alt: string; src: string; connector: Connector; - closeModal: (e: React.MouseEvent) => void; + closeModal: () => void; }) => { const { connect } = useConnect(); const isSvg = src?.startsWith('): void { connect({ connector }); - closeModal(e); + closeModal(); localStorage.setItem('lastUsedConnector', connector.name); } return ( ); }; const ConnectModal = ({ isOpen, onClose }: Props) => { const [animate, setAnimate] = useState(false); - const closeModal = (e: React.MouseEvent) => { - e.stopPropagation(); - setAnimate(false); - setTimeout(() => { - onClose(); - }, 400); - }; useEffect(() => { if (isOpen) { @@ -84,23 +77,20 @@ const ConnectModal = ({ isOpen, onClose }: Props) => { return ( -
-
+
+

- Connect a Wallet + Connect Wallet

-
-
-

Popular

-
+
+
+
{connectors.map((connector, index) => ( { ))}
-
-

- What is a wallet? -

-
-
-
- text -
-
-

- A home for your digital assets -

-

- Wallets are used to send, receive, store, and display digital - assets like Ethereum and NFTs. -

-
-
-
-
- text -
-
-

- A new way to sign-in -

-

- Instead of creating new accounts and passwords on every - website, just connect your wallet. -

-
-
-
-
+
); diff --git a/frontend/src/components/ConnectWallet.tsx b/frontend/src/components/ConnectWallet.tsx index 61d2ec3..021fba4 100644 --- a/frontend/src/components/ConnectWallet.tsx +++ b/frontend/src/components/ConnectWallet.tsx @@ -1,15 +1,26 @@ import { roboto } from '@/app/fonts'; +import { useState } from 'react'; +import ConnectModal from './ConnectModal'; const ConnectWallet = (props: any) => { + const [isOpen, setisOpen] = useState(false) return ( - + {...props} + > + CONNECT WALLET + + + { + isOpen && setisOpen(false)} /> + } + +
); }; diff --git a/frontend/src/components/GenericModal.tsx b/frontend/src/components/GenericModal.tsx index 62535d5..d995f09 100644 --- a/frontend/src/components/GenericModal.tsx +++ b/frontend/src/components/GenericModal.tsx @@ -1,4 +1,8 @@ 'use client'; + +import { useEffect } from "react"; +import ReactPortal from "./react-portal"; + const GenericModal = ({ isOpen, onClose, @@ -8,33 +12,58 @@ const GenericModal = ({ position, }: { isOpen: boolean; - onClose: (e: React.MouseEvent) => void; + onClose: () => void; animate: boolean; children: React.ReactNode; className?: string; position?: string; }) => { + + useEffect(() => { + const closeOnEscapeKey = (e: KeyboardEvent) => + e.key === "Escape" ? onClose() : null; + document.body.addEventListener("keydown", closeOnEscapeKey); + return (): void => { + document.body.removeEventListener("keydown", closeOnEscapeKey); + }; + }, [onClose]); + + useEffect(() => { + document.body.style.overflow = "hidden"; + return (): void => { + document.body.style.overflow = "unset"; + }; + }, [isOpen]); + + if (!isOpen) { + return null; + } return ( + + <> - {isOpen && ( -
+ + +
+
+
e.stopPropagation()} - className={`bg-[#1c1b1f] rounded-[25px] flex flex-col border-[1px] border-solid border-outline-grey transition-[opacity,transform] duration-500 ease-in-out ${ - animate - ? 'translate-y-0 opacity-100' - : 'translate-y-full opacity-0' - } ${className}`} + onClick={onClose} + className={`fixed w-full inset-0 flex items-center justify-center z-50 + pt-20 md:p-0 overflow-x-hidden transition-all duration-300 ease-in-out`} > - {children} +
e.stopPropagation()} + className="border border-[#170F2E] rounded-3xl bg-[#303030] sm:max-w-sm md:max-w-lg w-full" + > + {children} +
-
- )} +
+ ); }; diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx index b61766b..96b4636 100644 --- a/frontend/src/components/Navbar.tsx +++ b/frontend/src/components/Navbar.tsx @@ -31,18 +31,23 @@ const NavBar = (props: any) => { ); }; +const navItems = [ + { name: 'Manufacturer', route: '/manufacturer/account' }, + { name: 'Contact', route: '/contact' }, +]; + const NavLinks = () => ( diff --git a/frontend/src/app/components/ManufacturerForm.tsx b/frontend/src/components/manufacturer/ManufacturerForm.tsx similarity index 100% rename from frontend/src/app/components/ManufacturerForm.tsx rename to frontend/src/components/manufacturer/ManufacturerForm.tsx diff --git a/frontend/src/components/react-portal.tsx b/frontend/src/components/react-portal.tsx new file mode 100644 index 0000000..59b0bec --- /dev/null +++ b/frontend/src/components/react-portal.tsx @@ -0,0 +1,37 @@ +"use client"; + +import { useLayoutEffect, useState } from "react"; +import { createPortal } from "react-dom"; + +interface ReactPortalProps { + children: React.ReactElement; + containerId: string; +} + +const createContainerAndAppendToBody = (containerId: string) => { + if (!document) return null; + const wrapperElement = document.createElement("div"); + wrapperElement.setAttribute("id", containerId); + document.body.appendChild(wrapperElement); + return wrapperElement; +}; + +export default function ReactPortal({ + children, + containerId, +}: ReactPortalProps) { + const [containerElement, setContainerElement] = useState(); + + useLayoutEffect(() => { + let container = document.getElementById(containerId); + if (!container) { + container = createContainerAndAppendToBody(containerId); + } + setContainerElement(container!); + }, [containerId]); + + if (containerElement == null) { + return null; + } + return createPortal(children, containerElement); +}