mirror of
https://github.com/AtHeartEngineering/bandada.git
synced 2026-01-09 02:17:54 -05:00
@@ -38,6 +38,7 @@
|
||||
"no-restricted-syntax": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-underscore-dangle": "off",
|
||||
"react/require-default-props": "off",
|
||||
"consistent-return": "off",
|
||||
"class-methods-use-this": "off",
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
|
||||
9
apps/dashboard/src/assets/image2.svg
Normal file
9
apps/dashboard/src/assets/image2.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 10 MiB |
@@ -7,74 +7,84 @@ import {
|
||||
Text,
|
||||
VStack
|
||||
} from "@chakra-ui/react"
|
||||
import { Link } from "react-router-dom"
|
||||
import icon1Image from "../assets/icon1.svg"
|
||||
import icon2Image from "../assets/icon2.svg"
|
||||
import icon3Image from "../assets/icon3.svg"
|
||||
import icon4Image from "../assets/icon4.svg"
|
||||
import { Group } from "../types"
|
||||
|
||||
export type GroupCardProps = {
|
||||
name?: string
|
||||
type?: string
|
||||
description?: string
|
||||
members?: any[]
|
||||
treeDepth?: number
|
||||
}
|
||||
|
||||
export default function GroupCard({
|
||||
name,
|
||||
type,
|
||||
description,
|
||||
members,
|
||||
treeDepth,
|
||||
id
|
||||
}: Group): JSX.Element {
|
||||
treeDepth
|
||||
}: GroupCardProps): JSX.Element {
|
||||
return (
|
||||
<Link to={`/groups/${type}/${id}`}>
|
||||
<VStack
|
||||
flex="1"
|
||||
align="left"
|
||||
justify="space-between"
|
||||
fontFamily="DM Sans, sans-serif"
|
||||
p="24px"
|
||||
w="350px"
|
||||
h="280px"
|
||||
>
|
||||
<Box>
|
||||
<HStack>
|
||||
<Image
|
||||
src={
|
||||
treeDepth >= 27
|
||||
? icon4Image
|
||||
: treeDepth >= 24
|
||||
? icon3Image
|
||||
: treeDepth >= 20
|
||||
? icon2Image
|
||||
: icon1Image
|
||||
}
|
||||
htmlWidth="35px"
|
||||
alt="Bandada icon"
|
||||
/>
|
||||
<VStack
|
||||
borderRadius="8px"
|
||||
borderColor="balticSea.200"
|
||||
borderWidth="1px"
|
||||
borderStyle="solid"
|
||||
bgColor="balticSea.100"
|
||||
flex="1"
|
||||
align="left"
|
||||
justify="space-between"
|
||||
fontFamily="DM Sans, sans-serif"
|
||||
p="24px"
|
||||
h="280px"
|
||||
>
|
||||
<Box>
|
||||
<HStack>
|
||||
<Image
|
||||
src={
|
||||
!treeDepth
|
||||
? icon1Image
|
||||
: treeDepth >= 27
|
||||
? icon4Image
|
||||
: treeDepth >= 24
|
||||
? icon3Image
|
||||
: treeDepth >= 20
|
||||
? icon2Image
|
||||
: icon1Image
|
||||
}
|
||||
htmlWidth="35px"
|
||||
alt="Bandada icon"
|
||||
/>
|
||||
|
||||
<Tag
|
||||
colorScheme="primary"
|
||||
borderRadius="full"
|
||||
borderWidth={1}
|
||||
borderColor="classicRose.900"
|
||||
color="classicRose.900"
|
||||
bgColor="classicRose.50"
|
||||
>
|
||||
<TagLabel>{type}</TagLabel>
|
||||
</Tag>
|
||||
</HStack>
|
||||
<Tag
|
||||
colorScheme="primary"
|
||||
borderRadius="full"
|
||||
borderWidth={1}
|
||||
borderColor="classicRose.900"
|
||||
color="classicRose.900"
|
||||
bgColor="classicRose.50"
|
||||
>
|
||||
<TagLabel>{type || "on/off chain"}</TagLabel>
|
||||
</Tag>
|
||||
</HStack>
|
||||
|
||||
<Text fontSize="20px" mt="12px">
|
||||
{name}
|
||||
</Text>
|
||||
<Text fontSize="20px" mt="12px">
|
||||
{name || "[untitled]"}
|
||||
</Text>
|
||||
|
||||
<Text mt="12px" color="balticSea.600">
|
||||
{description}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text mt="12px" color="balticSea.600">
|
||||
{description ||
|
||||
(type !== "on-chain" && "[no description yet]")}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<VStack align="left" spacing="0">
|
||||
<Text fontSize="20px">{members.length}</Text>
|
||||
<Text color="balticSea.400">members</Text>
|
||||
</VStack>
|
||||
<VStack align="left" spacing="0">
|
||||
<Text fontSize="20px">{members?.length || 0}</Text>
|
||||
<Text color="balticSea.400">members</Text>
|
||||
</VStack>
|
||||
</Link>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,30 +1,51 @@
|
||||
import { GroupSizes } from "../types"
|
||||
import { GroupSize } from "../types"
|
||||
|
||||
const groupSizes: GroupSizes = {
|
||||
small: {
|
||||
description: "For communities, small teams",
|
||||
capacity: "Capacity 65 thousand",
|
||||
useCases: ["voting", "feedback"],
|
||||
const groupSizes: GroupSize[] = [
|
||||
{
|
||||
name: "Small",
|
||||
description: "Communities and teams",
|
||||
capacity: "Up to 65k members",
|
||||
useCases: [
|
||||
"Donate to your community",
|
||||
"Give event feedback",
|
||||
"Prove demographic, criminal, or health information to an employer"
|
||||
],
|
||||
treeDepth: 16
|
||||
},
|
||||
medium: {
|
||||
description: "For cities, large teams",
|
||||
capacity: "Capacity 1 million",
|
||||
useCases: ["voting", "feedback"],
|
||||
{
|
||||
name: "Medium",
|
||||
description: "Cities and companies",
|
||||
capacity: "Up to 1M members",
|
||||
useCases: [
|
||||
"Vote in your city's election",
|
||||
"Share feedback about work",
|
||||
"Prove professional certification",
|
||||
"Apply for grants/subsidies"
|
||||
],
|
||||
treeDepth: 20
|
||||
},
|
||||
large: {
|
||||
description: "For nations",
|
||||
capacity: "Capacity 33 Million",
|
||||
useCases: ["voting", "feedback"],
|
||||
{
|
||||
name: "Large",
|
||||
description: "Cities, corporations, countries",
|
||||
capacity: "Up to 33M members",
|
||||
useCases: [
|
||||
"Participate in a census",
|
||||
"Vote in a national election",
|
||||
"Donate to a campaign"
|
||||
],
|
||||
treeDepth: 25
|
||||
},
|
||||
xl: {
|
||||
description: "For multiple nations, contries",
|
||||
capacity: "Capacity 1 Billion",
|
||||
useCases: ["voting", "feedback"],
|
||||
{
|
||||
name: "XL",
|
||||
description: "Large countries or multiple nations",
|
||||
capacity: "Up to 1B members",
|
||||
useCases: [
|
||||
"Prove passport status",
|
||||
"Share health status with other countries",
|
||||
"Sponsor a cause"
|
||||
],
|
||||
treeDepth: 30
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export default groupSizes
|
||||
|
||||
@@ -11,24 +11,23 @@ import {
|
||||
InputRightElement,
|
||||
Spinner,
|
||||
Text,
|
||||
useDisclosure,
|
||||
VStack
|
||||
} from "@chakra-ui/react"
|
||||
import { useCallback, useContext, useEffect, useState } from "react"
|
||||
import { FiSearch } from "react-icons/fi"
|
||||
import { getGroups as getOnchainGroups } from "../api/semaphoreAPI"
|
||||
import { Link, useNavigate } from "react-router-dom"
|
||||
import { getGroups as getOffchainGroups } from "../api/bandadaAPI"
|
||||
import CreateGroupModal from "../components/create-group-modal"
|
||||
import { getGroups as getOnchainGroups } from "../api/semaphoreAPI"
|
||||
import GroupCard from "../components/group-card"
|
||||
import { AuthContext } from "../context/auth-context"
|
||||
import { Group } from "../types"
|
||||
|
||||
export default function GroupsPage(): JSX.Element {
|
||||
const { admin } = useContext(AuthContext)
|
||||
const createGroupModal = useDisclosure()
|
||||
const [_isLoading, setIsLoading] = useState(false)
|
||||
const [_groups, setGroups] = useState<Group[]>([])
|
||||
const [_searchField, setSearchField] = useState<string>("")
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
@@ -57,21 +56,6 @@ export default function GroupsPage(): JSX.Element {
|
||||
})()
|
||||
}, [admin])
|
||||
|
||||
const addGroup = useCallback(
|
||||
(group?: Group) => {
|
||||
if (!group) {
|
||||
createGroupModal.onClose()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
setGroups([group, ..._groups])
|
||||
|
||||
createGroupModal.onClose()
|
||||
},
|
||||
[_groups, createGroupModal]
|
||||
)
|
||||
|
||||
const filterGroup = useCallback(
|
||||
(group: Group) =>
|
||||
group.name.toLowerCase().includes(_searchField.toLowerCase()),
|
||||
@@ -122,7 +106,7 @@ export default function GroupsPage(): JSX.Element {
|
||||
<Button
|
||||
variant="solid"
|
||||
colorScheme="primary"
|
||||
onClick={createGroupModal.onOpen}
|
||||
onClick={() => navigate("/groups/new")}
|
||||
>
|
||||
Add group
|
||||
</Button>
|
||||
@@ -153,25 +137,15 @@ export default function GroupsPage(): JSX.Element {
|
||||
a.name < b.name ? -1 : a.name > b.name ? 1 : 0
|
||||
)
|
||||
.map((group) => (
|
||||
<GridItem
|
||||
borderRadius="8px"
|
||||
borderColor="balticSea.200"
|
||||
borderWidth="1px"
|
||||
borderStyle="solid"
|
||||
bgColor="balticSea.100"
|
||||
key={group.id + group.name}
|
||||
>
|
||||
<GroupCard {...group} />
|
||||
</GridItem>
|
||||
<Link to={`/groups/${group.type}/${group.id}`}>
|
||||
<GridItem key={group.id + group.name}>
|
||||
<GroupCard {...group} />
|
||||
</GridItem>
|
||||
</Link>
|
||||
))}
|
||||
</Grid>
|
||||
)}
|
||||
</VStack>
|
||||
|
||||
<CreateGroupModal
|
||||
isOpen={createGroupModal.isOpen}
|
||||
onClose={addGroup}
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
502
apps/dashboard/src/pages/new-group.tsx
Normal file
502
apps/dashboard/src/pages/new-group.tsx
Normal file
@@ -0,0 +1,502 @@
|
||||
import { validators } from "@bandada/reputation"
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Heading,
|
||||
HStack,
|
||||
Icon,
|
||||
Image,
|
||||
Input,
|
||||
ListItem,
|
||||
Select,
|
||||
Tag,
|
||||
Text,
|
||||
UnorderedList,
|
||||
VStack
|
||||
} from "@chakra-ui/react"
|
||||
import { useState } from "react"
|
||||
import { FiHardDrive, FiZap } from "react-icons/fi"
|
||||
import { MdOutlineKeyboardArrowRight } from "react-icons/md"
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import icon1Image from "../assets/icon1.svg"
|
||||
import icon2Image from "../assets/icon2.svg"
|
||||
import icon3Image from "../assets/icon3.svg"
|
||||
import icon4Image from "../assets/icon4.svg"
|
||||
import image2 from "../assets/image2.svg"
|
||||
import GroupCard from "../components/group-card"
|
||||
import { groupSizes } from "../data"
|
||||
import capitalize from "../utils/capitalize"
|
||||
|
||||
const steps = ["General info", "Group size", "Member mechanism", "Summary"]
|
||||
const groupTypes = ["on-chain", "off-chain"]
|
||||
const accessModes = ["manual", "credentials"]
|
||||
|
||||
export default function NewGroupPage(): JSX.Element {
|
||||
const [_currentStep, setCurrentStep] = useState<number>(0)
|
||||
const [_groupName, setGroupName] = useState<string>("")
|
||||
const [_groupDescription, setGroupDescription] = useState<string>()
|
||||
const [_groupType, setGroupType] = useState<"off-chain" | "on-chain">()
|
||||
const [_treeDepth, setTreeDepth] = useState<number>()
|
||||
const [_accessMode, setAccessMode] = useState<"manual" | "credentials">()
|
||||
const navigate = useNavigate()
|
||||
|
||||
return (
|
||||
<Container maxW="container.xl" px="8" pb="20">
|
||||
<VStack spacing="9" flex="1">
|
||||
<HStack justifyContent="space-between" width="100%">
|
||||
<Heading fontSize="40px" as="h1">
|
||||
Nueva bandada
|
||||
</Heading>
|
||||
</HStack>
|
||||
|
||||
<HStack w="100%" bg="balticSea.50" p="16px" borderRadius="8px">
|
||||
{steps.map((step, i) => (
|
||||
<HStack
|
||||
onClick={
|
||||
i < _currentStep
|
||||
? () => setCurrentStep(i)
|
||||
: undefined
|
||||
}
|
||||
cursor={i < _currentStep ? "pointer" : "inherit"}
|
||||
color={
|
||||
i === _currentStep
|
||||
? "balticSea.800"
|
||||
: "balticSea.500"
|
||||
}
|
||||
key={step}
|
||||
>
|
||||
<Text
|
||||
color={
|
||||
i === _currentStep
|
||||
? "balticSea.50"
|
||||
: "balticSea.800"
|
||||
}
|
||||
fontSize="13px"
|
||||
py="4px"
|
||||
px="10px"
|
||||
borderRadius="50px"
|
||||
bgGradient={
|
||||
i === _currentStep
|
||||
? "linear(to-r, sunsetOrange.500, classicRose.600)"
|
||||
: "linear(to-r, balticSea.200, balticSea.200)"
|
||||
}
|
||||
>
|
||||
{i + 1}
|
||||
</Text>
|
||||
<Text>{step}</Text>
|
||||
{i !== steps.length - 1 && (
|
||||
<Icon
|
||||
as={MdOutlineKeyboardArrowRight}
|
||||
boxSize={5}
|
||||
/>
|
||||
)}
|
||||
</HStack>
|
||||
))}
|
||||
</HStack>
|
||||
|
||||
<HStack w="100%" align="start">
|
||||
<VStack
|
||||
align="left"
|
||||
position="relative"
|
||||
w="374px"
|
||||
h="483px"
|
||||
bgImg={`url(${image2})`}
|
||||
bgRepeat="no-repeat"
|
||||
p="20px"
|
||||
borderRadius="8px"
|
||||
>
|
||||
<Box
|
||||
position="absolute"
|
||||
h="300px"
|
||||
w="100%"
|
||||
top="0px"
|
||||
left="0px"
|
||||
bgGradient="linear(169.41deg, #402A75 3.98%, rgba(220, 189, 238, 0) 65.06%)"
|
||||
borderRadius="8px"
|
||||
/>
|
||||
|
||||
<Heading
|
||||
zIndex="1"
|
||||
fontSize="25px"
|
||||
as="h1"
|
||||
color="balticSea.50"
|
||||
pb="16px"
|
||||
>
|
||||
Group preview
|
||||
</Heading>
|
||||
|
||||
<Box zIndex="1">
|
||||
<GroupCard
|
||||
name={_groupName}
|
||||
description={_groupDescription}
|
||||
type={_groupType}
|
||||
treeDepth={_treeDepth}
|
||||
/>
|
||||
</Box>
|
||||
</VStack>
|
||||
<VStack
|
||||
bg="balticSea.50"
|
||||
py="25px"
|
||||
px="35px"
|
||||
borderRadius="8px"
|
||||
flex="1"
|
||||
align="left"
|
||||
>
|
||||
{_currentStep === 0 ? (
|
||||
<>
|
||||
<Text>What type of group is this?</Text>
|
||||
|
||||
<HStack>
|
||||
{groupTypes.map((groupType: any) => (
|
||||
<VStack
|
||||
borderColor={
|
||||
_groupType === groupType
|
||||
? "classicRose.600"
|
||||
: "balticSea.200"
|
||||
}
|
||||
borderWidth="2px"
|
||||
borderRadius="8px"
|
||||
w="252px"
|
||||
h="210px"
|
||||
align="left"
|
||||
spacing="0"
|
||||
cursor="pointer"
|
||||
onClick={() =>
|
||||
setGroupType(groupType)
|
||||
}
|
||||
key={groupType}
|
||||
>
|
||||
<HStack
|
||||
bgColor={
|
||||
_groupType === groupType
|
||||
? "classicRose.100"
|
||||
: "balticSea.100"
|
||||
}
|
||||
px="20px"
|
||||
py="15px"
|
||||
borderTopRadius="8px"
|
||||
spacing="3"
|
||||
>
|
||||
<Icon
|
||||
color={
|
||||
_groupType === groupType
|
||||
? "classicRose.600"
|
||||
: "balticSea.600"
|
||||
}
|
||||
boxSize="5"
|
||||
as={
|
||||
groupType === "on-chain"
|
||||
? FiZap
|
||||
: FiHardDrive
|
||||
}
|
||||
/>
|
||||
|
||||
<Text>
|
||||
{groupType === "on-chain"
|
||||
? "On chain"
|
||||
: "Off chain"}
|
||||
</Text>
|
||||
</HStack>
|
||||
|
||||
<Text
|
||||
color="balticSea.700"
|
||||
px="16px"
|
||||
py="10px"
|
||||
>
|
||||
Quick summary of pros and cons
|
||||
of on-chain groups, spanning
|
||||
about 3 lines?
|
||||
</Text>
|
||||
</VStack>
|
||||
))}
|
||||
</HStack>
|
||||
|
||||
<VStack align="left" pt="20px">
|
||||
<Text>Name</Text>
|
||||
|
||||
<Input
|
||||
size="lg"
|
||||
value={_groupName}
|
||||
onChange={(event) =>
|
||||
setGroupName(event.target.value)
|
||||
}
|
||||
/>
|
||||
<Text fontSize="13px" color="balticSea.500">
|
||||
Give it a cool name you can recognize.
|
||||
</Text>
|
||||
</VStack>
|
||||
|
||||
{_groupType === "off-chain" && (
|
||||
<VStack align="left" pt="20px">
|
||||
<Text>Description</Text>
|
||||
|
||||
<Input
|
||||
size="lg"
|
||||
minLength={10}
|
||||
value={_groupDescription ?? ""}
|
||||
onChange={(event) =>
|
||||
setGroupDescription(
|
||||
event.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Text
|
||||
fontSize="13px"
|
||||
color="balticSea.500"
|
||||
>
|
||||
Describe your group.
|
||||
</Text>
|
||||
</VStack>
|
||||
)}
|
||||
|
||||
{_groupType && (
|
||||
<Box pt="20px">
|
||||
<Text
|
||||
p="16px"
|
||||
borderRadius="8px"
|
||||
bgColor="classicRose.100"
|
||||
color="classicRose.900"
|
||||
>
|
||||
{_groupType === "off-chain"
|
||||
? "By continuing, you will create that will be stored in our servers."
|
||||
: "By continuing, you will create that lives on the Ethereum blockchain."}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
) : _currentStep === 1 ? (
|
||||
<>
|
||||
<Text>How big is your group?</Text>
|
||||
|
||||
<HStack w="764px" py="16px" overflowX="scroll">
|
||||
{groupSizes.map((groupSize) => (
|
||||
<VStack
|
||||
borderColor={
|
||||
_treeDepth ===
|
||||
groupSize.treeDepth
|
||||
? "classicRose.600"
|
||||
: "balticSea.300"
|
||||
}
|
||||
borderWidth="2px"
|
||||
borderRadius="8px"
|
||||
minW="320px"
|
||||
h="370px"
|
||||
align="start"
|
||||
spacing="0"
|
||||
cursor="pointer"
|
||||
p="16px"
|
||||
onClick={() =>
|
||||
setTreeDepth(
|
||||
groupSize.treeDepth
|
||||
)
|
||||
}
|
||||
key={groupSize.name}
|
||||
>
|
||||
<Image
|
||||
src={
|
||||
groupSize.treeDepth >= 27
|
||||
? icon4Image
|
||||
: groupSize.treeDepth >=
|
||||
24
|
||||
? icon3Image
|
||||
: groupSize.treeDepth >=
|
||||
20
|
||||
? icon2Image
|
||||
: icon1Image
|
||||
}
|
||||
htmlWidth="50px"
|
||||
alt="Bandada icon"
|
||||
/>
|
||||
|
||||
<Heading
|
||||
fontSize="25px"
|
||||
as="h1"
|
||||
pt="16px"
|
||||
pb="10px"
|
||||
>
|
||||
{groupSize.name}
|
||||
</Heading>
|
||||
|
||||
<Tag
|
||||
colorScheme="primary"
|
||||
borderRadius="full"
|
||||
borderWidth={1}
|
||||
borderColor="classicRose.900"
|
||||
color="classicRose.900"
|
||||
bgColor="classicRose.50"
|
||||
>
|
||||
{groupSize.capacity}
|
||||
</Tag>
|
||||
|
||||
<Text
|
||||
color="balticSea.500"
|
||||
py="10px"
|
||||
>
|
||||
{groupSize.description}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
color="balticSea.700"
|
||||
pt="10px"
|
||||
>
|
||||
Anonymously:
|
||||
</Text>
|
||||
<UnorderedList
|
||||
color="balticSea.700"
|
||||
pl="20px"
|
||||
>
|
||||
{groupSize.useCases.map(
|
||||
(useCase) => (
|
||||
<ListItem key={useCase}>
|
||||
{useCase}
|
||||
</ListItem>
|
||||
)
|
||||
)}
|
||||
</UnorderedList>
|
||||
</VStack>
|
||||
))}
|
||||
</HStack>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<HStack>
|
||||
{accessModes.map((accessMode: any) => (
|
||||
<VStack
|
||||
borderColor={
|
||||
_accessMode === accessMode
|
||||
? "classicRose.600"
|
||||
: "balticSea.200"
|
||||
}
|
||||
borderWidth="2px"
|
||||
borderRadius="8px"
|
||||
w="252px"
|
||||
h="210px"
|
||||
align="left"
|
||||
spacing="0"
|
||||
cursor="pointer"
|
||||
onClick={() =>
|
||||
setAccessMode(accessMode)
|
||||
}
|
||||
key={accessMode}
|
||||
>
|
||||
<HStack
|
||||
bgColor={
|
||||
_accessMode === accessMode
|
||||
? "classicRose.100"
|
||||
: "balticSea.100"
|
||||
}
|
||||
px="20px"
|
||||
py="15px"
|
||||
borderTopRadius="8px"
|
||||
spacing="3"
|
||||
>
|
||||
<Icon
|
||||
color={
|
||||
_accessMode ===
|
||||
accessMode
|
||||
? "classicRose.600"
|
||||
: "balticSea.600"
|
||||
}
|
||||
boxSize="5"
|
||||
as={
|
||||
accessMode ===
|
||||
"on-chain"
|
||||
? FiZap
|
||||
: FiHardDrive
|
||||
}
|
||||
/>
|
||||
|
||||
<Text>
|
||||
{capitalize(accessMode)}
|
||||
</Text>
|
||||
</HStack>
|
||||
|
||||
<Text
|
||||
color="balticSea.700"
|
||||
px="16px"
|
||||
py="10px"
|
||||
>
|
||||
{accessMode === "manual"
|
||||
? "I’ll add members by pasting in their address or sending them a generated invite link."
|
||||
: "Members can join my group if they fit the criteria I will setup."}
|
||||
</Text>
|
||||
</VStack>
|
||||
))}
|
||||
</HStack>
|
||||
|
||||
{_accessMode === "credentials" && (
|
||||
<>
|
||||
<VStack align="left" pt="20px">
|
||||
<Text>
|
||||
Choose credential and provider
|
||||
</Text>
|
||||
|
||||
<Select
|
||||
size="lg"
|
||||
color="balticSea.400"
|
||||
>
|
||||
{validators.map((validator) => (
|
||||
<option
|
||||
key={validator.id}
|
||||
value={validator.id}
|
||||
>
|
||||
{validator.id}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</VStack>
|
||||
|
||||
<Box pt="20px">
|
||||
<Text
|
||||
p="16px"
|
||||
borderRadius="8px"
|
||||
bgColor="classicRose.100"
|
||||
color="classicRose.900"
|
||||
>
|
||||
Disclaimer: We will use a bit of
|
||||
your member’s data to check if
|
||||
they meet the criteria and
|
||||
generate their reputation to
|
||||
join the group.
|
||||
</Text>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<HStack justify="right" pt="20px">
|
||||
<Button
|
||||
variant="solid"
|
||||
colorScheme="tertiary"
|
||||
onClick={() =>
|
||||
_currentStep === 0
|
||||
? navigate("/groups")
|
||||
: setCurrentStep(_currentStep - 1)
|
||||
}
|
||||
>
|
||||
{_currentStep === 0 ? "Cancel" : "Back"}
|
||||
</Button>
|
||||
<Button
|
||||
isDisabled={
|
||||
!_groupName ||
|
||||
(_groupType === "off-chain" &&
|
||||
!_groupDescription) ||
|
||||
!_groupType ||
|
||||
(_currentStep === 1 && !_treeDepth) ||
|
||||
(_currentStep === 2 && !_accessMode)
|
||||
}
|
||||
variant="solid"
|
||||
colorScheme="primary"
|
||||
onClick={() => setCurrentStep(_currentStep + 1)}
|
||||
>
|
||||
Continue
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import NotFoundPage from "./pages/404"
|
||||
import GroupPage from "./pages/group"
|
||||
import GroupsPage from "./pages/groups"
|
||||
import HomePage from "./pages/home"
|
||||
import NewGroupPage from "./pages/new-group"
|
||||
import ReputationPage from "./pages/reputation"
|
||||
|
||||
export default function Routes(): JSX.Element {
|
||||
@@ -35,6 +36,10 @@ export default function Routes(): JSX.Element {
|
||||
path: "groups",
|
||||
element: <GroupsPage />
|
||||
},
|
||||
{
|
||||
path: "groups/new",
|
||||
element: <NewGroupPage />
|
||||
},
|
||||
{
|
||||
path: "groups/:groupType/:groupId",
|
||||
element: <GroupPage />
|
||||
|
||||
@@ -13,12 +13,11 @@ export type Group = {
|
||||
}
|
||||
|
||||
export type GroupSize = {
|
||||
name: string
|
||||
description: string
|
||||
capacity: string
|
||||
useCases: string[]
|
||||
treeDepth: number
|
||||
}
|
||||
|
||||
export type GroupSizes = Record<string, GroupSize>
|
||||
|
||||
export default Group
|
||||
|
||||
3
apps/dashboard/src/utils/capitalize.ts
Normal file
3
apps/dashboard/src/utils/capitalize.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function capitalize(s: string) {
|
||||
return s[0].toUpperCase() + s.substring(1)
|
||||
}
|
||||
Reference in New Issue
Block a user