mirror of
https://github.com/AtHeartEngineering/bandada.git
synced 2026-01-09 18:27:59 -05:00
@@ -2,11 +2,11 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Client</title>
|
||||
<title>Bandada Demo</title>
|
||||
<base href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
<link rel="icon" type="image/x-icon" href="./src/assets/favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -8,17 +8,21 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bandada/api-sdk": "0.12.0",
|
||||
"@bandada/utils": "0.12.0",
|
||||
"@chakra-ui/react": "^2.5.1",
|
||||
"@chakra-ui/theme-tools": "^2.0.16",
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.6",
|
||||
"@semaphore-protocol/identity": "3.4.0",
|
||||
"@fontsource-variable/unbounded": "^5.0.5",
|
||||
"@semaphore-protocol/identity": "3.10.1",
|
||||
"@web3-react/core": "^6.1.9",
|
||||
"@web3-react/injected-connector": "^6.0.7",
|
||||
"ethers": "^5.4.7",
|
||||
"framer-motion": "^10.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.10.1",
|
||||
"react-router-dom": "^6.8.1",
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
},
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { ChakraProvider } from "@chakra-ui/react"
|
||||
import { Web3ReactProvider } from "@web3-react/core"
|
||||
import { providers } from "ethers"
|
||||
import { Route, Routes } from "react-router-dom"
|
||||
import NavBar from "./components/navbar"
|
||||
import Home from "./pages/home"
|
||||
import PermissionedGroup from "./pages/permissioned-group"
|
||||
|
||||
export default function App() {
|
||||
function getLibrary(provider: any) {
|
||||
return new providers.Web3Provider(provider)
|
||||
}
|
||||
|
||||
return (
|
||||
<Web3ReactProvider getLibrary={(provider) => getLibrary(provider)}>
|
||||
<ChakraProvider>
|
||||
<NavBar />
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route
|
||||
path="/invites/:inviteCode"
|
||||
element={<PermissionedGroup />}
|
||||
/>
|
||||
</Routes>
|
||||
</ChakraProvider>
|
||||
</Web3ReactProvider>
|
||||
)
|
||||
}
|
||||
BIN
apps/client/src/assets/favicon.ico
Normal file
BIN
apps/client/src/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
19
apps/client/src/assets/icon1.svg
Normal file
19
apps/client/src/assets/icon1.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.85986 31.7156L12.428 29.2313L14.6872 31.3369L12.428 42.6567L20.0723 39.2482C20.0723 39.2482 21.7049 31.0121 22.2124 29.4087L23.8409 29.0187L25.9719 27.2784L23.8409 25.6719L22.2124 25.3496C21.2387 21.9958 20.0723 16.7251 20.0723 16.7251L12.428 12.4799L14.6872 22.9001L12.428 25.3496L7.28614 22.9001L6.85986 31.7156Z" fill="url(#paint0_linear_1655_9972)"/>
|
||||
<path d="M42.7496 44.6115L37.8229 41.0443L38.5191 38.041L49.4436 34.335L42.6819 29.4368C42.6819 29.4368 34.7389 32.1428 33.098 32.5057L31.9484 31.2943L29.3795 30.3237L29.0515 32.9668L29.5845 34.5342C27.167 37.0512 23.1864 40.6925 23.1864 40.6925L23.3233 49.4156L31.2164 42.2572L34.4631 42.9841L34.9066 48.6488L42.7496 44.6115Z" fill="url(#paint1_linear_1655_9972)"/>
|
||||
<path d="M42.4825 11.0984L37.6129 14.7431L38.3565 17.735L49.3382 21.2677L42.6548 26.2722C42.6548 26.2722 34.67 23.6922 33.0235 23.3553L31.8933 24.5847L29.3401 25.5959L28.9703 22.9582L29.4785 21.3826C27.0215 18.9042 22.9837 15.3262 22.9837 15.3262L22.9827 6.60203L30.988 13.6348L34.2228 12.8566L34.5767 7.18561L42.4825 11.0984Z" fill="url(#paint2_linear_1655_9972)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1655_9972" x1="9.91778" y1="12.4799" x2="26.216" y2="13.47" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF5242"/>
|
||||
<stop offset="1" stop-color="#EB179B"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1655_9972" x1="24.5749" y1="51.5835" x2="17.3016" y2="37.0154" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF5242"/>
|
||||
<stop offset="1" stop-color="#EB179B"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_1655_9972" x1="24.1999" y1="4.41463" x2="17.1578" y2="19.0959" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF5242"/>
|
||||
<stop offset="1" stop-color="#EB179B"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1,74 +0,0 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
Container,
|
||||
Flex,
|
||||
Spacer,
|
||||
Text,
|
||||
Tooltip,
|
||||
useClipboard
|
||||
} from "@chakra-ui/react"
|
||||
import { useWeb3React } from "@web3-react/core"
|
||||
import { InjectedConnector } from "@web3-react/injected-connector"
|
||||
import { shortenAddress } from "@bandada/utils"
|
||||
import { providers } from "ethers"
|
||||
import { useEffect } from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
const injectedConnector = new InjectedConnector({})
|
||||
|
||||
export default function NavBar(): JSX.Element {
|
||||
const { activate, account } = useWeb3React<providers.Web3Provider>()
|
||||
const { hasCopied, onCopy } = useClipboard(account || "")
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
if (await injectedConnector.isAuthorized()) {
|
||||
await activate(injectedConnector)
|
||||
}
|
||||
})()
|
||||
}, [activate])
|
||||
|
||||
return (
|
||||
<Box bgColor="#F8F9FF" borderBottom="1px" borderColor="gray.200">
|
||||
<Container maxWidth="container.xl">
|
||||
<Flex h="100px">
|
||||
<Center>
|
||||
<Link to="/">
|
||||
<Text fontSize="lg" fontWeight="bold">
|
||||
Bandada
|
||||
</Text>
|
||||
</Link>
|
||||
</Center>
|
||||
<Spacer />
|
||||
<Center>
|
||||
{account ? (
|
||||
<Tooltip
|
||||
label={hasCopied ? "Copied" : "Copy"}
|
||||
closeOnClick={false}
|
||||
hasArrow
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={onCopy}
|
||||
sx={{ marginRight: 10 }}
|
||||
>
|
||||
{shortenAddress(account)}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Button
|
||||
mr="10px"
|
||||
onClick={() => activate(injectedConnector)}
|
||||
>
|
||||
Connect wallet
|
||||
</Button>
|
||||
)}
|
||||
</Center>
|
||||
</Flex>
|
||||
</Container>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
import { Identity } from "@semaphore-protocol/identity"
|
||||
import { request } from "@bandada/utils"
|
||||
import { Signer } from "ethers"
|
||||
import { useCallback, useState } from "react"
|
||||
import { Invite } from "../types/invite"
|
||||
|
||||
type ReturnParameters = {
|
||||
getInvite: (inviteCode: string | undefined) => Promise<Invite>
|
||||
generateIdentityCommitment: (
|
||||
signer: Signer,
|
||||
groupId: string,
|
||||
groupName: string
|
||||
) => Promise<string | null>
|
||||
addMember: (
|
||||
groupId: string,
|
||||
idCommitment: string,
|
||||
inviteCode: string
|
||||
) => Promise<void>
|
||||
hasjoined: boolean
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
export default function usePermissionedGroups(): ReturnParameters {
|
||||
const [_loading, setLoading] = useState<boolean>(false)
|
||||
const [_hasJoined, setHasjoined] = useState<boolean>(false)
|
||||
|
||||
const getInvite = useCallback(
|
||||
async (inviteCode: string | undefined): Promise<Invite> => {
|
||||
const codeInfo = await request(
|
||||
`${import.meta.env.VITE_API_URL}/invites/${inviteCode}`
|
||||
)
|
||||
|
||||
return codeInfo
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
const generateIdentityCommitment = useCallback(
|
||||
async (
|
||||
signer: Signer,
|
||||
groupId: string,
|
||||
groupName: string
|
||||
): Promise<string | null> => {
|
||||
setLoading(true)
|
||||
const nonce = 0
|
||||
const message = `Sign this message to generate your ${groupName} Semaphore identity with key nonce: ${nonce}.`
|
||||
const identity = new Identity(await signer.signMessage(message))
|
||||
const identityCommitment = identity.getCommitment().toString()
|
||||
const hasJoined = await request(
|
||||
`${
|
||||
import.meta.env.VITE_API_URL
|
||||
}/groups/${groupId}/members/${identityCommitment}`
|
||||
)
|
||||
setHasjoined(hasJoined)
|
||||
setLoading(false)
|
||||
return identityCommitment
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
const addMember = useCallback(
|
||||
async (
|
||||
groupId: string,
|
||||
idCommitment: string,
|
||||
inviteCode: string
|
||||
): Promise<void> => {
|
||||
await request(
|
||||
`${
|
||||
import.meta.env.VITE_API_URL
|
||||
}/groups/${groupId}/members/${idCommitment}`,
|
||||
{
|
||||
method: "post",
|
||||
data: {
|
||||
inviteCode
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
return {
|
||||
getInvite,
|
||||
generateIdentityCommitment,
|
||||
addMember,
|
||||
hasjoined: _hasJoined,
|
||||
loading: _loading
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { useWeb3React } from "@web3-react/core"
|
||||
import { providers, Signer } from "ethers"
|
||||
|
||||
const useSigner = () => {
|
||||
const [signer, setSigner] = useState<Signer>()
|
||||
const { account, library } = useWeb3React<providers.Web3Provider>()
|
||||
|
||||
useEffect(() => {
|
||||
if (!library || !account) return
|
||||
|
||||
setSigner(library.getSigner(account))
|
||||
}, [account, library])
|
||||
|
||||
return signer
|
||||
}
|
||||
|
||||
export default useSigner
|
||||
@@ -1,16 +1,19 @@
|
||||
import { StrictMode } from "react"
|
||||
import * as ReactDOM from "react-dom/client"
|
||||
import { BrowserRouter } from "react-router-dom"
|
||||
import { ChakraProvider } from "@chakra-ui/react"
|
||||
import App from "./app"
|
||||
import "@fontsource-variable/unbounded"
|
||||
import { Web3ReactProvider } from "@web3-react/core"
|
||||
import { providers } from "ethers"
|
||||
import * as ReactDOM from "react-dom/client"
|
||||
import Routes from "./routes"
|
||||
import theme from "./styles"
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement)
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<BrowserRouter basename={import.meta.env.BASE_URL || ""}>
|
||||
<ChakraProvider>
|
||||
<App />
|
||||
</ChakraProvider>
|
||||
</BrowserRouter>
|
||||
</StrictMode>
|
||||
<Web3ReactProvider
|
||||
getLibrary={(provider) => new providers.Web3Provider(provider)}
|
||||
>
|
||||
<ChakraProvider theme={theme}>
|
||||
<Routes />
|
||||
</ChakraProvider>
|
||||
</Web3ReactProvider>
|
||||
)
|
||||
|
||||
@@ -1,16 +1,176 @@
|
||||
import { Container, Heading } from "@chakra-ui/react"
|
||||
import { request } from "@bandada/utils"
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
Heading,
|
||||
HStack,
|
||||
Icon,
|
||||
Image,
|
||||
Input,
|
||||
Link,
|
||||
Text,
|
||||
VStack
|
||||
} from "@chakra-ui/react"
|
||||
import { Identity } from "@semaphore-protocol/identity"
|
||||
import { useWeb3React } from "@web3-react/core"
|
||||
import { InjectedConnector } from "@web3-react/injected-connector"
|
||||
import { providers } from "ethers"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { FiGithub } from "react-icons/fi"
|
||||
import { useSearchParams } from "react-router-dom"
|
||||
import icon1Image from "../assets/icon1.svg"
|
||||
|
||||
const injectedConnector = new InjectedConnector({})
|
||||
|
||||
export default function HomePage(): JSX.Element {
|
||||
const [_inviteCode, setInviteCode] = useState<string>("")
|
||||
const [_loading, setLoading] = useState<boolean>(false)
|
||||
const { activate, active, library, account } =
|
||||
useWeb3React<providers.Web3Provider>()
|
||||
const [_searchParams] = useSearchParams()
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
if (await injectedConnector.isAuthorized()) {
|
||||
await activate(injectedConnector)
|
||||
}
|
||||
})()
|
||||
}, [activate])
|
||||
|
||||
useEffect(() => {
|
||||
const inviteCode = _searchParams.get("inviteCode")
|
||||
|
||||
if (inviteCode) {
|
||||
setInviteCode(inviteCode)
|
||||
}
|
||||
}, [_searchParams])
|
||||
|
||||
const joinGroupByInvite = useCallback(
|
||||
async (inviteCode: string) => {
|
||||
if (account && library) {
|
||||
setLoading(true)
|
||||
|
||||
const invite = await request(
|
||||
`${import.meta.env.VITE_API_URL}/invites/${inviteCode}`
|
||||
)
|
||||
|
||||
if (!invite) {
|
||||
alert("Some error occurred!")
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
const signer = library.getSigner(account)
|
||||
|
||||
const message = `Sign this message to generate your Semaphore identity.`
|
||||
const identity = new Identity(await signer.signMessage(message))
|
||||
const identityCommitment = identity.getCommitment().toString()
|
||||
const hasJoined = await request(
|
||||
`${import.meta.env.VITE_API_URL}/groups/${
|
||||
invite.groupId
|
||||
}/members/${identityCommitment}`
|
||||
)
|
||||
|
||||
if (hasJoined) {
|
||||
alert("You have already joined this group")
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
await request(
|
||||
`${import.meta.env.VITE_API_URL}/groups/${
|
||||
invite.groupId
|
||||
}/members/${identityCommitment}`,
|
||||
{
|
||||
method: "post",
|
||||
data: {
|
||||
inviteCode
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
alert("You have joined the group!")
|
||||
setInviteCode("")
|
||||
setLoading(false)
|
||||
}
|
||||
},
|
||||
[account, library]
|
||||
)
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
return (
|
||||
<Container
|
||||
textAlign="center"
|
||||
flex="1"
|
||||
mb="80px"
|
||||
mt="300px"
|
||||
px="80px"
|
||||
maxW="container.lg"
|
||||
>
|
||||
<Heading fontSize="150px">Client App</Heading>
|
||||
<Container maxW="container.xl" pt="20" pb="20" px="8" centerContent>
|
||||
<VStack spacing="20" pb="30px">
|
||||
<HStack mb="60px" justify="space-between" w="100%">
|
||||
<HStack spacing="1">
|
||||
<Image
|
||||
src={icon1Image}
|
||||
htmlWidth="32px"
|
||||
alt="Bandada icon"
|
||||
/>
|
||||
<Heading fontSize="22px" as="h1">
|
||||
bandada
|
||||
</Heading>
|
||||
</HStack>
|
||||
|
||||
<HStack spacing="5">
|
||||
<Link
|
||||
href="https://github.com/privacy-scaling-explorations/bandada"
|
||||
isExternal
|
||||
>
|
||||
<HStack spacing="1">
|
||||
<Icon boxSize={5} as={FiGithub} />
|
||||
<Text textDecoration="underline">Github</Text>
|
||||
</HStack>
|
||||
</Link>
|
||||
</HStack>
|
||||
</HStack>
|
||||
|
||||
<Heading
|
||||
fontSize="40px"
|
||||
as="h1"
|
||||
lineHeight="67px"
|
||||
textAlign="center"
|
||||
>
|
||||
Join Bandada groups
|
||||
<br />
|
||||
by invite .
|
||||
</Heading>
|
||||
|
||||
{!active ? (
|
||||
<Button
|
||||
colorScheme="secondary"
|
||||
variant="solid"
|
||||
onClick={() => activate(injectedConnector)}
|
||||
>
|
||||
Connect Metamask
|
||||
</Button>
|
||||
) : (
|
||||
<VStack w="400px" spacing="5">
|
||||
<VStack align="left" w="100%">
|
||||
<Text>Invite code</Text>
|
||||
<Input
|
||||
size="lg"
|
||||
value={_inviteCode}
|
||||
placeholder="Paste your code here"
|
||||
onChange={(event) =>
|
||||
setInviteCode(event.target.value)
|
||||
}
|
||||
/>
|
||||
</VStack>
|
||||
|
||||
<Button
|
||||
width="100%"
|
||||
colorScheme="secondary"
|
||||
variant="solid"
|
||||
onClick={() => joinGroupByInvite(_inviteCode)}
|
||||
isDisabled={!_inviteCode}
|
||||
isLoading={_loading}
|
||||
>
|
||||
Join group
|
||||
</Button>
|
||||
</VStack>
|
||||
)}
|
||||
</VStack>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
13
apps/client/src/routes.tsx
Normal file
13
apps/client/src/routes.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createBrowserRouter, RouterProvider } from "react-router-dom"
|
||||
import HomePage from "./pages/home"
|
||||
|
||||
export default function Routes(): JSX.Element {
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: "/",
|
||||
element: <HomePage />
|
||||
}
|
||||
])
|
||||
|
||||
return <RouterProvider router={router} />
|
||||
}
|
||||
43
apps/client/src/styles/colors.ts
Normal file
43
apps/client/src/styles/colors.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
const colors = {
|
||||
balticSea: {
|
||||
50: "#f8f7f8",
|
||||
100: "#F6EDF4",
|
||||
200: "#ded9de",
|
||||
300: "#c0b8c1",
|
||||
400: "#9d919f",
|
||||
500: "#827384",
|
||||
600: "#6b5d6c",
|
||||
700: "#574c58",
|
||||
800: "#4b414b",
|
||||
900: "#413941",
|
||||
950: "#231f23"
|
||||
},
|
||||
sunsetOrange: {
|
||||
50: "#fff2f1",
|
||||
100: "#ffe2df",
|
||||
200: "#ffcac5",
|
||||
300: "#ffa59d",
|
||||
400: "#ff7164",
|
||||
500: "#ff5242",
|
||||
600: "#ed2715",
|
||||
700: "#c81d0d",
|
||||
800: "#a51c0f",
|
||||
900: "#881e14",
|
||||
950: "#4b0a04"
|
||||
},
|
||||
classicRose: {
|
||||
50: "#fef1fa",
|
||||
100: "#fee5f7",
|
||||
200: "#ffccf2",
|
||||
300: "#ffa1e6",
|
||||
400: "#ff66d2",
|
||||
500: "#fb39bb",
|
||||
600: "#eb179b",
|
||||
700: "#cd097d",
|
||||
800: "#a90b67",
|
||||
900: "#8d0e57",
|
||||
950: "#570032"
|
||||
}
|
||||
}
|
||||
|
||||
export default colors
|
||||
136
apps/client/src/styles/components/button.ts
Normal file
136
apps/client/src/styles/components/button.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { SystemStyleObject } from "@chakra-ui/react"
|
||||
import { GlobalStyleProps } from "@chakra-ui/theme-tools"
|
||||
|
||||
const height = "48px"
|
||||
const paddingX = "16px"
|
||||
const paddingY = "12px"
|
||||
|
||||
const Button = {
|
||||
baseStyle: {
|
||||
_focus: {
|
||||
boxShadow: "none"
|
||||
},
|
||||
fontFamily: "DM Sans, sans-serif",
|
||||
borderRadius: 8,
|
||||
fontWeight: 500
|
||||
},
|
||||
variants: {
|
||||
outline: (): SystemStyleObject => ({
|
||||
height,
|
||||
paddingX,
|
||||
paddingY
|
||||
}),
|
||||
solid: (props: GlobalStyleProps): SystemStyleObject => {
|
||||
const { colorScheme: c } = props
|
||||
|
||||
if (c === "primary") {
|
||||
const bgGradient =
|
||||
"linear(to-r, sunsetOrange.500, classicRose.600)"
|
||||
const color = "balticSea.50"
|
||||
|
||||
return {
|
||||
bgGradient,
|
||||
color,
|
||||
height,
|
||||
paddingX,
|
||||
paddingY,
|
||||
_hover: {
|
||||
bgGradient:
|
||||
"linear(to-r, sunsetOrange.600, classicRose.700)",
|
||||
_disabled: {
|
||||
bgGradient
|
||||
}
|
||||
},
|
||||
_active: {
|
||||
bgGradient:
|
||||
"linear(to-r, sunsetOrange.700, classicRose.800)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c === "secondary") {
|
||||
const bg = "balticSea.950"
|
||||
const color = "balticSea.100"
|
||||
|
||||
return {
|
||||
bg,
|
||||
fontWeight: 600,
|
||||
fontSize: "13px",
|
||||
color,
|
||||
paddingX,
|
||||
paddingY,
|
||||
_hover: {
|
||||
bg: "balticSea.900",
|
||||
_disabled: {
|
||||
bg
|
||||
}
|
||||
},
|
||||
_active: { bg: "balticSea.700" }
|
||||
}
|
||||
}
|
||||
|
||||
if (c === "tertiary") {
|
||||
const bg = "balticSea.100"
|
||||
const color = "balticSea.900"
|
||||
|
||||
return {
|
||||
bg,
|
||||
fontWeight: 600,
|
||||
fontSize: "13px",
|
||||
color,
|
||||
height,
|
||||
paddingX,
|
||||
paddingY,
|
||||
_hover: {
|
||||
bg: "balticSea.200",
|
||||
_disabled: {
|
||||
bg
|
||||
}
|
||||
},
|
||||
_active: { bg: "balticSea.300" }
|
||||
}
|
||||
}
|
||||
|
||||
if (c === "danger") {
|
||||
const bg = "sunsetOrange.200"
|
||||
const color = "sunsetOrange.950"
|
||||
|
||||
return {
|
||||
bg,
|
||||
fontWeight: 600,
|
||||
fontSize: "13px",
|
||||
color,
|
||||
height,
|
||||
paddingX,
|
||||
paddingY,
|
||||
_hover: {
|
||||
bg: "sunsetOrange.300",
|
||||
_disabled: {
|
||||
bg
|
||||
}
|
||||
},
|
||||
_active: { bg: "sunsetOrange.400" }
|
||||
}
|
||||
}
|
||||
|
||||
const bg = "rgba(0,0,0,0)"
|
||||
|
||||
return {
|
||||
bg,
|
||||
color: `${c}.800`,
|
||||
height,
|
||||
paddingX,
|
||||
paddingY,
|
||||
_hover: {
|
||||
bg: `${c}.200`,
|
||||
_disabled: {
|
||||
bg
|
||||
}
|
||||
},
|
||||
_active: { bg: `${c}.300` }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Button
|
||||
5
apps/client/src/styles/components/index.ts
Normal file
5
apps/client/src/styles/components/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import Button from "./button"
|
||||
|
||||
export default {
|
||||
Button
|
||||
}
|
||||
16
apps/client/src/styles/index.ts
Normal file
16
apps/client/src/styles/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { extendTheme } from "@chakra-ui/react"
|
||||
import styles from "./styles"
|
||||
import colors from "./colors"
|
||||
import components from "./components"
|
||||
|
||||
const config = {
|
||||
fonts: {
|
||||
heading: "Unbounded Variable, sans-serif",
|
||||
body: "DM Sans, sans-serif"
|
||||
},
|
||||
colors,
|
||||
styles,
|
||||
components
|
||||
}
|
||||
|
||||
export default extendTheme(config)
|
||||
26
apps/client/src/styles/styles.ts
Normal file
26
apps/client/src/styles/styles.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { SystemStyleObject } from "@chakra-ui/react"
|
||||
import { Styles } from "@chakra-ui/theme-tools"
|
||||
|
||||
const styles: Styles = {
|
||||
global: (): SystemStyleObject => ({
|
||||
body: {},
|
||||
"body, #root, #root > div": {
|
||||
minHeight: "100vh"
|
||||
},
|
||||
"#root > div": {
|
||||
display: "flex",
|
||||
flexDirection: "column"
|
||||
},
|
||||
h1: {
|
||||
fontWeight: "400 !important"
|
||||
},
|
||||
"h2, h3": {
|
||||
fontWeight: "500 !important"
|
||||
},
|
||||
input: {
|
||||
fontSize: "16px !important"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default styles
|
||||
@@ -1,6 +0,0 @@
|
||||
export type Group = {
|
||||
name: string
|
||||
description: string
|
||||
treeDepth: number
|
||||
members: string[]
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
import { Invite } from "./invite"
|
||||
import { Group } from "./group"
|
||||
|
||||
export type { Invite, Group }
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Group } from "./group"
|
||||
|
||||
export type Invite = {
|
||||
code: string
|
||||
isRedeemed: boolean
|
||||
groupName: string
|
||||
groupId: string
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# This file contains build time variables for dev env.
|
||||
|
||||
VITE_API_URL=http://localhost:3000
|
||||
VITE_CLIENT_INVITES_URL=http://localhost:3002/invites/\
|
||||
VITE_CLIENT_INVITES_URL=http://localhost:3002?inviteCode=\
|
||||
VITE_ETHEREUM_NETWORK=goerli
|
||||
VITE_GITHUB_CLIENT_ID=a83a8b014ef38270fb22
|
||||
VITE_TWITTER_CLIENT_ID=NV82Mm85NWlSZ1llZkpLMl9vN3A6MTpjaQ
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# This file contains build time variables for prod env.
|
||||
|
||||
VITE_API_URL=https://api.bandada.appliedzkp.org
|
||||
VITE_CLIENT_INVITES_URL=https://client.bandada.appliedzkp.org/invites/\
|
||||
VITE_CLIENT_INVITES_URL=https://client.bandada.appliedzkp.org?inviteCode=\
|
||||
VITE_ETHEREUM_NETWORK=goerli
|
||||
VITE_GITHUB_CLIENT_ID=6ccd7b93e84260e353f9
|
||||
VITE_TWITTER_CLIENT_ID=NV82Mm85NWlSZ1llZkpLMl9vN3A6MTpjaQ
|
||||
|
||||
@@ -3,7 +3,7 @@ import { SiweMessage } from "siwe"
|
||||
import { Group } from "../types"
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL
|
||||
const CLIENT_URL = import.meta.env.VITE_CLIENT_INVITES_URL
|
||||
const CLIENT_INVITES_URL = import.meta.env.VITE_CLIENT_INVITES_URL
|
||||
|
||||
/**
|
||||
* It generates a magic link with a valid invite code
|
||||
@@ -26,7 +26,7 @@ export async function generateMagicLink(
|
||||
}
|
||||
})
|
||||
|
||||
return (clientUrl || CLIENT_URL).replace("\\", code)
|
||||
return (clientUrl || CLIENT_INVITES_URL).replace("\\", code)
|
||||
} catch (error: any) {
|
||||
console.error(error)
|
||||
|
||||
|
||||
16
yarn.lock
16
yarn.lock
@@ -783,7 +783,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@bandada/api-sdk@workspace:libs/api-sdk":
|
||||
"@bandada/api-sdk@0.12.0, @bandada/api-sdk@workspace:libs/api-sdk":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@bandada/api-sdk@workspace:libs/api-sdk"
|
||||
dependencies:
|
||||
@@ -5109,16 +5109,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@semaphore-protocol/identity@npm:3.4.0":
|
||||
version: 3.4.0
|
||||
resolution: "@semaphore-protocol/identity@npm:3.4.0"
|
||||
"@semaphore-protocol/identity@npm:3.10.1":
|
||||
version: 3.10.1
|
||||
resolution: "@semaphore-protocol/identity@npm:3.10.1"
|
||||
dependencies:
|
||||
"@ethersproject/bignumber": ^5.5.0
|
||||
"@ethersproject/keccak256": ^5.7.0
|
||||
"@ethersproject/random": ^5.5.1
|
||||
"@ethersproject/strings": ^5.6.1
|
||||
js-sha512: ^0.8.0
|
||||
checksum: ac1c621196d972f8698591cf5fb9e60146f3223a87f77208f2931fc56749e68a14fbc01b7bc2a6abb69bbe69192f579c17db971f55381ba5fa50a561e232c57b
|
||||
checksum: cb00d3bfea550500aa20ffba9a569c10dbe4f32356bff867f5429c2d0fa74f285c0334a10305407d6797308f8398ca23b8bd3170a0f418acca9461f034791682
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -9114,11 +9114,14 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "client@workspace:apps/client"
|
||||
dependencies:
|
||||
"@bandada/api-sdk": 0.12.0
|
||||
"@bandada/utils": 0.12.0
|
||||
"@chakra-ui/react": ^2.5.1
|
||||
"@chakra-ui/theme-tools": ^2.0.16
|
||||
"@emotion/react": ^11.10.6
|
||||
"@emotion/styled": ^11.10.6
|
||||
"@semaphore-protocol/identity": 3.4.0
|
||||
"@fontsource-variable/unbounded": ^5.0.5
|
||||
"@semaphore-protocol/identity": 3.10.1
|
||||
"@types/react": ^18.0.27
|
||||
"@types/react-dom": ^18.0.10
|
||||
"@vitejs/plugin-react": ^3.1.0
|
||||
@@ -9128,6 +9131,7 @@ __metadata:
|
||||
framer-motion: ^10.0.1
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
react-icons: ^4.10.1
|
||||
react-router-dom: ^6.8.1
|
||||
regenerator-runtime: ^0.13.11
|
||||
typescript: ^4.9.3
|
||||
|
||||
Reference in New Issue
Block a user