From 05ae932853d84fd26207062e61e63ca188fbe339 Mon Sep 17 00:00:00 2001 From: Eesha Date: Thu, 1 Aug 2024 23:31:04 -0400 Subject: [PATCH] frontend rebased on the remote-proof-generation branch --- package.json | 12 + packages/app/index.css | 10 +- packages/app/index.html | 11 + packages/app/proofWorker.js | 19 + packages/app/src/App.tsx | 126 ++- packages/app/src/components/Accordion.tsx | 97 ++ packages/app/src/components/Button.tsx | 250 +++- .../app/src/components/DragAndDropTextBox.tsx | 96 +- .../app/src/components/EmailInputMethod.tsx | 78 +- .../app/src/components/LabeledTextArea.tsx | 205 +++- packages/app/src/components/Nav.tsx | 147 +++ .../app/src/components/SingleLineInput.tsx | 142 ++- packages/app/src/components/StatusTag.tsx | 35 + packages/app/src/components/Stepper.tsx | 741 ++++++++++++ packages/app/src/components/Video.tsx | 52 + packages/app/src/index.tsx | 37 +- packages/app/src/pages/AboutPage.tsx | 186 +++ packages/app/src/pages/MainPage.tsx | 1003 ++++++++++------- packages/app/src/styles.css | 39 +- packages/app/src/testWorker.js | 9 + packages/app/src/theme.tsx | 214 ++++ packages/app/tailwind.config.js | 12 + yarn.lock | 802 ++++++++++++- 23 files changed, 3691 insertions(+), 632 deletions(-) create mode 100644 packages/app/proofWorker.js create mode 100644 packages/app/src/components/Accordion.tsx create mode 100644 packages/app/src/components/Nav.tsx create mode 100644 packages/app/src/components/StatusTag.tsx create mode 100644 packages/app/src/components/Stepper.tsx create mode 100644 packages/app/src/components/Video.tsx create mode 100644 packages/app/src/pages/AboutPage.tsx create mode 100644 packages/app/src/testWorker.js create mode 100644 packages/app/src/theme.tsx create mode 100644 packages/app/tailwind.config.js diff --git a/package.json b/package.json index fd5b388..5d0dbcc 100644 --- a/package.json +++ b/package.json @@ -11,5 +11,17 @@ "packageManager": "yarn@3.2.3", "resolutions": { "zk-regex-sdk": "portal:/Users/savitar/Projects/opensource/proof-of-twitter/packages/app/zk-regex-sdk" + }, + "devDependencies": { + "autoprefixer": "^10.4.19", + "postcss": "^8.4.40", + "react-router-dom": "^6.26.0", + "tailwindcss": "^3.4.7" + }, + "dependencies": { + "@emotion/react": "^11.13.0", + "@emotion/styled": "^11.13.0", + "@mui/icons-material": "^5.16.6", + "@mui/material": "^5.16.6" } } diff --git a/packages/app/index.css b/packages/app/index.css index 4bf1c5d..7d348f2 100644 --- a/packages/app/index.css +++ b/packages/app/index.css @@ -2,11 +2,15 @@ @tailwind components; @tailwind utilities; +:root { + font-family: "Space Grotesk", sans-serif; + background-color: #ffbfbf; + background: radial-gradient(70.71% 70.71% at 50% 50%, #FFF 19%, rgba(255, 255, 255, 0.00) 61%), linear-gradient(38deg, rgba(255, 255, 255, 0.00) 60%, rgba(255, 255, 255, 0.69) 100%), linear-gradient(45deg, #FFF 10%, rgba(255, 255, 255, 0.00) 23.5%), linear-gradient(36deg, #FFF 12.52%, rgba(255, 255, 255, 0.00) 76.72%), linear-gradient(214deg, rgba(255, 255, 255, 0.00) 0%, rgba(255, 220, 234, 0.40) 37.53%, rgba(255, 255, 255, 0.00) 71%), linear-gradient(212deg, rgba(255, 255, 255, 0.00) 15%, #E4F1FE 72.5%, rgba(255, 255, 255, 0.00) 91.5%); +} + body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: "Space Grotesk", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } diff --git a/packages/app/index.html b/packages/app/index.html index 10746d0..a9cc814 100644 --- a/packages/app/index.html +++ b/packages/app/index.html @@ -39,6 +39,17 @@ window.process = process; window.setImmediate = setImmediate; + + + + + + + + + diff --git a/packages/app/proofWorker.js b/packages/app/proofWorker.js new file mode 100644 index 0000000..025b29f --- /dev/null +++ b/packages/app/proofWorker.js @@ -0,0 +1,19 @@ +// src/proofWorker.js + +import { generateProof } from "@zk-email/helpers/dist/zkp"; + +self.onmessage = async (e) => { + const { input, circuitArtifactsUrl, circuitName } = e.data; + + try { + const { proof, publicSignals } = await generateProof( + input, + circuitArtifactsUrl, + circuitName + ); + + self.postMessage({ proof, publicSignals }); + } catch (error) { + self.postMessage({ error: error.message }); + } +}; diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 29676be..34703f8 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -1,4 +1,82 @@ +// import { MainPage } from "./pages/MainPage"; +// import "./styles.css"; +// import { +// BrowserRouter as Router, +// Route, +// Routes, +// Link, +// } from "react-router-dom"; +// import { useLocation } from "react-use"; +// import styled from "styled-components"; +// import { ConnectButton } from "@rainbow-me/rainbowkit"; + +// const NavSection = () => { +// const { pathname } = useLocation(); + +// return ( +// +// ); +// }; + +// const App = () => { +// return ( +// +//
+// + +// +// } /> +// Not found} /> +// +//
+//
+// ); +// }; + +// export default App; + +// const Logo = styled(Link)` +// text-transform: uppercase; +// letter-spacing: 0.04em; +// color: #fff; +// text-decoration: none; +// font-size: 1.2rem; +// `; + +// const Nav = styled.nav` +// display: flex; +// align-items: center; +// justify-content: space-between; +// margin: 12px; +// `; + +// const DocsLink = styled.a` +// color: rgba(255, 255, 255, 0.8); +// text-decoration: none; +// underline: none; +// transition: all 0.2s ease-in-out; +// &:hover { +// color: rgba(255, 255, 255, 1); +// } +// `; + + import { MainPage } from "./pages/MainPage"; +import AboutPage from "./pages/AboutPage"; import "./styles.css"; import { BrowserRouter as Router, @@ -10,36 +88,16 @@ import { useLocation } from "react-use"; import styled from "styled-components"; import { ConnectButton } from "@rainbow-me/rainbowkit"; -const NavSection = () => { - const { pathname } = useLocation(); - - return ( - - ); -}; const App = () => { + const { pathname } = useLocation(); return (
- } /> + } /> Not found} />
@@ -49,27 +107,3 @@ const App = () => { export default App; -const Logo = styled(Link)` - text-transform: uppercase; - letter-spacing: 0.04em; - color: #fff; - text-decoration: none; - font-size: 1.2rem; -`; - -const Nav = styled.nav` - display: flex; - align-items: center; - justify-content: space-between; - margin: 12px; -`; - -const DocsLink = styled.a` - color: rgba(255, 255, 255, 0.8); - text-decoration: none; - underline: none; - transition: all 0.2s ease-in-out; - &:hover { - color: rgba(255, 255, 255, 1); - } -`; diff --git a/packages/app/src/components/Accordion.tsx b/packages/app/src/components/Accordion.tsx new file mode 100644 index 0000000..f179332 --- /dev/null +++ b/packages/app/src/components/Accordion.tsx @@ -0,0 +1,97 @@ +import React, { FC } from 'react'; +import { + Accordion as MuiAccordion, + AccordionSummary, + AccordionDetails, + Typography, + styled, +} from '@mui/material'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; + +// Define the props types +interface AccordionProps { + title: string; + contents: string; + alignment?: 'left' | 'right'; +} + +const CustomAccordion = styled(MuiAccordion)(({ theme }) => ({ + marginBottom: theme.spacing(2), + '&:before': { + display: 'none', + }, + background: 'inherit', + boxShadow: 'none', + borderBottom: '1px solid rgba(0, 0, 0, 0.12)', + '& .MuiAccordionSummary-root': { + backgroundColor: 'rgba(0, 0, 0, 0)', + '&:hover .MuiAccordionSummary-expandIconWrapper': { + color: theme.palette.secondary.main, + }, + }, + '& .MuiAccordionSummary-content': { + margin: 0, + display: 'flex', + alignItems: 'center', + width: '100%', + }, + '& .MuiAccordionSummary-expandIconWrapper': { + marginRight: theme.spacing(1), + transition: 'transform 0.2s', + }, + '& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': { + transform: 'rotate(180deg)', + }, + '& .MuiAccordionDetails-root': { + padding: theme.spacing(2), + }, +})); + +const Accordion: FC = ({ title, contents, alignment = 'left' }) => { + return ( + + } + aria-controls="panel-content" + id="panel-header" + sx={{ + flexDirection: alignment === 'right' ? 'row-reverse' : 'row', + justifyContent: alignment === 'right' ? 'space-between' : 'flex-start', + '& .MuiAccordionSummary-expandIconWrapper': { + order: alignment === 'right' ? 2 : 1, + marginRight: alignment === 'right' ? 0 : 1, + marginLeft: alignment === 'right' ? 1 : 0, + }, + width: '100%', + }} + > + + {title} + + + + + {contents} + + + + ); +}; + +export default Accordion; \ No newline at end of file diff --git a/packages/app/src/components/Button.tsx b/packages/app/src/components/Button.tsx index 385498f..a2922e8 100644 --- a/packages/app/src/components/Button.tsx +++ b/packages/app/src/components/Button.tsx @@ -1,10 +1,99 @@ +// import styled from "styled-components"; + +// export const Button = styled.button` +// padding: 0 14px; +// border-radius: 4px; +// background: #8272e4; +// border: none; +// display: flex; +// align-items: center; +// justify-content: center; +// font-weight: 600; +// font-size: 0.9rem; +// letter-spacing: -0.02em; +// color: #fff; +// cursor: pointer; +// height: 48px; +// width: 100%; +// min-width: 32px; +// transition: all 0.2s ease-in-out; +// &:hover { +// background: #9b8df2; +// } +// &:disabled { +// opacity: 0.5; +// cursor: not-allowed; +// } +// `; + +// export const OutlinedButton = styled.button` +// padding: 0 14px; +// border-radius: 4px; +// border: none; +// display: flex; +// align-items: center; +// justify-content: center; +// font-weight: 500; +// font-size: 0.9rem; +// letter-spacing: -0.02em; +// color: #8272e4; +// cursor: pointer; +// height: 48px; +// width: 100%; +// min-width: 32px; +// transition: all 0.2s ease-in-out; +// background: transparent; +// border: 1px solid #8272e4; +// &:hover { +// background: #9b8df2; +// color: white; +// } +// &:disabled { +// opacity: 0.5; +// cursor: not-allowed; +// } +// `; + + +// export const TextButton = styled.button` +// width: fit-content; +// background: transparent; +// border: none; +// color: white; +// font-weight: 500; +// padding: 4px 16px; +// border-radius: 4px; +// &:hover { +// background: #00000020; +// color: white; +// } +// &:disabled { +// opacity: 0.5; +// cursor: not-allowed; +// } +// `; + + + + +import React from 'react'; import styled from "styled-components"; +import { useTheme, Button as MuiButton } from "@mui/material"; + +interface ButtonProps { + highlighted?: boolean; + disabled?: boolean; + onClick?: () => void; + children: React.ReactNode; + endIcon?: React.ReactNode; + href?: string; + target?: string; +} -export const Button = styled.button` +const StyledButton = styled(MuiButton)<{ highlighted: boolean }>` padding: 0 14px; - border-radius: 4px; - background: #8272e4; - border: none; + text-transform: none; + border-radius: 9px; display: flex; align-items: center; justify-content: center; @@ -17,58 +106,175 @@ export const Button = styled.button` width: 100%; min-width: 32px; transition: all 0.2s ease-in-out; + background: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')}; + &:hover { - background: #9b8df2; + background: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')}; + opacity: 0.5; } + &:disabled { opacity: 0.5; cursor: not-allowed; + color: ${({ highlighted, theme }) => (highlighted ? '#ffffff' : 'grey')}; + } + + @media (max-width: 600px) { + font-size: 0.8rem; + padding: 0 12px; + } + + @media (max-width: 400px) { + font-size: 0.6rem; + padding: 0 5px; + height: 42px; } `; -export const OutlinedButton = styled.button` +const StyledOutlinedButton = styled(MuiButton)<{ highlighted: boolean }>` padding: 0 14px; - border-radius: 4px; - border: none; + border-radius: 9px; display: flex; align-items: center; justify-content: center; font-weight: 500; font-size: 0.9rem; letter-spacing: -0.02em; - color: #8272e4; + text-transform: none; cursor: pointer; height: 48px; width: 100%; min-width: 32px; transition: all 0.2s ease-in-out; - background: transparent; - border: 1px solid #8272e4; + background: '#ffffff'; + border: 1px solid ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')}; + color: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')}; + &:hover { - background: #9b8df2; + background: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')}; color: white; } + &:disabled { opacity: 0.5; cursor: not-allowed; } + + @media (max-width: 600px) { + font-size: 0.8rem; + padding: 0 12px; + } + + @media (max-width: 400px) { + font-size: 0.6rem; + padding: 0 5px; + height: 42px; + } `; +const StyledTextButton = styled(MuiButton)<{ highlighted: boolean }>` + width: fit-content; + background: '#ffffff'; + border: none; + color: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : theme.palette.secondary.main)}; + font-weight: 500; + padding: 4px 16px; + border-radius: 9px; -export const TextButton = styled.button` -width: fit-content; -background: transparent; -border: none; -color: white; -font-weight: 500; -padding: 4px 16px; -border-radius: 4px; &:hover { - background: #00000020; - color: white; + color: theme.palette.secondary.main; } + &:disabled { opacity: 0.5; cursor: not-allowed; } + + @media (max-width: 600px) { + font-size: 0.8rem; + padding: 2px 12px; + } + + @media (max-width: 400px) { + font-size: 0.6rem; + padding: 2px 10px; + height: 42px; + } `; + +export const Button: React.FC = ({ highlighted = false, disabled, onClick, children, endIcon, href, target }) => { + const theme = useTheme(); + + const handleClick = (e: React.MouseEvent) => { + if (disabled) return; + if (href) { + window.open(href, target); + } else if (onClick) { + onClick(); + } + }; + + return ( + + {children} + + ); +}; + +export const OutlinedButton: React.FC = ({ highlighted = false, disabled, onClick, children, endIcon, href, target }) => { + const theme = useTheme(); + + const handleClick = (e: React.MouseEvent) => { + if (disabled) return; + if (href) { + window.open(href, target); + } else if (onClick) { + onClick(); + } + }; + + return ( + + {children} + + ); +}; + +export const TextButton: React.FC = ({ highlighted = false, disabled, onClick, children, endIcon, href, target }) => { + const theme = useTheme(); + + const handleClick = (e: React.MouseEvent) => { + if (disabled) return; + if (href) { + window.open(href, target); + } else if (onClick) { + onClick(); + } + }; + + return ( + + {children} + {endIcon && {endIcon}} + + ); +}; + diff --git a/packages/app/src/components/DragAndDropTextBox.tsx b/packages/app/src/components/DragAndDropTextBox.tsx index 9f51137..8ef5525 100644 --- a/packages/app/src/components/DragAndDropTextBox.tsx +++ b/packages/app/src/components/DragAndDropTextBox.tsx @@ -1,20 +1,80 @@ +// import React from "react"; +// import styled from 'styled-components'; +// import { useDragAndDrop } from '../hooks/useDragAndDrop'; + +// const DragAndDropTextBoxWrapper = styled.div` +// display: flex; +// flex-direction: column; +// align-items: center; +// border: 2px dashed #ccc; +// padding: 20px; +// `; + +// type Props = { +// onFileDrop: (file: File) => void; +// }; + +// const DragAndDropTextBox: React.FC = ({onFileDrop}) => { +// const { +// dragging, +// handleDragEnter, +// handleDragLeave, +// handleDragOver, +// handleDrop, +// handleDragEnd, +// } = useDragAndDrop(); + +// return ( +// handleDrop(e, onFileDrop)} +// > +// {dragging ? ( +//
Drop here
+// ) : ( +//
Drop .eml file here
+// )} +//
+// ); +// }; + +// export default DragAndDropTextBox; + + + + + import React from "react"; -import styled from 'styled-components'; +import styled, { css, ThemeProvider } from 'styled-components'; +import { useTheme } from "@mui/material/styles"; import { useDragAndDrop } from '../hooks/useDragAndDrop'; +import { Typography } from "@mui/material"; -const DragAndDropTextBoxWrapper = styled.div` +const DragAndDropTextBoxWrapper = styled.div<{ highlighted: boolean }>` display: flex; flex-direction: column; align-items: center; border: 2px dashed #ccc; padding: 20px; + ${({ highlighted, theme }) => + highlighted + ? css` + border-color: ${theme.palette.accent.main}; + color: ${theme.palette.accent.main} + ` + : ''} `; type Props = { onFileDrop: (file: File) => void; + highlighted?: boolean; }; -const DragAndDropTextBox: React.FC = ({onFileDrop}) => { +const DragAndDropTextBox: React.FC = ({ onFileDrop, highlighted = false }) => { + const theme = useTheme(); const { dragging, handleDragEnter, @@ -25,20 +85,24 @@ const DragAndDropTextBox: React.FC = ({onFileDrop}) => { } = useDragAndDrop(); return ( - handleDrop(e, onFileDrop)} - > - {dragging ? ( -
Drop here
- ) : ( -
Drop .eml file here
- )} -
+ + handleDrop(e, onFileDrop)} + > + {dragging ? ( +
Drop here
+ ) : ( +
Drop .eml file here
+ )} +
+
); }; export default DragAndDropTextBox; + diff --git a/packages/app/src/components/EmailInputMethod.tsx b/packages/app/src/components/EmailInputMethod.tsx index 851b661..38f3ff0 100644 --- a/packages/app/src/components/EmailInputMethod.tsx +++ b/packages/app/src/components/EmailInputMethod.tsx @@ -1,12 +1,55 @@ -import { useState } from "react"; +// import { useState } from "react"; +// import { Button, OutlinedButton } from "./Button"; + +// const EmailInputMethod = ({ +// onClickGoogle, +// onClickEMLFile, +// }: { +// onClickGoogle: () => void; +// onClickEMLFile: () => void; +// }) => { +// return ( +//
+// +// or +// { +// onClickEMLFile(); +// }} +// > +// Upload email .eml file{" "} +// +//
+// ); +// }; + +// export default EmailInputMethod; + + + import { Button, OutlinedButton } from "./Button"; -const EmailInputMethod = ({ - onClickGoogle, - onClickEMLFile, -}: { +interface EmailInputMethodProps { onClickGoogle: () => void; onClickEMLFile: () => void; + highlighted?: boolean; + disabled?: boolean; // Optional disabled prop +} + +const EmailInputMethod: React.FC = ({ + onClickGoogle, + onClickEMLFile, + highlighted = false, + disabled = false, // Default value set to false }) => { return (
- - or - { - onClickEMLFile(); - }} - > - Upload email .eml file{" "} - + + {!disabled && ( + <> + or + + Upload email .eml file{" "} + + + )}
); }; diff --git a/packages/app/src/components/LabeledTextArea.tsx b/packages/app/src/components/LabeledTextArea.tsx index 66112c6..2c72e2b 100644 --- a/packages/app/src/components/LabeledTextArea.tsx +++ b/packages/app/src/components/LabeledTextArea.tsx @@ -1,7 +1,110 @@ +// import _ from "lodash"; +// import React, { CSSProperties } from "react"; +// import styled from "styled-components"; +// import { Col } from "./Layout"; + +// export const LabeledTextArea: React.FC<{ +// style?: CSSProperties; +// className?: string; +// label: string; +// value: string; +// warning?: string; +// warningColor?: string; +// disabled?: boolean; +// disabledReason?: string; +// secret?: boolean; +// onChange?: React.ChangeEventHandler; +// }> = ({ +// style, +// warning, +// warningColor, +// disabled, +// disabledReason, +// label, +// value, +// onChange, +// className, +// secret, +// }) => { +// return ( +// +// +// {warning && ( +// +// {warning} +// +// )} +//