From 6349d51275ba92e69981fa9b3db97b6c3be0a8a6 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 01:41:43 -0700 Subject: [PATCH 01/48] half-decent redirect --- apps/web/src/pages/index.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/web/src/pages/index.tsx b/apps/web/src/pages/index.tsx index 132c1df8..b524a099 100644 --- a/apps/web/src/pages/index.tsx +++ b/apps/web/src/pages/index.tsx @@ -1,5 +1,7 @@ import { Stack } from '@zoralabs/zord' +import { useRouter } from 'next/router' import React from 'react' +import { useAccount } from 'wagmi' import Everything from 'src/components/Home/Everything' import FAQ from 'src/components/Home/FAQ' @@ -17,10 +19,21 @@ import { NextPageWithLayout } from './_app' export type DaoProps = AuctionFragment['dao'] const HomePage: NextPageWithLayout = () => { + const router = useRouter() + const _account = useAccount({ + onConnect({ address, isReconnected }) { + const wasRedirected = sessionStorage.getItem('wasRedirected') + if (address && isReconnected && !wasRedirected) { + sessionStorage.setItem('wasRedirected', 'true') + router.push('/about') + } + }, + }) return ( <> + {/* */} From 7e5d1109e61ba6f85948dfc4da8ebcda518093f8 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 02:46:47 -0700 Subject: [PATCH 02/48] slightly better redirect --- apps/web/src/layouts/DefaultLayout/Nav.tsx | 3 ++ .../web/src/layouts/DefaultLayout/NavMenu.tsx | 7 +++++ apps/web/src/pages/index.tsx | 31 +++++++++++++------ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/apps/web/src/layouts/DefaultLayout/Nav.tsx b/apps/web/src/layouts/DefaultLayout/Nav.tsx index e0778271..4c16430d 100644 --- a/apps/web/src/layouts/DefaultLayout/Nav.tsx +++ b/apps/web/src/layouts/DefaultLayout/Nav.tsx @@ -53,6 +53,9 @@ export const Nav = () => { + + + diff --git a/apps/web/src/layouts/DefaultLayout/NavMenu.tsx b/apps/web/src/layouts/DefaultLayout/NavMenu.tsx index 799642d8..0c2b8841 100644 --- a/apps/web/src/layouts/DefaultLayout/NavMenu.tsx +++ b/apps/web/src/layouts/DefaultLayout/NavMenu.tsx @@ -376,6 +376,13 @@ export const NavMenu = () => { + + + + Dashboard + + + diff --git a/apps/web/src/pages/index.tsx b/apps/web/src/pages/index.tsx index b524a099..7cbafdf7 100644 --- a/apps/web/src/pages/index.tsx +++ b/apps/web/src/pages/index.tsx @@ -1,6 +1,6 @@ import { Stack } from '@zoralabs/zord' import { useRouter } from 'next/router' -import React from 'react' +import React, { useEffect } from 'react' import { useAccount } from 'wagmi' import Everything from 'src/components/Home/Everything' @@ -20,15 +20,26 @@ export type DaoProps = AuctionFragment['dao'] const HomePage: NextPageWithLayout = () => { const router = useRouter() - const _account = useAccount({ - onConnect({ address, isReconnected }) { - const wasRedirected = sessionStorage.getItem('wasRedirected') - if (address && isReconnected && !wasRedirected) { - sessionStorage.setItem('wasRedirected', 'true') - router.push('/about') - } - }, - }) + const { address } = useAccount() + // { + // onConnect({ address }) { + // const wasRedirected = sessionStorage.getItem('wasRedirected') + + // if (address && !wasRedirected) { + // sessionStorage.setItem('wasRedirected', 'true') + // router.push('/about') + // } + // }, + // } + + // useEffect helps load redirect a little faster on page load + useEffect(() => { + const wasRedirected = sessionStorage.getItem('wasRedirected') + if (address && !wasRedirected) { + sessionStorage.setItem('wasRedirected', 'true') + router.push('/about') + } + }, [address]) return ( <> From a581590afe5ee124e77cc2cd7ba858e60757a3d2 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 15:53:24 -0700 Subject: [PATCH 03/48] fetcher, api route, and query --- .../data/subgraph/requests/dashboardQuery.ts | 61 +++++++++++++++++++ apps/web/src/pages/api/dashboard/[user].ts | 30 +++++++++ apps/web/src/pages/dashboard.tsx | 23 +++++++ 3 files changed, 114 insertions(+) create mode 100644 apps/web/src/data/subgraph/requests/dashboardQuery.ts create mode 100644 apps/web/src/pages/api/dashboard/[user].ts create mode 100644 apps/web/src/pages/dashboard.tsx diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts new file mode 100644 index 00000000..f5b033dc --- /dev/null +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -0,0 +1,61 @@ +import * as Sentry from '@sentry/nextjs' + +import { PUBLIC_DEFAULT_CHAINS } from 'src/constants/defaultChains' +import { SDK } from 'src/data/subgraph/client' +import { CHAIN_ID } from 'src/typings' + +export type MyDaosResponse = Array<{ + name: string + collectionAddress: string + auctionAddress: string + chainId: CHAIN_ID +}> + +const DAOS_TO_EXCLUDE = [ + '0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03', + '0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b', +] + +export const dashboardRequest = async (memberAddress: string) => { + // let daos: MyDaosResponse = [] + + if (!memberAddress) throw new Error('No user address provided') + + try { + const data = await Promise.all( + PUBLIC_DEFAULT_CHAINS.map((chain) => + SDK.connect(chain.id) + .daoTokenOwners({ + where: { + owner: memberAddress, + }, + first: 30, + }) + .then((x) => ({ ...x, chainId: chain.id })) + ) + ) + + return data + .map((queries) => + queries.daotokenOwners + .map((x) => { + return x.dao + }) + .filter((dao) => !DAOS_TO_EXCLUDE.includes(dao.tokenAddress)) + .map((dao) => ({ + name: dao.name || '', + collectionAddress: dao.tokenAddress, + auctionAddress: dao?.auctionAddress || '', + chainId: queries.chainId, + })) + ) + .flat() + .sort((a, b) => a.name.localeCompare(b.name)) + } catch (e: any) { + console.error(e) + Sentry.captureException(e) + await Sentry.flush(2000) + } + + // return daos +} diff --git a/apps/web/src/pages/api/dashboard/[user].ts b/apps/web/src/pages/api/dashboard/[user].ts new file mode 100644 index 00000000..7e402ad8 --- /dev/null +++ b/apps/web/src/pages/api/dashboard/[user].ts @@ -0,0 +1,30 @@ +import { getAddress } from 'ethers/lib/utils.js' +import { NextApiRequest, NextApiResponse } from 'next' + +import { dashboardRequest } from 'src/data/subgraph/requests/dashboardQuery' +import { NotFoundError } from 'src/services/errors' + +const handler = async (req: NextApiRequest, res: NextApiResponse) => { + const { user } = req.query + + let address: string + + try { + address = getAddress(user as string) + } catch (e) { + return res.status(400).json({ error: 'bad address input' }) + } + try { + const daos = await dashboardRequest(address) + + res.status(200).json(daos) + } catch (e) { + if (e instanceof NotFoundError) { + return res.status(404).json({ error: 'daos not found' }) + } + + return res.status(500).json({ error: 'backend failed' }) + } +} + +export default handler diff --git a/apps/web/src/pages/dashboard.tsx b/apps/web/src/pages/dashboard.tsx new file mode 100644 index 00000000..89f63726 --- /dev/null +++ b/apps/web/src/pages/dashboard.tsx @@ -0,0 +1,23 @@ +import axios from 'axios' +import React from 'react' +import useSWR from 'swr' +import { useAccount } from 'wagmi' + +const fetchDashboardData = async (address: string) => { + const userDaos = await axios.get(`/api/dashboard/${address}`).then((x) => x.data) + console.log('userDaos', userDaos) + return userDaos +} + +const Dashboard = () => { + const { address } = useAccount() + + const { data, error, isValidating } = useSWR( + [`dashboard:${address}`], + address ? () => fetchDashboardData(address) : null + ) + + return
Dashboard
+} + +export default Dashboard From 1a9f6fcc3807a9a27d7f67529c5b78231b74ef1d Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 16:32:41 -0700 Subject: [PATCH 04/48] write query that bundles proposals, current auction data with user dao data --- .../subgraph/queries/dashboardQuery.graphql | 26 +++++ .../data/subgraph/requests/dashboardQuery.ts | 7 +- apps/web/src/data/subgraph/sdk.generated.ts | 96 ++++++++++++++++++- 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 apps/web/src/data/subgraph/queries/dashboardQuery.graphql diff --git a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql new file mode 100644 index 00000000..ef85d80b --- /dev/null +++ b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql @@ -0,0 +1,26 @@ +query dashboard($where: DAOTokenOwner_filter, $first: Int, $skip: Int) { + daotokenOwners(where: $where, first: $first, skip: $skip) { + dao { + ...DAO + proposals( + where: { executed_not: true, canceled_not: true, vetoed_not: true } + first: 10 + skip: 0 + orderBy: proposalNumber + orderDirection: desc + ) { + ...Proposal + } + currentAuction { + endTime + highestBid { + amount + } + token { + name + image + } + } + } + } +} diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts index f5b033dc..d3f0900c 100644 --- a/apps/web/src/data/subgraph/requests/dashboardQuery.ts +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -20,14 +20,14 @@ export const dashboardRequest = async (memberAddress: string) => { // let daos: MyDaosResponse = [] if (!memberAddress) throw new Error('No user address provided') - + console.log('memberAddress', memberAddress) try { const data = await Promise.all( PUBLIC_DEFAULT_CHAINS.map((chain) => SDK.connect(chain.id) - .daoTokenOwners({ + .dashboard({ where: { - owner: memberAddress, + owner: memberAddress.toLowerCase(), }, first: 30, }) @@ -43,6 +43,7 @@ export const dashboardRequest = async (memberAddress: string) => { }) .filter((dao) => !DAOS_TO_EXCLUDE.includes(dao.tokenAddress)) .map((dao) => ({ + ...dao, name: dao.name || '', collectionAddress: dao.tokenAddress, auctionAddress: dao?.auctionAddress || '', diff --git a/apps/web/src/data/subgraph/sdk.generated.ts b/apps/web/src/data/subgraph/sdk.generated.ts index a7e6d8b4..a18fe1bc 100644 --- a/apps/web/src/data/subgraph/sdk.generated.ts +++ b/apps/web/src/data/subgraph/sdk.generated.ts @@ -2041,6 +2041,56 @@ export type DaoTokenOwnersQuery = { }> } +export type DashboardQueryVariables = Exact<{ + where?: InputMaybe + first?: InputMaybe + skip?: InputMaybe +}> + +export type DashboardQuery = { + __typename?: 'Query' + daotokenOwners: Array<{ + __typename?: 'DAOTokenOwner' + dao: { + __typename?: 'DAO' + name: string + tokenAddress: any + auctionAddress: any + proposals: Array<{ + __typename?: 'Proposal' + abstainVotes: number + againstVotes: number + calldatas?: string | null + description?: string | null + descriptionHash: any + executableFrom?: any | null + expiresAt?: any | null + forVotes: number + proposalId: any + proposalNumber: number + proposalThreshold: any + proposer: any + quorumVotes: any + targets: Array + timeCreated: any + title?: string | null + values: Array + voteEnd: any + voteStart: any + snapshotBlockNumber: any + transactionHash: any + dao: { __typename?: 'DAO'; governorAddress: any; tokenAddress: any } + }> + currentAuction?: { + __typename?: 'Auction' + endTime: any + highestBid?: { __typename?: 'AuctionBid'; amount: any } | null + token: { __typename?: 'Token'; name: string; image: string } + } | null + } + }> +} + export type ExploreDaosPageQueryVariables = Exact<{ orderBy?: InputMaybe orderDirection?: InputMaybe @@ -2363,7 +2413,7 @@ export const TokenFragmentDoc = gql` ` export const ActiveAuctionsDocument = gql` query activeAuctions($first: Int!, $where: Auction_filter!) { - auctions(orderBy: endTime, orderDirection: asc, first: $first, where: $where) { + auctions(orderBy: endTime, orderDirection: desc, first: $first, where: $where) { ...Auction } } @@ -2470,6 +2520,36 @@ export const DaoTokenOwnersDocument = gql` } ${DaoFragmentDoc} ` +export const DashboardDocument = gql` + query dashboard($where: DAOTokenOwner_filter, $first: Int, $skip: Int) { + daotokenOwners(where: $where, first: $first, skip: $skip) { + dao { + ...DAO + proposals( + where: { executed_not: true, canceled_not: true, vetoed_not: true } + first: 10 + skip: 0 + orderBy: proposalNumber + orderDirection: desc + ) { + ...Proposal + } + currentAuction { + endTime + highestBid { + amount + } + token { + name + image + } + } + } + } + } + ${DaoFragmentDoc} + ${ProposalFragmentDoc} +` export const ExploreDaosPageDocument = gql` query exploreDaosPage( $orderBy: Auction_orderBy @@ -2727,6 +2807,20 @@ export function getSdk( 'query' ) }, + dashboard( + variables?: DashboardQueryVariables, + requestHeaders?: Dom.RequestInit['headers'] + ): Promise { + return withWrapper( + (wrappedRequestHeaders) => + client.request(DashboardDocument, variables, { + ...requestHeaders, + ...wrappedRequestHeaders, + }), + 'dashboard', + 'query' + ) + }, exploreDaosPage( variables?: ExploreDaosPageQueryVariables, requestHeaders?: Dom.RequestInit['headers'] From 9a99a8a2f2166f3ad408e7de80058fe9f848f429 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 17:58:32 -0700 Subject: [PATCH 05/48] finish rough query, fetch proposal states on client --- .../subgraph/fragments/CurrentAuction.graphql | 11 ++++ .../subgraph/queries/dashboardQuery.graphql | 9 +-- .../data/subgraph/requests/dashboardQuery.ts | 25 +++++--- apps/web/src/data/subgraph/sdk.generated.ts | 32 +++++++--- apps/web/src/pages/dashboard.tsx | 63 +++++++++++++++++-- 5 files changed, 110 insertions(+), 30 deletions(-) create mode 100644 apps/web/src/data/subgraph/fragments/CurrentAuction.graphql diff --git a/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql b/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql new file mode 100644 index 00000000..72aebfa4 --- /dev/null +++ b/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql @@ -0,0 +1,11 @@ +fragment CurrentAuction on Auction { + endTime + highestBid { + amount + } + token { + name + image + tokenId + } +} diff --git a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql index ef85d80b..4879c78f 100644 --- a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql +++ b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql @@ -12,14 +12,7 @@ query dashboard($where: DAOTokenOwner_filter, $first: Int, $skip: Int) { ...Proposal } currentAuction { - endTime - highestBid { - amount - } - token { - name - image - } + ...CurrentAuction } } } diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts index d3f0900c..3eb367b7 100644 --- a/apps/web/src/data/subgraph/requests/dashboardQuery.ts +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -4,23 +4,29 @@ import { PUBLIC_DEFAULT_CHAINS } from 'src/constants/defaultChains' import { SDK } from 'src/data/subgraph/client' import { CHAIN_ID } from 'src/typings' -export type MyDaosResponse = Array<{ - name: string - collectionAddress: string - auctionAddress: string - chainId: CHAIN_ID -}> +import { + CurrentAuctionFragment, + DaoFragment, + ProposalFragment, +} from '../sdk.generated' const DAOS_TO_EXCLUDE = [ '0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03', '0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b', ] +type DashboardDaos = DaoFragment & + { + chainId: CHAIN_ID + proposals: ProposalFragment[] + currentAuction: CurrentAuctionFragment + }[] + export const dashboardRequest = async (memberAddress: string) => { // let daos: MyDaosResponse = [] if (!memberAddress) throw new Error('No user address provided') - console.log('memberAddress', memberAddress) + try { const data = await Promise.all( PUBLIC_DEFAULT_CHAINS.map((chain) => @@ -43,10 +49,11 @@ export const dashboardRequest = async (memberAddress: string) => { }) .filter((dao) => !DAOS_TO_EXCLUDE.includes(dao.tokenAddress)) .map((dao) => ({ - ...dao, name: dao.name || '', - collectionAddress: dao.tokenAddress, + tokenAddress: dao.tokenAddress, auctionAddress: dao?.auctionAddress || '', + proposals: dao.proposals, + currentAuction: dao.currentAuction, chainId: queries.chainId, })) ) diff --git a/apps/web/src/data/subgraph/sdk.generated.ts b/apps/web/src/data/subgraph/sdk.generated.ts index a18fe1bc..95e6d666 100644 --- a/apps/web/src/data/subgraph/sdk.generated.ts +++ b/apps/web/src/data/subgraph/sdk.generated.ts @@ -1855,6 +1855,13 @@ export type AuctionBidFragment = { bidder: any } +export type CurrentAuctionFragment = { + __typename?: 'Auction' + endTime: any + highestBid?: { __typename?: 'AuctionBid'; amount: any } | null + token: { __typename?: 'Token'; name: string; image: string; tokenId: any } +} + export type DaoFragment = { __typename?: 'DAO' name: string @@ -2085,7 +2092,7 @@ export type DashboardQuery = { __typename?: 'Auction' endTime: any highestBid?: { __typename?: 'AuctionBid'; amount: any } | null - token: { __typename?: 'Token'; name: string; image: string } + token: { __typename?: 'Token'; name: string; image: string; tokenId: any } } | null } }> @@ -2336,6 +2343,19 @@ export const AuctionBidFragmentDoc = gql` bidder } ` +export const CurrentAuctionFragmentDoc = gql` + fragment CurrentAuction on Auction { + endTime + highestBid { + amount + } + token { + name + image + tokenId + } + } +` export const DaoFragmentDoc = gql` fragment DAO on DAO { name @@ -2535,20 +2555,14 @@ export const DashboardDocument = gql` ...Proposal } currentAuction { - endTime - highestBid { - amount - } - token { - name - image - } + ...CurrentAuction } } } } ${DaoFragmentDoc} ${ProposalFragmentDoc} + ${CurrentAuctionFragmentDoc} ` export const ExploreDaosPageDocument = gql` query exploreDaosPage( diff --git a/apps/web/src/pages/dashboard.tsx b/apps/web/src/pages/dashboard.tsx index 89f63726..688d029b 100644 --- a/apps/web/src/pages/dashboard.tsx +++ b/apps/web/src/pages/dashboard.tsx @@ -3,10 +3,55 @@ import React from 'react' import useSWR from 'swr' import { useAccount } from 'wagmi' +import { + ProposalState, + getProposalState, +} from 'src/data/contract/requests/getProposalState' +import { + CurrentAuctionFragment, + DaoFragment, + ProposalFragment, +} from 'src/data/subgraph/sdk.generated' +import { CHAIN_ID } from 'src/typings' + +const ACTIVE_PROPOSAL_STATES = [ + ProposalState.Active, + ProposalState.Pending, + ProposalState.Queued, +] + +type DashboardDao = DaoFragment & { + chainId: CHAIN_ID + proposals: ProposalFragment[] + currentAuction: CurrentAuctionFragment +} + +const fetchDaoProposalState = async (dao: DashboardDao) => { + const proposals = await Promise.all( + dao.proposals.map(async (proposal) => { + const proposalState = await getProposalState( + dao.chainId, + proposal.dao.governorAddress, + proposal.proposalId + ) + return { ...proposal, proposalState } + }) + ) + return { + ...dao, + proposals: proposals.filter((proposal) => + ACTIVE_PROPOSAL_STATES.includes(proposal.proposalState) + ), + } +} + const fetchDashboardData = async (address: string) => { - const userDaos = await axios.get(`/api/dashboard/${address}`).then((x) => x.data) - console.log('userDaos', userDaos) - return userDaos + const userDaos = await axios + .get(`/api/dashboard/${address}`) + .then((x) => x.data) + + const resolved = await Promise.all(userDaos.map(fetchDaoProposalState)) + return resolved } const Dashboard = () => { @@ -17,7 +62,17 @@ const Dashboard = () => { address ? () => fetchDashboardData(address) : null ) - return
Dashboard
+ if (error) { + return
error
+ } + if (isValidating) { + return
loading
+ } + if (!data) { + return
no data
+ } + + return
{data?.map((dao) => dao.name)}
} export default Dashboard From 5df224a29e517b6ca864839e941fb4723e9c2ee1 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 21:16:00 -0700 Subject: [PATCH 06/48] display some data --- .../data/subgraph/requests/dashboardQuery.ts | 14 ---------- apps/web/src/pages/dashboard.tsx | 27 ++++++++++++++++++- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts index 3eb367b7..9efcb9e2 100644 --- a/apps/web/src/data/subgraph/requests/dashboardQuery.ts +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -2,26 +2,12 @@ import * as Sentry from '@sentry/nextjs' import { PUBLIC_DEFAULT_CHAINS } from 'src/constants/defaultChains' import { SDK } from 'src/data/subgraph/client' -import { CHAIN_ID } from 'src/typings' - -import { - CurrentAuctionFragment, - DaoFragment, - ProposalFragment, -} from '../sdk.generated' const DAOS_TO_EXCLUDE = [ '0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03', '0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b', ] -type DashboardDaos = DaoFragment & - { - chainId: CHAIN_ID - proposals: ProposalFragment[] - currentAuction: CurrentAuctionFragment - }[] - export const dashboardRequest = async (memberAddress: string) => { // let daos: MyDaosResponse = [] diff --git a/apps/web/src/pages/dashboard.tsx b/apps/web/src/pages/dashboard.tsx index 688d029b..1e9176b6 100644 --- a/apps/web/src/pages/dashboard.tsx +++ b/apps/web/src/pages/dashboard.tsx @@ -72,7 +72,32 @@ const Dashboard = () => { return
no data
} - return
{data?.map((dao) => dao.name)}
+ return ( +
+

Dashboard

+
+

DAOs

+
+ {data?.map((dao) => ( +
{dao.name}
+ ))} +
+
+
+

Proposals

+
+ {data?.map((dao) => ( + <> +

{dao.name}

+ {dao.proposals.map((proposal) => ( +
{proposal.title}
+ ))} + + ))} +
+
+
+ ) } export default Dashboard From 760f6a79eb46801a52706fbcf89530838148e3e4 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 7 Sep 2023 21:44:08 -0700 Subject: [PATCH 07/48] render instead of redirect --- .../data/subgraph/requests/dashboardQuery.ts | 2 - .../dashboard/Dashboard.tsx} | 10 +++-- apps/web/src/modules/dashboard/index.ts | 1 + apps/web/src/pages/index.tsx | 37 ++++++++----------- 4 files changed, 23 insertions(+), 27 deletions(-) rename apps/web/src/{pages/dashboard.tsx => modules/dashboard/Dashboard.tsx} (88%) create mode 100644 apps/web/src/modules/dashboard/index.ts diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts index 9efcb9e2..8e1e23a6 100644 --- a/apps/web/src/data/subgraph/requests/dashboardQuery.ts +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -9,8 +9,6 @@ const DAOS_TO_EXCLUDE = [ ] export const dashboardRequest = async (memberAddress: string) => { - // let daos: MyDaosResponse = [] - if (!memberAddress) throw new Error('No user address provided') try { diff --git a/apps/web/src/pages/dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx similarity index 88% rename from apps/web/src/pages/dashboard.tsx rename to apps/web/src/modules/dashboard/Dashboard.tsx index 1e9176b6..fd44109e 100644 --- a/apps/web/src/pages/dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -1,8 +1,10 @@ +import { Flex } from '@zoralabs/zord' import axios from 'axios' import React from 'react' import useSWR from 'swr' import { useAccount } from 'wagmi' +import { Meta } from 'src/components/Meta' import { ProposalState, getProposalState, @@ -59,7 +61,8 @@ const Dashboard = () => { const { data, error, isValidating } = useSWR( [`dashboard:${address}`], - address ? () => fetchDashboardData(address) : null + address ? () => fetchDashboardData(address) : null, + { revalidateOnFocus: false } ) if (error) { @@ -73,7 +76,8 @@ const Dashboard = () => { } return ( -
+ +

Dashboard

DAOs

@@ -96,7 +100,7 @@ const Dashboard = () => { ))}
- +
) } diff --git a/apps/web/src/modules/dashboard/index.ts b/apps/web/src/modules/dashboard/index.ts new file mode 100644 index 00000000..f3598477 --- /dev/null +++ b/apps/web/src/modules/dashboard/index.ts @@ -0,0 +1 @@ +export * from './Dashboard' diff --git a/apps/web/src/pages/index.tsx b/apps/web/src/pages/index.tsx index 7cbafdf7..4aea64d7 100644 --- a/apps/web/src/pages/index.tsx +++ b/apps/web/src/pages/index.tsx @@ -1,6 +1,5 @@ import { Stack } from '@zoralabs/zord' -import { useRouter } from 'next/router' -import React, { useEffect } from 'react' +import React from 'react' import { useAccount } from 'wagmi' import Everything from 'src/components/Home/Everything' @@ -13,33 +12,27 @@ import { Meta } from 'src/components/Meta' import { AuctionFragment } from 'src/data/subgraph/sdk.generated' import { getHomeLayout } from 'src/layouts/HomeLayout' import { DaoFeed } from 'src/modules/dao' +import Dashboard from 'src/modules/dashboard/Dashboard' import { NextPageWithLayout } from './_app' export type DaoProps = AuctionFragment['dao'] const HomePage: NextPageWithLayout = () => { - const router = useRouter() + // const router = useRouter() const { address } = useAccount() - // { - // onConnect({ address }) { - // const wasRedirected = sessionStorage.getItem('wasRedirected') - - // if (address && !wasRedirected) { - // sessionStorage.setItem('wasRedirected', 'true') - // router.push('/about') - // } - // }, - // } - - // useEffect helps load redirect a little faster on page load - useEffect(() => { - const wasRedirected = sessionStorage.getItem('wasRedirected') - if (address && !wasRedirected) { - sessionStorage.setItem('wasRedirected', 'true') - router.push('/about') - } - }, [address]) + + // useEffect(() => { + // const wasRedirected = sessionStorage.getItem('wasRedirected') + // if (address && !wasRedirected) { + // sessionStorage.setItem('wasRedirected', 'true') + // router.push('/about') + // } + // }, [address]) + + if (address) { + return + } return ( <> From 57980e189bfca9a6d6b94c2ba18c03b2c74eb30e Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 8 Sep 2023 12:11:04 -0700 Subject: [PATCH 08/48] page layout, dao/proposal lists --- .../subgraph/queries/dashboardQuery.graphql | 1 + .../data/subgraph/requests/dashboardQuery.ts | 1 + apps/web/src/data/subgraph/sdk.generated.ts | 2 + apps/web/src/modules/dashboard/Dashboard.tsx | 167 +++++++++++++++--- 4 files changed, 149 insertions(+), 22 deletions(-) diff --git a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql index 4879c78f..3cc5ab66 100644 --- a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql +++ b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql @@ -2,6 +2,7 @@ query dashboard($where: DAOTokenOwner_filter, $first: Int, $skip: Int) { daotokenOwners(where: $where, first: $first, skip: $skip) { dao { ...DAO + contractImage proposals( where: { executed_not: true, canceled_not: true, vetoed_not: true } first: 10 diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts index 8e1e23a6..24ecd654 100644 --- a/apps/web/src/data/subgraph/requests/dashboardQuery.ts +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -39,6 +39,7 @@ export const dashboardRequest = async (memberAddress: string) => { proposals: dao.proposals, currentAuction: dao.currentAuction, chainId: queries.chainId, + daoImage: dao.contractImage, })) ) .flat() diff --git a/apps/web/src/data/subgraph/sdk.generated.ts b/apps/web/src/data/subgraph/sdk.generated.ts index 95e6d666..4ea5ff14 100644 --- a/apps/web/src/data/subgraph/sdk.generated.ts +++ b/apps/web/src/data/subgraph/sdk.generated.ts @@ -2060,6 +2060,7 @@ export type DashboardQuery = { __typename?: 'DAOTokenOwner' dao: { __typename?: 'DAO' + contractImage: string name: string tokenAddress: any auctionAddress: any @@ -2545,6 +2546,7 @@ export const DashboardDocument = gql` daotokenOwners(where: $where, first: $first, skip: $skip) { dao { ...DAO + contractImage proposals( where: { executed_not: true, canceled_not: true, vetoed_not: true } first: 10 diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index fd44109e..937ca72f 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -1,9 +1,12 @@ -import { Flex } from '@zoralabs/zord' +import { Box, Button, Flex, Text } from '@zoralabs/zord' import axios from 'axios' +import { getFetchableUrl } from 'ipfs-service' +import Image from 'next/image' import React from 'react' import useSWR from 'swr' import { useAccount } from 'wagmi' +import { Avatar } from 'src/components/Avatar' import { Meta } from 'src/components/Meta' import { ProposalState, @@ -24,6 +27,7 @@ const ACTIVE_PROPOSAL_STATES = [ type DashboardDao = DaoFragment & { chainId: CHAIN_ID + daoImage: string proposals: ProposalFragment[] currentAuction: CurrentAuctionFragment } @@ -76,32 +80,151 @@ const Dashboard = () => { } return ( - + -

Dashboard

-
-

DAOs

-
+ + + Dashboard + + + + DAOs + {data?.map((dao) => ( -
{dao.name}
+ ))} -
-
-
-

Proposals

-
- {data?.map((dao) => ( - <> -

{dao.name}

- {dao.proposals.map((proposal) => ( -
{proposal.title}
- ))} - - ))} -
-
+ + + + Proposals + + {data + .filter((dao) => dao.proposals.length) + .map((dao) => ( + + ))} + + {/*
+ {data?.map((dao) => ( + <> +

{dao.name}

+ {dao.proposals.map((proposal) => ( +
{proposal.title}
+ ))} + + ))} +
*/} +
+
) } export default Dashboard + +const DaoAuctionCard = ({ daoImage, tokenAddress }: DashboardDao) => { + const daoImageSrc = React.useMemo(() => { + return daoImage ? getFetchableUrl(daoImage) : null + }, [daoImage]) + return ( + + {daoImageSrc ? ( + + + + ) : ( + + + + )} + + ) +} + +const DaoProposals = ({ daoImage, tokenAddress, name, proposals }: DashboardDao) => { + const daoImageSrc = React.useMemo(() => { + return daoImage ? getFetchableUrl(daoImage) : null + }, [daoImage]) + return ( + + + + {daoImageSrc ? ( + + + + ) : ( + + + + )} + + {name} + + + + + {proposals.map((proposal) => ( + + ))} + + ) +} + +const DaoProposalCard = ({ title, proposalNumber }: ProposalFragment) => { + return ( + + + + {proposalNumber} + + + {title} + + + + ) +} From d13e4cb8d4c09afacdfa7f5f3142face472f1e3c Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 8 Sep 2023 15:27:07 -0700 Subject: [PATCH 09/48] current bid and countdown displays --- apps/web/src/modules/dashboard/Dashboard.tsx | 131 ++++++++++++++++--- 1 file changed, 110 insertions(+), 21 deletions(-) diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 937ca72f..22c69e12 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -1,13 +1,17 @@ import { Box, Button, Flex, Text } from '@zoralabs/zord' import axios from 'axios' +import dayjs from 'dayjs' import { getFetchableUrl } from 'ipfs-service' import Image from 'next/image' -import React from 'react' +import React, { useState } from 'react' import useSWR from 'swr' +import { formatEther } from 'viem' import { useAccount } from 'wagmi' import { Avatar } from 'src/components/Avatar' +import { ContractButton } from 'src/components/ContractButton' import { Meta } from 'src/components/Meta' +import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' import { ProposalState, getProposalState, @@ -17,8 +21,11 @@ import { DaoFragment, ProposalFragment, } from 'src/data/subgraph/sdk.generated' +import { useCountdown, useIsMounted } from 'src/hooks' import { CHAIN_ID } from 'src/typings' +import { bidInput } from '../auction/components/Auction.css' + const ACTIVE_PROPOSAL_STATES = [ ProposalState.Active, ProposalState.Pending, @@ -127,10 +134,40 @@ const Dashboard = () => { export default Dashboard -const DaoAuctionCard = ({ daoImage, tokenAddress }: DashboardDao) => { - const daoImageSrc = React.useMemo(() => { - return daoImage ? getFetchableUrl(daoImage) : null - }, [daoImage]) +const DashCountdown = ({ + endTime, + onEnd, + isOver, +}: { + endTime: string | null + onEnd: () => void + isOver: boolean +}) => { + const { countdownString } = useCountdown(Number(endTime), onEnd) + const isMounted = useIsMounted() + const countdownText = !endTime || isOver ? 'N/A' : countdownString + if (!isMounted) return null + return ( + + {countdownText} + + ) +} + +const DaoAuctionCard = ({ currentAuction, chainId }: DashboardDao) => { + const { name: chainName, icon: chainIcon } = + PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} + const bidText = currentAuction.highestBid?.amount + ? formatEther(BigInt(currentAuction.highestBid.amount)) + : 'N/A' + const { endTime } = currentAuction + const [isEnded, setIsEnded] = useState(false) + + const isOver = !!endTime ? dayjs.unix(Date.now() / 1000) >= dayjs.unix(endTime) : true + const onEnd = () => { + setIsEnded(true) + } + return ( { cursor={'pointer'} py={{ '@initial': 'x2', '@768': 'x3' }} px={{ '@initial': 'x2', '@768': 'x6' }} + align={'center'} > - {daoImageSrc ? ( - - - - ) : ( - - + + + + + + {chainIcon && ( + + )} + + {chainName} + + + + {currentAuction.token.name} + + + + + Current Bid + + + {bidText} + + + + + Ends In + + + +
+ + - )} +
+ {}}>Bid
) } @@ -193,6 +281,7 @@ const DaoProposals = ({ daoImage, tokenAddress, name, proposals }: DashboardDao) {name}
+ From f4abe2f563f6bba16439da53612d3ad07abaaac5 Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 8 Sep 2023 17:04:36 -0700 Subject: [PATCH 10/48] set up auction card listeners --- apps/web/src/constants/swrKeys.ts | 1 + apps/web/src/modules/dashboard/Dashboard.tsx | 56 +++++++++++++------ .../src/modules/dashboard/dashboard.css.ts | 27 +++++++++ 3 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 apps/web/src/modules/dashboard/dashboard.css.ts diff --git a/apps/web/src/constants/swrKeys.ts b/apps/web/src/constants/swrKeys.ts index 16a25b66..23b1337d 100644 --- a/apps/web/src/constants/swrKeys.ts +++ b/apps/web/src/constants/swrKeys.ts @@ -19,6 +19,7 @@ const SWR_KEYS = { DAO_FEED: 'dao-feed', MEMBERS: 'members', TOKEN_IMAGE: 'token-image', + DASHBOARD: 'dashboard', DYNAMIC: { MY_DAOS(str: string) { return `my-daos-${str}` diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 22c69e12..1c06f207 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -4,14 +4,16 @@ import dayjs from 'dayjs' import { getFetchableUrl } from 'ipfs-service' import Image from 'next/image' import React, { useState } from 'react' -import useSWR from 'swr' +import useSWR, { mutate } from 'swr' import { formatEther } from 'viem' -import { useAccount } from 'wagmi' +import { useAccount, useContractEvent } from 'wagmi' import { Avatar } from 'src/components/Avatar' import { ContractButton } from 'src/components/ContractButton' import { Meta } from 'src/components/Meta' import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' +import SWR_KEYS from 'src/constants/swrKeys' +import { auctionAbi } from 'src/data/contract/abis' import { ProposalState, getProposalState, @@ -24,7 +26,7 @@ import { import { useCountdown, useIsMounted } from 'src/hooks' import { CHAIN_ID } from 'src/typings' -import { bidInput } from '../auction/components/Auction.css' +import { bidInput } from './dashboard.css' const ACTIVE_PROPOSAL_STATES = [ ProposalState.Active, @@ -71,7 +73,7 @@ const Dashboard = () => { const { address } = useAccount() const { data, error, isValidating } = useSWR( - [`dashboard:${address}`], + [`${SWR_KEYS.DASHBOARD}:${address}`], address ? () => fetchDashboardData(address) : null, { revalidateOnFocus: false } ) @@ -82,6 +84,9 @@ const Dashboard = () => { if (isValidating) { return
loading
} + if (!address) { + return
no address
+ } if (!data) { return
no data
} @@ -103,7 +108,7 @@ const Dashboard = () => { DAOs {data?.map((dao) => ( - + ))} @@ -115,17 +120,6 @@ const Dashboard = () => { .map((dao) => ( ))} - - {/*
- {data?.map((dao) => ( - <> -

{dao.name}

- {dao.proposals.map((proposal) => ( -
{proposal.title}
- ))} - - ))} -
*/}
@@ -154,7 +148,12 @@ const DashCountdown = ({ ) } -const DaoAuctionCard = ({ currentAuction, chainId }: DashboardDao) => { +const DaoAuctionCard = ({ + currentAuction, + chainId, + auctionAddress, + userAddress, +}: DashboardDao & { userAddress: string }) => { const { name: chainName, icon: chainIcon } = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} const bidText = currentAuction.highestBid?.amount @@ -168,6 +167,29 @@ const DaoAuctionCard = ({ currentAuction, chainId }: DashboardDao) => { setIsEnded(true) } + useContractEvent({ + address: auctionAddress, + abi: auctionAbi, + eventName: 'AuctionCreated', + chainId, + listener: async () => { + await mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`, userAddress], () => + fetchDashboardData(userAddress) + ) + }, + }) + useContractEvent({ + address: auctionAddress, + abi: auctionAbi, + eventName: 'AuctionBid', + chainId, + listener: async () => { + await mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`, userAddress], () => + fetchDashboardData(userAddress) + ) + }, + }) + return ( Date: Fri, 8 Sep 2023 17:47:08 -0700 Subject: [PATCH 11/48] update query --- .../src/data/subgraph/queries/dashboardQuery.graphql | 4 ++++ apps/web/src/data/subgraph/requests/dashboardQuery.ts | 1 + apps/web/src/data/subgraph/sdk.generated.ts | 9 +++++++++ apps/web/src/modules/dashboard/Dashboard.tsx | 10 ++++++++-- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql index 3cc5ab66..c7e98434 100644 --- a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql +++ b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql @@ -3,6 +3,10 @@ query dashboard($where: DAOTokenOwner_filter, $first: Int, $skip: Int) { dao { ...DAO contractImage + auctionConfig { + minimumBidIncrement + reservePrice + } proposals( where: { executed_not: true, canceled_not: true, vetoed_not: true } first: 10 diff --git a/apps/web/src/data/subgraph/requests/dashboardQuery.ts b/apps/web/src/data/subgraph/requests/dashboardQuery.ts index 24ecd654..9d973dc4 100644 --- a/apps/web/src/data/subgraph/requests/dashboardQuery.ts +++ b/apps/web/src/data/subgraph/requests/dashboardQuery.ts @@ -33,6 +33,7 @@ export const dashboardRequest = async (memberAddress: string) => { }) .filter((dao) => !DAOS_TO_EXCLUDE.includes(dao.tokenAddress)) .map((dao) => ({ + ...dao, name: dao.name || '', tokenAddress: dao.tokenAddress, auctionAddress: dao?.auctionAddress || '', diff --git a/apps/web/src/data/subgraph/sdk.generated.ts b/apps/web/src/data/subgraph/sdk.generated.ts index 4ea5ff14..80ee85bc 100644 --- a/apps/web/src/data/subgraph/sdk.generated.ts +++ b/apps/web/src/data/subgraph/sdk.generated.ts @@ -2064,6 +2064,11 @@ export type DashboardQuery = { name: string tokenAddress: any auctionAddress: any + auctionConfig: { + __typename?: 'AuctionConfig' + minimumBidIncrement: any + reservePrice: any + } proposals: Array<{ __typename?: 'Proposal' abstainVotes: number @@ -2547,6 +2552,10 @@ export const DashboardDocument = gql` dao { ...DAO contractImage + auctionConfig { + minimumBidIncrement + reservePrice + } proposals( where: { executed_not: true, canceled_not: true, vetoed_not: true } first: 10 diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 1c06f207..389f7a35 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -37,6 +37,10 @@ const ACTIVE_PROPOSAL_STATES = [ type DashboardDao = DaoFragment & { chainId: CHAIN_ID daoImage: string + auctionConfig: { + minimumBidIncrement: string + reservePrice: string + } proposals: ProposalFragment[] currentAuction: CurrentAuctionFragment } @@ -77,7 +81,7 @@ const Dashboard = () => { address ? () => fetchDashboardData(address) : null, { revalidateOnFocus: false } ) - + console.log('data', data) if (error) { return
error
} @@ -269,7 +273,9 @@ const DaoAuctionCard = ({ - {}}>Bid + {}} borderRadius={'curved'}> + Bid +
) } From 4e68d6afd2388d78d4a7dca33408f1ae7cc2f766 Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 8 Sep 2023 18:26:00 -0700 Subject: [PATCH 12/48] min bid button --- apps/web/src/modules/dashboard/Dashboard.tsx | 62 ++++++++++++++++--- .../src/modules/dashboard/dashboard.css.ts | 2 +- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 389f7a35..5b72125a 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -6,7 +6,7 @@ import Image from 'next/image' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' import { formatEther } from 'viem' -import { useAccount, useContractEvent } from 'wagmi' +import { useAccount, useBalance, useContractEvent } from 'wagmi' import { Avatar } from 'src/components/Avatar' import { ContractButton } from 'src/components/ContractButton' @@ -24,8 +24,10 @@ import { ProposalFragment, } from 'src/data/subgraph/sdk.generated' import { useCountdown, useIsMounted } from 'src/hooks' -import { CHAIN_ID } from 'src/typings' +import { AddressType, CHAIN_ID } from 'src/typings' +import { formatCryptoVal } from 'src/utils/numbers' +import { useMinBidIncrement } from '../auction' import { bidInput } from './dashboard.css' const ACTIVE_PROPOSAL_STATES = [ @@ -81,7 +83,7 @@ const Dashboard = () => { address ? () => fetchDashboardData(address) : null, { revalidateOnFocus: false } ) - console.log('data', data) + if (error) { return
error
} @@ -157,15 +159,28 @@ const DaoAuctionCard = ({ chainId, auctionAddress, userAddress, -}: DashboardDao & { userAddress: string }) => { + auctionConfig, +}: DashboardDao & { userAddress: AddressType }) => { const { name: chainName, icon: chainIcon } = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} + + const { endTime, highestBid } = currentAuction + const { minimumBidIncrement, reservePrice } = auctionConfig + const [bidAmount, setBidAmount] = useState('') + const [isEnded, setIsEnded] = useState(false) + + const { data: balance } = useBalance({ address: userAddress, chainId }) + const bidText = currentAuction.highestBid?.amount ? formatEther(BigInt(currentAuction.highestBid.amount)) : 'N/A' - const { endTime } = currentAuction - const [isEnded, setIsEnded] = useState(false) + const { minBidAmount } = useMinBidIncrement({ + highestBid: highestBid?.amount ? BigInt(highestBid?.amount) : undefined, + reservePrice: BigInt(reservePrice), + minBidIncrement: BigInt(minimumBidIncrement), + }) + const formattedMinBid = formatCryptoVal(minBidAmount) const isOver = !!endTime ? dayjs.unix(Date.now() / 1000) >= dayjs.unix(endTime) : true const onEnd = () => { setIsEnded(true) @@ -270,7 +285,40 @@ const DaoAuctionCard = ({
- + setBidAmount(e.target.value)} + /> + + +
{}} borderRadius={'curved'}> diff --git a/apps/web/src/modules/dashboard/dashboard.css.ts b/apps/web/src/modules/dashboard/dashboard.css.ts index 7544783e..a954934d 100644 --- a/apps/web/src/modules/dashboard/dashboard.css.ts +++ b/apps/web/src/modules/dashboard/dashboard.css.ts @@ -21,7 +21,7 @@ export const bidInput = style([ }, atoms({ backgroundColor: 'background2', - fontSize: 16, + fontSize: 14, lineHeight: 24, }), ]) From cc8f9ec0bd4628b97f0ff480d7e213a220c86c2e Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 12:57:31 -0700 Subject: [PATCH 13/48] settle auction --- .../subgraph/fragments/CurrentAuction.graphql | 1 + apps/web/src/data/subgraph/sdk.generated.ts | 5 +- .../components/CurrentAuction/Settle.tsx | 16 +- apps/web/src/modules/dashboard/Dashboard.tsx | 172 +++++++++++------- 4 files changed, 125 insertions(+), 69 deletions(-) diff --git a/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql b/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql index 72aebfa4..8ad972bf 100644 --- a/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql +++ b/apps/web/src/data/subgraph/fragments/CurrentAuction.graphql @@ -2,6 +2,7 @@ fragment CurrentAuction on Auction { endTime highestBid { amount + bidder } token { name diff --git a/apps/web/src/data/subgraph/sdk.generated.ts b/apps/web/src/data/subgraph/sdk.generated.ts index 80ee85bc..388320ff 100644 --- a/apps/web/src/data/subgraph/sdk.generated.ts +++ b/apps/web/src/data/subgraph/sdk.generated.ts @@ -1858,7 +1858,7 @@ export type AuctionBidFragment = { export type CurrentAuctionFragment = { __typename?: 'Auction' endTime: any - highestBid?: { __typename?: 'AuctionBid'; amount: any } | null + highestBid?: { __typename?: 'AuctionBid'; amount: any; bidder: any } | null token: { __typename?: 'Token'; name: string; image: string; tokenId: any } } @@ -2097,7 +2097,7 @@ export type DashboardQuery = { currentAuction?: { __typename?: 'Auction' endTime: any - highestBid?: { __typename?: 'AuctionBid'; amount: any } | null + highestBid?: { __typename?: 'AuctionBid'; amount: any; bidder: any } | null token: { __typename?: 'Token'; name: string; image: string; tokenId: any } } | null } @@ -2354,6 +2354,7 @@ export const CurrentAuctionFragmentDoc = gql` endTime highestBid { amount + bidder } token { name diff --git a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx index 66ae3dce..093aeb5a 100644 --- a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx +++ b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx @@ -12,6 +12,7 @@ import { ContractButton } from 'src/components/ContractButton' import { auctionAbi } from 'src/data/contract/abis' import { useDaoStore } from 'src/modules/dao' import { useChainStore } from 'src/stores/useChainStore' +import { AddressType } from 'src/typings' import { auctionActionButtonVariants } from '../Auction.css' @@ -19,26 +20,29 @@ interface SettleProps { isEnding: boolean collectionAddress?: string owner?: string | undefined + externalAuctionAddress?: string } -export const Settle = ({ isEnding, owner }: SettleProps) => { +export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) => { const chain = useChainStore((x) => x.chain) - const addresses = useDaoStore((state) => state.addresses) + const addresses = useDaoStore?.((state) => state.addresses) || {} const { address } = useAccount() const isWinner = owner != undefined && address == owner + const auctionAddress = (externalAuctionAddress as AddressType) || addresses?.auction + const { data: paused } = useContractRead({ - enabled: !!addresses?.auction, - address: addresses?.auction, + enabled: !!auctionAddress, + address: auctionAddress, chainId: chain.id, abi: auctionAbi, functionName: 'paused', }) const { config, error } = usePrepareContractWrite({ - enabled: !!addresses?.auction, - address: addresses?.auction, + enabled: !!auctionAddress, + address: auctionAddress, abi: auctionAbi, functionName: paused ? 'settleAuction' : 'settleCurrentAndCreateNewAuction', }) diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 5b72125a..70d9ea90 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -6,7 +6,11 @@ import Image from 'next/image' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' import { formatEther } from 'viem' -import { useAccount, useBalance, useContractEvent } from 'wagmi' +import { + useAccount, + useBalance, + useContractEvent, +} from 'wagmi' import { Avatar } from 'src/components/Avatar' import { ContractButton } from 'src/components/ContractButton' @@ -23,11 +27,12 @@ import { DaoFragment, ProposalFragment, } from 'src/data/subgraph/sdk.generated' -import { useCountdown, useIsMounted } from 'src/hooks' +import { useCountdown, useIsMounted, useTimeout } from 'src/hooks' import { AddressType, CHAIN_ID } from 'src/typings' import { formatCryptoVal } from 'src/utils/numbers' import { useMinBidIncrement } from '../auction' +import { Settle } from '../auction/components/CurrentAuction/Settle' import { bidInput } from './dashboard.css' const ACTIVE_PROPOSAL_STATES = [ @@ -154,33 +159,19 @@ const DashCountdown = ({ ) } -const DaoAuctionCard = ({ - currentAuction, - chainId, - auctionAddress, - userAddress, - auctionConfig, -}: DashboardDao & { userAddress: AddressType }) => { +const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { + const { currentAuction, chainId, auctionAddress, userAddress, auctionConfig } = props const { name: chainName, icon: chainIcon } = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} - const { endTime, highestBid } = currentAuction - const { minimumBidIncrement, reservePrice } = auctionConfig - const [bidAmount, setBidAmount] = useState('') - const [isEnded, setIsEnded] = useState(false) + const { endTime } = currentAuction - const { data: balance } = useBalance({ address: userAddress, chainId }) + const [isEnded, setIsEnded] = useState(false) const bidText = currentAuction.highestBid?.amount ? formatEther(BigInt(currentAuction.highestBid.amount)) : 'N/A' - const { minBidAmount } = useMinBidIncrement({ - highestBid: highestBid?.amount ? BigInt(highestBid?.amount) : undefined, - reservePrice: BigInt(reservePrice), - minBidIncrement: BigInt(minimumBidIncrement), - }) - const formattedMinBid = formatCryptoVal(minBidAmount) const isOver = !!endTime ? dayjs.unix(Date.now() / 1000) >= dayjs.unix(endTime) : true const onEnd = () => { setIsEnded(true) @@ -283,47 +274,7 @@ const DaoAuctionCard = ({ -
- - setBidAmount(e.target.value)} - /> - - - - -
- {}} borderRadius={'curved'}> - Bid - + ) } @@ -393,3 +344,102 @@ const DaoProposalCard = ({ title, proposalNumber }: ProposalFragment) => { ) } + +const BidActionButton = ({ + userAddress, + chainId, + auctionConfig, + currentAuction, + isEnded, + auctionAddress, + isOver, +}: DashboardDao & { userAddress: AddressType; isOver: boolean; isEnded: boolean }) => { + const { data: balance } = useBalance({ address: userAddress, chainId }) + const { minimumBidIncrement, reservePrice } = auctionConfig + const { highestBid } = currentAuction + const { minBidAmount } = useMinBidIncrement({ + highestBid: highestBid?.amount ? BigInt(highestBid?.amount) : undefined, + reservePrice: BigInt(reservePrice), + minBidIncrement: BigInt(minimumBidIncrement), + }) + // const { data: paused } = useContractRead({ + // enabled: !!auctionAddress, + // address: auctionAddress, + // chainId, + // abi: auctionAbi, + // functionName: 'paused', + // }) + // const { config, error } = usePrepareContractWrite({ + // enabled: !!auctionAddress, + // address: auctionAddress, + // abi: auctionAbi, + // functionName: paused ? 'settleAuction' : 'settleCurrentAndCreateNewAuction', + // }) + // const {writeAsync, status} = useContractWrite(config) + const [bidAmount, setBidAmount] = useState('') + const [isEnding, setIsEnding] = useState(false) + const formattedMinBid = formatCryptoVal(minBidAmount) + + const isEndingTimeout = isEnded ? 4000 : null + useTimeout(() => { + setIsEnding(false) + }, isEndingTimeout) + + if (isEnded || isOver) { + return ( + + + + ) + } + + return ( + <> +
+ + setBidAmount(e.target.value)} + /> + + + + +
+ {}} borderRadius={'curved'}> + Bid + + + ) +} From f49689e260ba3ac7561a0c6213c77899bec48290 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 14:16:59 -0700 Subject: [PATCH 14/48] handle auction refresh after bid/settle --- .../components/CurrentAuction/Settle.tsx | 4 +- apps/web/src/modules/dashboard/Dashboard.tsx | 72 +++++++++++++++---- .../api/dao/[network]/[token]/[tokenId].ts | 3 +- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx index 093aeb5a..2217ca01 100644 --- a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx +++ b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx @@ -20,7 +20,7 @@ interface SettleProps { isEnding: boolean collectionAddress?: string owner?: string | undefined - externalAuctionAddress?: string + externalAuctionAddress?: AddressType } export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) => { @@ -30,7 +30,7 @@ export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) const { address } = useAccount() const isWinner = owner != undefined && address == owner - const auctionAddress = (externalAuctionAddress as AddressType) || addresses?.auction + const auctionAddress = externalAuctionAddress || addresses?.auction const { data: paused } = useContractRead({ enabled: !!auctionAddress, diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 70d9ea90..8d04afcc 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -11,6 +11,7 @@ import { useBalance, useContractEvent, } from 'wagmi' +import { readContract } from 'wagmi/actions' import { Avatar } from 'src/components/Avatar' import { ContractButton } from 'src/components/ContractButton' @@ -29,6 +30,7 @@ import { } from 'src/data/subgraph/sdk.generated' import { useCountdown, useIsMounted, useTimeout } from 'src/hooks' import { AddressType, CHAIN_ID } from 'src/typings' +import { unpackOptionalArray } from 'src/utils/helpers' import { formatCryptoVal } from 'src/utils/numbers' import { useMinBidIncrement } from '../auction' @@ -77,6 +79,7 @@ const fetchDashboardData = async (address: string) => { .then((x) => x.data) const resolved = await Promise.all(userDaos.map(fetchDaoProposalState)) + console.log('resolved', resolved) return resolved } @@ -88,7 +91,7 @@ const Dashboard = () => { address ? () => fetchDashboardData(address) : null, { revalidateOnFocus: false } ) - + console.log('data', data) if (error) { return
error
} @@ -160,10 +163,45 @@ const DashCountdown = ({ } const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { - const { currentAuction, chainId, auctionAddress, userAddress, auctionConfig } = props + const { + currentAuction, + chainId, + auctionAddress, + userAddress, + auctionConfig, + tokenAddress, + } = props const { name: chainName, icon: chainIcon } = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} + const { data: auction } = useSWR( + [SWR_KEYS.AUCTION, chainId, auctionAddress], + (_, chainId, auctionAddress) => + readContract({ + abi: auctionAbi, + address: auctionAddress as AddressType, + functionName: 'auction', + chainId, + }), + { revalidateOnFocus: true } + ) + + const [liveTokenId, liveHighestBid, liveHighestBidder, _, liveEndTime, liveSettled] = + unpackOptionalArray(auction, 6) + + // const { data: token } = useSWR( + // [ + // `${SWR_KEYS.TOKEN}:${tokenAddress}:${liveTokenId}`, + // chainId, + // tokenAddress, + // liveTokenId, + // ], + // (_, id) => + // axios + // .get(`/api/dao/${chainId}/${tokenAddress}/${liveTokenId}`) + // .then((x) => x.data) + // ) + const { endTime } = currentAuction const [isEnded, setIsEnded] = useState(false) @@ -177,15 +215,22 @@ const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { setIsEnded(true) } + const isTokenActiveAuction = + !liveSettled && + !!liveTokenId && + liveTokenId.toString() == currentAuction.token.tokenId + useContractEvent({ address: auctionAddress, abi: auctionAbi, eventName: 'AuctionCreated', chainId, listener: async () => { - await mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`, userAddress], () => - fetchDashboardData(userAddress) - ) + setTimeout(() => { + mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`], () => + fetchDashboardData(userAddress) + ) + }, 3000) }, }) useContractEvent({ @@ -194,9 +239,11 @@ const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { eventName: 'AuctionBid', chainId, listener: async () => { - await mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`, userAddress], () => - fetchDashboardData(userAddress) - ) + setTimeout(() => { + mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`], () => + fetchDashboardData(userAddress) + ) + }, 3000) }, }) @@ -362,13 +409,7 @@ const BidActionButton = ({ reservePrice: BigInt(reservePrice), minBidIncrement: BigInt(minimumBidIncrement), }) - // const { data: paused } = useContractRead({ - // enabled: !!auctionAddress, - // address: auctionAddress, - // chainId, - // abi: auctionAbi, - // functionName: 'paused', - // }) + // const { config, error } = usePrepareContractWrite({ // enabled: !!auctionAddress, // address: auctionAddress, @@ -382,6 +423,7 @@ const BidActionButton = ({ const isEndingTimeout = isEnded ? 4000 : null useTimeout(() => { + console.log('timeout fired') setIsEnding(false) }, isEndingTimeout) diff --git a/apps/web/src/pages/api/dao/[network]/[token]/[tokenId].ts b/apps/web/src/pages/api/dao/[network]/[token]/[tokenId].ts index 67199db8..9e0327ad 100644 --- a/apps/web/src/pages/api/dao/[network]/[token]/[tokenId].ts +++ b/apps/web/src/pages/api/dao/[network]/[token]/[tokenId].ts @@ -7,8 +7,9 @@ import { AddressType } from 'src/typings' const handler = async (req: NextApiRequest, res: NextApiResponse) => { const { network, token, tokenId } = req.query + console.log('network', network) const chain = PUBLIC_DEFAULT_CHAINS.find((x) => x.slug == network) - + console.log('chain', chain) if (!chain) { return res.status(404).end() } From e64db01038c4e7d331058b3950ba56a46ddc07ff Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 14:41:55 -0700 Subject: [PATCH 15/48] fix janky mutate refresh, fix poor state update --- apps/web/src/modules/dashboard/Dashboard.tsx | 93 +++++++++++--------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 8d04afcc..27edf769 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -6,12 +6,7 @@ import Image from 'next/image' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' import { formatEther } from 'viem' -import { - useAccount, - useBalance, - useContractEvent, -} from 'wagmi' -import { readContract } from 'wagmi/actions' +import { useAccount, useBalance, useContractEvent } from 'wagmi' import { Avatar } from 'src/components/Avatar' import { ContractButton } from 'src/components/ContractButton' @@ -28,9 +23,8 @@ import { DaoFragment, ProposalFragment, } from 'src/data/subgraph/sdk.generated' -import { useCountdown, useIsMounted, useTimeout } from 'src/hooks' +import { useCountdown, useIsMounted } from 'src/hooks' import { AddressType, CHAIN_ID } from 'src/typings' -import { unpackOptionalArray } from 'src/utils/helpers' import { formatCryptoVal } from 'src/utils/numbers' import { useMinBidIncrement } from '../auction' @@ -91,11 +85,13 @@ const Dashboard = () => { address ? () => fetchDashboardData(address) : null, { revalidateOnFocus: false } ) - console.log('data', data) + + const [mutating, setMutating] = useState(false) + if (error) { return
error
} - if (isValidating) { + if (isValidating && !mutating) { return
loading
} if (!address) { @@ -105,6 +101,12 @@ const Dashboard = () => { return
no data
} + const handleMutate = async () => { + setMutating(true) + await mutate([`${SWR_KEYS.DASHBOARD}:${address}`], () => fetchDashboardData(address)) + setMutating(false) + } + return ( { DAOs {data?.map((dao) => ( - + ))} @@ -132,7 +139,7 @@ const Dashboard = () => { {data .filter((dao) => dao.proposals.length) .map((dao) => ( - + ))} @@ -162,32 +169,35 @@ const DashCountdown = ({ ) } -const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { +const DaoAuctionCard = ( + props: DashboardDao & { userAddress: AddressType; handleMutate: () => void } +) => { const { currentAuction, chainId, auctionAddress, userAddress, auctionConfig, + handleMutate, tokenAddress, } = props const { name: chainName, icon: chainIcon } = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} - const { data: auction } = useSWR( - [SWR_KEYS.AUCTION, chainId, auctionAddress], - (_, chainId, auctionAddress) => - readContract({ - abi: auctionAbi, - address: auctionAddress as AddressType, - functionName: 'auction', - chainId, - }), - { revalidateOnFocus: true } - ) + // const { data: auction } = useSWR( + // [SWR_KEYS.AUCTION, chainId, auctionAddress], + // (_, chainId, auctionAddress) => + // readContract({ + // abi: auctionAbi, + // address: auctionAddress as AddressType, + // functionName: 'auction', + // chainId, + // }), + // { revalidateOnFocus: true } + // ) - const [liveTokenId, liveHighestBid, liveHighestBidder, _, liveEndTime, liveSettled] = - unpackOptionalArray(auction, 6) + // const [liveTokenId, liveHighestBid, liveHighestBidder, _, liveEndTime, liveSettled] = + // unpackOptionalArray(auction, 6) // const { data: token } = useSWR( // [ @@ -215,10 +225,10 @@ const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { setIsEnded(true) } - const isTokenActiveAuction = - !liveSettled && - !!liveTokenId && - liveTokenId.toString() == currentAuction.token.tokenId + // const isTokenActiveAuction = + // !liveSettled && + // !!liveTokenId && + // liveTokenId.toString() == currentAuction.token.tokenId useContractEvent({ address: auctionAddress, @@ -226,10 +236,9 @@ const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { eventName: 'AuctionCreated', chainId, listener: async () => { + console.log('AuctionCreated') setTimeout(() => { - mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`], () => - fetchDashboardData(userAddress) - ) + handleMutate() }, 3000) }, }) @@ -240,9 +249,7 @@ const DaoAuctionCard = (props: DashboardDao & { userAddress: AddressType }) => { chainId, listener: async () => { setTimeout(() => { - mutate([`${SWR_KEYS.DASHBOARD}:${userAddress}`], () => - fetchDashboardData(userAddress) - ) + handleMutate() }, 3000) }, }) @@ -361,7 +368,7 @@ const DaoProposals = ({ daoImage, tokenAddress, name, proposals }: DashboardDao) {proposals.map((proposal) => ( - + ))} ) @@ -418,20 +425,20 @@ const BidActionButton = ({ // }) // const {writeAsync, status} = useContractWrite(config) const [bidAmount, setBidAmount] = useState('') - const [isEnding, setIsEnding] = useState(false) + // const [isEnding, setIsEnding] = useState(false) const formattedMinBid = formatCryptoVal(minBidAmount) const isEndingTimeout = isEnded ? 4000 : null - useTimeout(() => { - console.log('timeout fired') - setIsEnding(false) - }, isEndingTimeout) + // useTimeout(() => { + // console.log('timeout fired') + // setIsEnding(false) + // }, isEndingTimeout) if (isEnded || isOver) { return ( From 71b2d492f7bdf37c39ecc6a2bbd1eba9d05fab07 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 15:28:20 -0700 Subject: [PATCH 16/48] add bid TX write, add char limit to placeholder --- .../components/CurrentAuction/Settle.tsx | 4 + apps/web/src/modules/dashboard/Dashboard.tsx | 81 +++++++++++++------ 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx index 2217ca01..0ec26842 100644 --- a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx +++ b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx @@ -21,6 +21,10 @@ interface SettleProps { collectionAddress?: string owner?: string | undefined externalAuctionAddress?: AddressType + customStyles?: { + settle: string + settling: string + } } export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) => { diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 27edf769..7f61b9f9 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -5,8 +5,9 @@ import { getFetchableUrl } from 'ipfs-service' import Image from 'next/image' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' -import { formatEther } from 'viem' -import { useAccount, useBalance, useContractEvent } from 'wagmi' +import { Address, formatEther, parseEther } from 'viem' +import { useAccount, useBalance, useContractEvent, useNetwork } from 'wagmi' +import { prepareWriteContract, waitForTransaction, writeContract } from 'wagmi/actions' import { Avatar } from 'src/components/Avatar' import { ContractButton } from 'src/components/ContractButton' @@ -25,12 +26,18 @@ import { } from 'src/data/subgraph/sdk.generated' import { useCountdown, useIsMounted } from 'src/hooks' import { AddressType, CHAIN_ID } from 'src/typings' -import { formatCryptoVal } from 'src/utils/numbers' import { useMinBidIncrement } from '../auction' import { Settle } from '../auction/components/CurrentAuction/Settle' import { bidInput } from './dashboard.css' +function maxChar(str: string, maxLength: number) { + if (str.length <= maxLength) { + return str + } + return str.slice(0, maxLength) + '...' +} + const ACTIVE_PROPOSAL_STATES = [ ProposalState.Active, ProposalState.Pending, @@ -73,7 +80,6 @@ const fetchDashboardData = async (address: string) => { .then((x) => x.data) const resolved = await Promise.all(userDaos.map(fetchDaoProposalState)) - console.log('resolved', resolved) return resolved } @@ -411,28 +417,44 @@ const BidActionButton = ({ const { data: balance } = useBalance({ address: userAddress, chainId }) const { minimumBidIncrement, reservePrice } = auctionConfig const { highestBid } = currentAuction + const { chain: wagmiChain } = useNetwork() const { minBidAmount } = useMinBidIncrement({ highestBid: highestBid?.amount ? BigInt(highestBid?.amount) : undefined, reservePrice: BigInt(reservePrice), minBidIncrement: BigInt(minimumBidIncrement), }) - // const { config, error } = usePrepareContractWrite({ - // enabled: !!auctionAddress, - // address: auctionAddress, - // abi: auctionAbi, - // functionName: paused ? 'settleAuction' : 'settleCurrentAndCreateNewAuction', - // }) - // const {writeAsync, status} = useContractWrite(config) const [bidAmount, setBidAmount] = useState('') - // const [isEnding, setIsEnding] = useState(false) - const formattedMinBid = formatCryptoVal(minBidAmount) - - const isEndingTimeout = isEnded ? 4000 : null - // useTimeout(() => { - // console.log('timeout fired') - // setIsEnding(false) - // }, isEndingTimeout) + const [isLoading, setIsLoading] = useState(false) + + const isMinBid = Number(bidAmount) >= minBidAmount + + const isValidBid = bidAmount && isMinBid + + const isValidChain = wagmiChain?.id === chainId + + const handleCreateBid = async () => { + if (!isMinBid || !bidAmount || isLoading) return + + try { + setIsLoading(true) + + const config = await prepareWriteContract({ + abi: auctionAbi, + address: auctionAddress as Address, + functionName: 'createBid', + args: [BigInt(currentAuction.token.tokenId)], + value: parseEther(bidAmount.toString()), + }) + const tx = await writeContract(config) + if (tx?.hash) await waitForTransaction({ hash: tx.hash }) + setBidAmount('') + } catch (error) { + console.error(error) + } finally { + setIsLoading(false) + } + } if (isEnded || isOver) { return ( @@ -446,15 +468,21 @@ const BidActionButton = ({ ) } + // const handleCreateBid = async () => { + + // if(!isMinBid) + + // } + return ( <>
setBidAmount(e.target.value)} @@ -478,15 +506,20 @@ const BidActionButton = ({ paddingLeft: 0, paddingRight: 0, }} - onClick={() => setBidAmount(formattedMinBid)} - disabled={bidAmount >= formattedMinBid} + onClick={() => setBidAmount(minBidAmount.toString())} + disabled={Number(bidAmount) >= minBidAmount} > Min
- {}} borderRadius={'curved'}> + handleCreateBid()} + > Bid From 31e1a1beb0a4e9b7b7418c804b604bf5e878ced6 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 15:36:03 -0700 Subject: [PATCH 17/48] fix dashboard link --- apps/web/src/layouts/DefaultLayout/Nav.tsx | 2 +- .../web/src/layouts/DefaultLayout/NavMenu.tsx | 2 +- apps/web/src/modules/dashboard/Dashboard.tsx | 49 +------------------ 3 files changed, 3 insertions(+), 50 deletions(-) diff --git a/apps/web/src/layouts/DefaultLayout/Nav.tsx b/apps/web/src/layouts/DefaultLayout/Nav.tsx index 4c16430d..79953255 100644 --- a/apps/web/src/layouts/DefaultLayout/Nav.tsx +++ b/apps/web/src/layouts/DefaultLayout/Nav.tsx @@ -53,7 +53,7 @@ export const Nav = () => { - + diff --git a/apps/web/src/layouts/DefaultLayout/NavMenu.tsx b/apps/web/src/layouts/DefaultLayout/NavMenu.tsx index 0c2b8841..ac373a39 100644 --- a/apps/web/src/layouts/DefaultLayout/NavMenu.tsx +++ b/apps/web/src/layouts/DefaultLayout/NavMenu.tsx @@ -376,7 +376,7 @@ export const NavMenu = () => { - + Dashboard diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 7f61b9f9..16a7d15d 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -178,46 +178,10 @@ const DashCountdown = ({ const DaoAuctionCard = ( props: DashboardDao & { userAddress: AddressType; handleMutate: () => void } ) => { - const { - currentAuction, - chainId, - auctionAddress, - userAddress, - auctionConfig, - handleMutate, - tokenAddress, - } = props + const { currentAuction, chainId, auctionAddress, handleMutate } = props const { name: chainName, icon: chainIcon } = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} - // const { data: auction } = useSWR( - // [SWR_KEYS.AUCTION, chainId, auctionAddress], - // (_, chainId, auctionAddress) => - // readContract({ - // abi: auctionAbi, - // address: auctionAddress as AddressType, - // functionName: 'auction', - // chainId, - // }), - // { revalidateOnFocus: true } - // ) - - // const [liveTokenId, liveHighestBid, liveHighestBidder, _, liveEndTime, liveSettled] = - // unpackOptionalArray(auction, 6) - - // const { data: token } = useSWR( - // [ - // `${SWR_KEYS.TOKEN}:${tokenAddress}:${liveTokenId}`, - // chainId, - // tokenAddress, - // liveTokenId, - // ], - // (_, id) => - // axios - // .get(`/api/dao/${chainId}/${tokenAddress}/${liveTokenId}`) - // .then((x) => x.data) - // ) - const { endTime } = currentAuction const [isEnded, setIsEnded] = useState(false) @@ -231,11 +195,6 @@ const DaoAuctionCard = ( setIsEnded(true) } - // const isTokenActiveAuction = - // !liveSettled && - // !!liveTokenId && - // liveTokenId.toString() == currentAuction.token.tokenId - useContractEvent({ address: auctionAddress, abi: auctionAbi, @@ -468,12 +427,6 @@ const BidActionButton = ({ ) } - // const handleCreateBid = async () => { - - // if(!isMinBid) - - // } - return ( <>
From 955b05ab2fd9067bfe8cffe9d92b7380f8d658f6 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 16:18:04 -0700 Subject: [PATCH 18/48] big refactor --- .../src/modules/dashboard/BidActionButton.tsx | 134 ++++++ .../src/modules/dashboard/DaoAuctionCard.tsx | 166 +++++++ .../src/modules/dashboard/DaoProposalCard.tsx | 28 ++ .../src/modules/dashboard/DaoProposals.tsx | 55 +++ apps/web/src/modules/dashboard/Dashboard.tsx | 404 +----------------- .../src/modules/dashboard/DashboardLayout.tsx | 40 ++ apps/web/src/utils/helpers.ts | 7 + 7 files changed, 450 insertions(+), 384 deletions(-) create mode 100644 apps/web/src/modules/dashboard/BidActionButton.tsx create mode 100644 apps/web/src/modules/dashboard/DaoAuctionCard.tsx create mode 100644 apps/web/src/modules/dashboard/DaoProposalCard.tsx create mode 100644 apps/web/src/modules/dashboard/DaoProposals.tsx create mode 100644 apps/web/src/modules/dashboard/DashboardLayout.tsx diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx new file mode 100644 index 00000000..51389e83 --- /dev/null +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -0,0 +1,134 @@ +import { Box, Button, Flex } from '@zoralabs/zord' +import React, { useState } from 'react' +import { Address, parseEther } from 'viem' +import { useBalance, useNetwork } from 'wagmi' +import { prepareWriteContract, waitForTransaction, writeContract } from 'wagmi/actions' + +import { ContractButton } from 'src/components/ContractButton' +import { auctionAbi } from 'src/data/contract/abis' + + + + +import { AddressType } from 'src/typings' +import { maxChar } from 'src/utils/helpers' + +import { useMinBidIncrement } from '../auction' +import { Settle } from '../auction/components/CurrentAuction/Settle' +import { DashboardDao } from './Dashboard' +import { bidInput } from './dashboard.css' + +export const BidActionButton = ({ + userAddress, + chainId, + auctionConfig, + currentAuction, + isEnded, + auctionAddress, + isOver, +}: DashboardDao & { userAddress: AddressType; isOver: boolean; isEnded: boolean }) => { + const { data: balance } = useBalance({ address: userAddress, chainId }) + const { minimumBidIncrement, reservePrice } = auctionConfig + const { highestBid } = currentAuction + const { chain: wagmiChain } = useNetwork() + const { minBidAmount } = useMinBidIncrement({ + highestBid: highestBid?.amount ? BigInt(highestBid?.amount) : undefined, + reservePrice: BigInt(reservePrice), + minBidIncrement: BigInt(minimumBidIncrement), + }) + + const [bidAmount, setBidAmount] = useState('') + const [isLoading, setIsLoading] = useState(false) + + const isMinBid = Number(bidAmount) >= minBidAmount + + const isValidBid = bidAmount && isMinBid + + const isValidChain = wagmiChain?.id === chainId + + const handleCreateBid = async () => { + if (!isMinBid || !bidAmount || isLoading) return + + try { + setIsLoading(true) + + const config = await prepareWriteContract({ + abi: auctionAbi, + address: auctionAddress as Address, + functionName: 'createBid', + args: [BigInt(currentAuction.token.tokenId)], + value: parseEther(bidAmount.toString()), + }) + const tx = await writeContract(config) + if (tx?.hash) await waitForTransaction({ hash: tx.hash }) + setBidAmount('') + } catch (error) { + console.error(error) + } finally { + setIsLoading(false) + } + } + + if (isEnded || isOver) { + return ( + + + + ) + } + + return ( + <> + + + setBidAmount(e.target.value)} + /> + + + + + + handleCreateBid()} + > + Bid + + + ) +} diff --git a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx new file mode 100644 index 00000000..64cacea3 --- /dev/null +++ b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx @@ -0,0 +1,166 @@ +import { Box, Flex, Text } from '@zoralabs/zord' +import dayjs from 'dayjs' +import Image from 'next/image' +import Link from 'next/link' +import { useRouter } from 'next/router' +import React, { useState } from 'react' +import { formatEther } from 'viem' +import { useContractEvent } from 'wagmi' + +import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' +import { auctionAbi } from 'src/data/contract/abis' +import { useCountdown, useIsMounted } from 'src/hooks' +import { AddressType } from 'src/typings' + +import { BidActionButton } from './BidActionButton' +import { DashboardDao } from './Dashboard' + +export const DaoAuctionCard = ( + props: DashboardDao & { userAddress: AddressType; handleMutate: () => void } +) => { + const { currentAuction, chainId, auctionAddress, handleMutate, tokenAddress } = props + const { name: chainName, icon: chainIcon } = + PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} + const router = useRouter() + const { endTime } = currentAuction + + const [isEnded, setIsEnded] = useState(false) + + const bidText = currentAuction.highestBid?.amount + ? formatEther(BigInt(currentAuction.highestBid.amount)) + : 'N/A' + + const isOver = !!endTime ? dayjs.unix(Date.now() / 1000) >= dayjs.unix(endTime) : true + const onEnd = () => { + setIsEnded(true) + } + + useContractEvent({ + address: auctionAddress, + abi: auctionAbi, + eventName: 'AuctionCreated', + chainId, + listener: async () => { + console.log('AuctionCreated') + setTimeout(() => { + handleMutate() + }, 3000) + }, + }) + useContractEvent({ + address: auctionAddress, + abi: auctionAbi, + eventName: 'AuctionBid', + chainId, + listener: async () => { + setTimeout(() => { + handleMutate() + }, 3000) + }, + }) + + return ( + chain.id === chainId)?.slug + }/${tokenAddress}`} + passHref + > + + + + + + + {chainIcon && ( + + )} + + {chainName} + + + + {currentAuction.token.name} + + + + + Current Bid + + + {bidText} + + + + + Ends In + + + + + + + ) +} + +const DashCountdown = ({ + endTime, + onEnd, + isOver, +}: { + endTime: string | null + onEnd: () => void + isOver: boolean +}) => { + const { countdownString } = useCountdown(Number(endTime), onEnd) + const isMounted = useIsMounted() + const countdownText = !endTime || isOver ? 'N/A' : countdownString + if (!isMounted) return null + return ( + + {countdownText} + + ) +} diff --git a/apps/web/src/modules/dashboard/DaoProposalCard.tsx b/apps/web/src/modules/dashboard/DaoProposalCard.tsx new file mode 100644 index 00000000..6b7b1ef0 --- /dev/null +++ b/apps/web/src/modules/dashboard/DaoProposalCard.tsx @@ -0,0 +1,28 @@ +import { Flex, Text } from '@zoralabs/zord' + +import { ProposalFragment } from 'src/data/subgraph/sdk.generated' + +export const DaoProposalCard = ({ title, proposalNumber }: ProposalFragment) => { + return ( + + + + {proposalNumber} + + + {title} + + + + ) +} diff --git a/apps/web/src/modules/dashboard/DaoProposals.tsx b/apps/web/src/modules/dashboard/DaoProposals.tsx new file mode 100644 index 00000000..3a9dba0b --- /dev/null +++ b/apps/web/src/modules/dashboard/DaoProposals.tsx @@ -0,0 +1,55 @@ +import { Box, Button, Flex, Text } from '@zoralabs/zord' +import { getFetchableUrl } from 'ipfs-service' +import Image from 'next/image' +import React from 'react' + +import { Avatar } from 'src/components/Avatar' + +import { DaoProposalCard } from './DaoProposalCard' +import { DashboardDao } from './Dashboard' + +export const DaoProposals = ({ + daoImage, + tokenAddress, + name, + proposals, +}: DashboardDao) => { + const daoImageSrc = React.useMemo(() => { + return daoImage ? getFetchableUrl(daoImage) : null + }, [daoImage]) + return ( + + + + {daoImageSrc ? ( + + + + ) : ( + + + + )} + + {name} + + + + + + {proposals.map((proposal) => ( + + ))} + + ) +} diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 16a7d15d..362ba45d 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -1,20 +1,9 @@ -import { Box, Button, Flex, Text } from '@zoralabs/zord' import axios from 'axios' -import dayjs from 'dayjs' -import { getFetchableUrl } from 'ipfs-service' -import Image from 'next/image' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' -import { Address, formatEther, parseEther } from 'viem' -import { useAccount, useBalance, useContractEvent, useNetwork } from 'wagmi' -import { prepareWriteContract, waitForTransaction, writeContract } from 'wagmi/actions' +import { useAccount } from 'wagmi' -import { Avatar } from 'src/components/Avatar' -import { ContractButton } from 'src/components/ContractButton' -import { Meta } from 'src/components/Meta' -import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' import SWR_KEYS from 'src/constants/swrKeys' -import { auctionAbi } from 'src/data/contract/abis' import { ProposalState, getProposalState, @@ -24,19 +13,11 @@ import { DaoFragment, ProposalFragment, } from 'src/data/subgraph/sdk.generated' -import { useCountdown, useIsMounted } from 'src/hooks' -import { AddressType, CHAIN_ID } from 'src/typings' +import { CHAIN_ID } from 'src/typings' -import { useMinBidIncrement } from '../auction' -import { Settle } from '../auction/components/CurrentAuction/Settle' -import { bidInput } from './dashboard.css' - -function maxChar(str: string, maxLength: number) { - if (str.length <= maxLength) { - return str - } - return str.slice(0, maxLength) + '...' -} +import { DaoAuctionCard } from './DaoAuctionCard' +import { DaoProposals } from './DaoProposals' +import { DashboardLayout } from './DashboardLayout' const ACTIVE_PROPOSAL_STATES = [ ProposalState.Active, @@ -44,7 +25,7 @@ const ACTIVE_PROPOSAL_STATES = [ ProposalState.Queued, ] -type DashboardDao = DaoFragment & { +export type DashboardDao = DaoFragment & { chainId: CHAIN_ID daoImage: string auctionConfig: { @@ -114,367 +95,22 @@ const Dashboard = () => { } return ( - - - - - Dashboard - - - - DAOs - - {data?.map((dao) => ( - - ))} - - - - Proposals - - {data - .filter((dao) => dao.proposals.length) - .map((dao) => ( - - ))} - - - - ) -} - -export default Dashboard - -const DashCountdown = ({ - endTime, - onEnd, - isOver, -}: { - endTime: string | null - onEnd: () => void - isOver: boolean -}) => { - const { countdownString } = useCountdown(Number(endTime), onEnd) - const isMounted = useIsMounted() - const countdownText = !endTime || isOver ? 'N/A' : countdownString - if (!isMounted) return null - return ( - - {countdownText} - - ) -} - -const DaoAuctionCard = ( - props: DashboardDao & { userAddress: AddressType; handleMutate: () => void } -) => { - const { currentAuction, chainId, auctionAddress, handleMutate } = props - const { name: chainName, icon: chainIcon } = - PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId) ?? {} - - const { endTime } = currentAuction - - const [isEnded, setIsEnded] = useState(false) - - const bidText = currentAuction.highestBid?.amount - ? formatEther(BigInt(currentAuction.highestBid.amount)) - : 'N/A' - - const isOver = !!endTime ? dayjs.unix(Date.now() / 1000) >= dayjs.unix(endTime) : true - const onEnd = () => { - setIsEnded(true) - } - - useContractEvent({ - address: auctionAddress, - abi: auctionAbi, - eventName: 'AuctionCreated', - chainId, - listener: async () => { - console.log('AuctionCreated') - setTimeout(() => { - handleMutate() - }, 3000) - }, - }) - useContractEvent({ - address: auctionAddress, - abi: auctionAbi, - eventName: 'AuctionBid', - chainId, - listener: async () => { - setTimeout(() => { - handleMutate() - }, 3000) - }, - }) - - return ( - - - ( + - - - - {chainIcon && ( - - )} - - {chainName} - - - - {currentAuction.token.name} - - - - - Current Bid - - - {bidText} - - - - - Ends In - - - - - - ) -} - -const DaoProposals = ({ daoImage, tokenAddress, name, proposals }: DashboardDao) => { - const daoImageSrc = React.useMemo(() => { - return daoImage ? getFetchableUrl(daoImage) : null - }, [daoImage]) - return ( - - - - {daoImageSrc ? ( - - - - ) : ( - - - - )} - - {name} - - - - - - {proposals.map((proposal) => ( - ))} - - ) -} - -const DaoProposalCard = ({ title, proposalNumber }: ProposalFragment) => { - return ( - - - - {proposalNumber} - - - {title} - - - + daoProposals={data + .filter((dao) => dao.proposals.length) + .map((dao) => ( + + ))} + /> ) } -const BidActionButton = ({ - userAddress, - chainId, - auctionConfig, - currentAuction, - isEnded, - auctionAddress, - isOver, -}: DashboardDao & { userAddress: AddressType; isOver: boolean; isEnded: boolean }) => { - const { data: balance } = useBalance({ address: userAddress, chainId }) - const { minimumBidIncrement, reservePrice } = auctionConfig - const { highestBid } = currentAuction - const { chain: wagmiChain } = useNetwork() - const { minBidAmount } = useMinBidIncrement({ - highestBid: highestBid?.amount ? BigInt(highestBid?.amount) : undefined, - reservePrice: BigInt(reservePrice), - minBidIncrement: BigInt(minimumBidIncrement), - }) - - const [bidAmount, setBidAmount] = useState('') - const [isLoading, setIsLoading] = useState(false) - - const isMinBid = Number(bidAmount) >= minBidAmount - - const isValidBid = bidAmount && isMinBid - - const isValidChain = wagmiChain?.id === chainId - - const handleCreateBid = async () => { - if (!isMinBid || !bidAmount || isLoading) return - - try { - setIsLoading(true) - - const config = await prepareWriteContract({ - abi: auctionAbi, - address: auctionAddress as Address, - functionName: 'createBid', - args: [BigInt(currentAuction.token.tokenId)], - value: parseEther(bidAmount.toString()), - }) - const tx = await writeContract(config) - if (tx?.hash) await waitForTransaction({ hash: tx.hash }) - setBidAmount('') - } catch (error) { - console.error(error) - } finally { - setIsLoading(false) - } - } - - if (isEnded || isOver) { - return ( - - - - ) - } - - return ( - <> -
- - setBidAmount(e.target.value)} - /> - - - - -
- handleCreateBid()} - > - Bid - - - ) -} +export default Dashboard diff --git a/apps/web/src/modules/dashboard/DashboardLayout.tsx b/apps/web/src/modules/dashboard/DashboardLayout.tsx new file mode 100644 index 00000000..2eda5c3e --- /dev/null +++ b/apps/web/src/modules/dashboard/DashboardLayout.tsx @@ -0,0 +1,40 @@ +import { Box, Flex, Text } from '@zoralabs/zord' +import React, { ReactNode } from 'react' + +import { Meta } from 'src/components/Meta' + +export const DashboardLayout = ({ + auctionCards, + daoProposals, +}: { + auctionCards: ReactNode + daoProposals: ReactNode +}) => { + return ( + + + + + Dashboard + + + + DAOs + + {auctionCards} + + + + Proposals + + {daoProposals} + + + + ) +} diff --git a/apps/web/src/utils/helpers.ts b/apps/web/src/utils/helpers.ts index 6dae7743..77a467f8 100644 --- a/apps/web/src/utils/helpers.ts +++ b/apps/web/src/utils/helpers.ts @@ -261,3 +261,10 @@ export function unpackOptionalArray( } return array } + +export function maxChar(str: string, maxLength: number) { + if (str.length <= maxLength) { + return str + } + return str.slice(0, maxLength) + '...' +} From 84d845cf003a72699c5ba5902cb4fe6b257d1fef Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 16:25:34 -0700 Subject: [PATCH 19/48] handle no active proposals --- .../src/modules/dashboard/BidActionButton.tsx | 4 --- apps/web/src/modules/dashboard/Dashboard.tsx | 35 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx index 51389e83..0771384d 100644 --- a/apps/web/src/modules/dashboard/BidActionButton.tsx +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -6,10 +6,6 @@ import { prepareWriteContract, waitForTransaction, writeContract } from 'wagmi/a import { ContractButton } from 'src/components/ContractButton' import { auctionAbi } from 'src/data/contract/abis' - - - - import { AddressType } from 'src/typings' import { maxChar } from 'src/utils/helpers' diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 362ba45d..deb894c9 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -1,3 +1,4 @@ +import { Flex, Text } from '@zoralabs/zord' import axios from 'axios' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' @@ -94,6 +95,8 @@ const Dashboard = () => { setMutating(false) } + const hasLiveProposals = data.some((dao) => dao.proposals.length) + return ( ( @@ -104,11 +107,33 @@ const Dashboard = () => { handleMutate={handleMutate} /> ))} - daoProposals={data - .filter((dao) => dao.proposals.length) - .map((dao) => ( - - ))} + daoProposals={ + hasLiveProposals ? ( + data + .filter((dao) => dao.proposals.length) + .map((dao) => ) + ) : ( + + + No Active Proposals + + + Currently, none of your DAOs have proposals that are in active, queue, or + pending states. Check back later! + + + ) + } /> ) } From 7886557c0096f9b77d603acde6eccb14764b73f0 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 16:39:20 -0700 Subject: [PATCH 20/48] handle no proposals, refactor layout --- apps/web/src/modules/dashboard/Dashboard.tsx | 6 ++-- .../src/modules/dashboard/DashboardLayout.tsx | 2 +- apps/web/src/modules/dashboard/Display.tsx | 31 +++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 apps/web/src/modules/dashboard/Display.tsx diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index deb894c9..069dcdaa 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -77,15 +77,15 @@ const Dashboard = () => { const [mutating, setMutating] = useState(false) if (error) { - return
error
+ return
Error
} if (isValidating && !mutating) { return
loading
} if (!address) { - return
no address
+ return
No address
} - if (!data) { + if (!data?.length) { return
no data
} diff --git a/apps/web/src/modules/dashboard/DashboardLayout.tsx b/apps/web/src/modules/dashboard/DashboardLayout.tsx index 2eda5c3e..11c393a5 100644 --- a/apps/web/src/modules/dashboard/DashboardLayout.tsx +++ b/apps/web/src/modules/dashboard/DashboardLayout.tsx @@ -8,7 +8,7 @@ export const DashboardLayout = ({ daoProposals, }: { auctionCards: ReactNode - daoProposals: ReactNode + daoProposals?: ReactNode }) => { return ( { + return ( + + + {title} + + {description} + + ) +} From aa4b69821ad35f5b2d89259b21f6114345a5cf77 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 16:58:38 -0700 Subject: [PATCH 21/48] proposal links --- .../src/modules/dashboard/DaoAuctionCard.tsx | 9 +--- .../src/modules/dashboard/DaoProposalCard.tsx | 52 ++++++++++++------- .../src/modules/dashboard/DaoProposals.tsx | 25 +++++++-- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx index 64cacea3..04b1f771 100644 --- a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx +++ b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx @@ -58,14 +58,9 @@ export const DaoAuctionCard = ( }, 3000) }, }) - + const currentChainSlug = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId)?.slug return ( - chain.id === chainId)?.slug - }/${tokenAddress}`} - passHref - > + { +export const DaoProposalCard = ({ + title, + proposalNumber, + tokenAddress, + chainId, +}: ProposalFragment & { chainId: CHAIN_ID; tokenAddress: AddressType }) => { + const currentChainSlug = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId)?.slug return ( - - - - {proposalNumber} - - - {title} - + + + + {proposalNumber} + + + {title} + + - + ) } diff --git a/apps/web/src/modules/dashboard/DaoProposals.tsx b/apps/web/src/modules/dashboard/DaoProposals.tsx index 3a9dba0b..7e0b38fd 100644 --- a/apps/web/src/modules/dashboard/DaoProposals.tsx +++ b/apps/web/src/modules/dashboard/DaoProposals.tsx @@ -1,9 +1,11 @@ import { Box, Button, Flex, Text } from '@zoralabs/zord' import { getFetchableUrl } from 'ipfs-service' import Image from 'next/image' +import { useRouter } from 'next/router' import React from 'react' import { Avatar } from 'src/components/Avatar' +import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' import { DaoProposalCard } from './DaoProposalCard' import { DashboardDao } from './Dashboard' @@ -13,12 +15,18 @@ export const DaoProposals = ({ tokenAddress, name, proposals, + chainId, }: DashboardDao) => { const daoImageSrc = React.useMemo(() => { return daoImage ? getFetchableUrl(daoImage) : null }, [daoImage]) + + const router = useRouter() + + const currentChainSlug = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId)?.slug + return ( - + {daoImageSrc ? ( @@ -43,12 +51,23 @@ export const DaoProposals = ({
- {proposals.map((proposal) => ( - + ))}
) From 6ec74bf753d0fe0bee71223d3bae4ddd027f8c1a Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 17:14:19 -0700 Subject: [PATCH 22/48] proposal status --- .../subgraph/queries/dashboardQuery.graphql | 3 +++ apps/web/src/data/subgraph/sdk.generated.ts | 9 ++++--- .../src/modules/dashboard/DaoProposalCard.tsx | 25 ++++++++++++++++--- .../src/modules/dashboard/DaoProposals.tsx | 1 + apps/web/src/modules/dashboard/Dashboard.tsx | 4 +-- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql index c7e98434..86f124a8 100644 --- a/apps/web/src/data/subgraph/queries/dashboardQuery.graphql +++ b/apps/web/src/data/subgraph/queries/dashboardQuery.graphql @@ -15,6 +15,9 @@ query dashboard($where: DAOTokenOwner_filter, $first: Int, $skip: Int) { orderDirection: desc ) { ...Proposal + voteEnd + voteStart + expiresAt } currentAuction { ...CurrentAuction diff --git a/apps/web/src/data/subgraph/sdk.generated.ts b/apps/web/src/data/subgraph/sdk.generated.ts index 388320ff..ac83a9fc 100644 --- a/apps/web/src/data/subgraph/sdk.generated.ts +++ b/apps/web/src/data/subgraph/sdk.generated.ts @@ -2071,13 +2071,15 @@ export type DashboardQuery = { } proposals: Array<{ __typename?: 'Proposal' + voteEnd: any + voteStart: any + expiresAt?: any | null abstainVotes: number againstVotes: number calldatas?: string | null description?: string | null descriptionHash: any executableFrom?: any | null - expiresAt?: any | null forVotes: number proposalId: any proposalNumber: number @@ -2088,8 +2090,6 @@ export type DashboardQuery = { timeCreated: any title?: string | null values: Array - voteEnd: any - voteStart: any snapshotBlockNumber: any transactionHash: any dao: { __typename?: 'DAO'; governorAddress: any; tokenAddress: any } @@ -2565,6 +2565,9 @@ export const DashboardDocument = gql` orderDirection: desc ) { ...Proposal + voteEnd + voteStart + expiresAt } currentAuction { ...CurrentAuction diff --git a/apps/web/src/modules/dashboard/DaoProposalCard.tsx b/apps/web/src/modules/dashboard/DaoProposalCard.tsx index e2a9a375..7882d0fc 100644 --- a/apps/web/src/modules/dashboard/DaoProposalCard.tsx +++ b/apps/web/src/modules/dashboard/DaoProposalCard.tsx @@ -2,15 +2,26 @@ import { Flex, Text } from '@zoralabs/zord' import Link from 'next/link' import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' +import { ProposalState } from 'src/data/contract/requests/getProposalState' import { ProposalFragment } from 'src/data/subgraph/sdk.generated' import { AddressType, CHAIN_ID } from 'src/typings' +import { ProposalStatus } from '../proposal/components/ProposalStatus' + export const DaoProposalCard = ({ title, proposalNumber, tokenAddress, chainId, -}: ProposalFragment & { chainId: CHAIN_ID; tokenAddress: AddressType }) => { + proposalState, + voteEnd, + voteStart, + expiresAt, +}: ProposalFragment & { + chainId: CHAIN_ID + tokenAddress: AddressType + proposalState: ProposalState +}) => { const currentChainSlug = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId)?.slug return ( - + {proposalNumber} - + {title} + diff --git a/apps/web/src/modules/dashboard/DaoProposals.tsx b/apps/web/src/modules/dashboard/DaoProposals.tsx index 7e0b38fd..cfcd31b5 100644 --- a/apps/web/src/modules/dashboard/DaoProposals.tsx +++ b/apps/web/src/modules/dashboard/DaoProposals.tsx @@ -67,6 +67,7 @@ export const DaoProposals = ({ {...proposal} chainId={chainId} tokenAddress={tokenAddress} + proposalState={proposal.proposalState} /> ))} diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index 069dcdaa..e6e63b7c 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -33,7 +33,7 @@ export type DashboardDao = DaoFragment & { minimumBidIncrement: string reservePrice: string } - proposals: ProposalFragment[] + proposals: (ProposalFragment & { proposalState: ProposalState })[] currentAuction: CurrentAuctionFragment } @@ -45,7 +45,7 @@ const fetchDaoProposalState = async (dao: DashboardDao) => { proposal.dao.governorAddress, proposal.proposalId ) - return { ...proposal, proposalState } + return { ...proposal, proposalState: proposalState } }) ) return { From e0156c2f1711362d679477f487e4bc193d016699 Mon Sep 17 00:00:00 2001 From: jordan Date: Mon, 11 Sep 2023 17:38:06 -0700 Subject: [PATCH 23/48] handle loading, create skeletons --- apps/web/src/modules/dashboard/Dashboard.tsx | 19 ++++++++- apps/web/src/modules/dashboard/Skeletons.tsx | 41 +++++++++++++++++++ .../src/modules/dashboard/dashboard.css.ts | 27 ++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/modules/dashboard/Skeletons.tsx diff --git a/apps/web/src/modules/dashboard/Dashboard.tsx b/apps/web/src/modules/dashboard/Dashboard.tsx index e6e63b7c..737d7d8b 100644 --- a/apps/web/src/modules/dashboard/Dashboard.tsx +++ b/apps/web/src/modules/dashboard/Dashboard.tsx @@ -1,4 +1,4 @@ -import { Flex, Text } from '@zoralabs/zord' +import { Box, Flex, Text } from '@zoralabs/zord' import axios from 'axios' import React, { useState } from 'react' import useSWR, { mutate } from 'swr' @@ -19,6 +19,7 @@ import { CHAIN_ID } from 'src/typings' import { DaoAuctionCard } from './DaoAuctionCard' import { DaoProposals } from './DaoProposals' import { DashboardLayout } from './DashboardLayout' +import { AuctionCardSkeleton, DAOCardSkeleton, ProposalCardSkeleton } from './Skeletons' const ACTIVE_PROPOSAL_STATES = [ ProposalState.Active, @@ -80,7 +81,21 @@ const Dashboard = () => { return
Error
} if (isValidating && !mutating) { - return
loading
+ return ( + ( + + ))} + daoProposals={ + + + {Array.from({ length: 2 }).map((_, i) => ( + + ))} + + } + /> + ) } if (!address) { return
No address
diff --git a/apps/web/src/modules/dashboard/Skeletons.tsx b/apps/web/src/modules/dashboard/Skeletons.tsx new file mode 100644 index 00000000..649337ab --- /dev/null +++ b/apps/web/src/modules/dashboard/Skeletons.tsx @@ -0,0 +1,41 @@ +import { Box } from '@zoralabs/zord' +import React from 'react' + +import { + auctionCardSkeleton, + daoCardSkeleton, + proposalCardSkeleton, +} from './dashboard.css' + +export const AuctionCardSkeleton = () => { + return ( + + ) +} + +export const DAOCardSkeleton = () => { + return ( + + ) +} + +export const ProposalCardSkeleton = () => { + return ( + + ) +} diff --git a/apps/web/src/modules/dashboard/dashboard.css.ts b/apps/web/src/modules/dashboard/dashboard.css.ts index a954934d..e41f8f58 100644 --- a/apps/web/src/modules/dashboard/dashboard.css.ts +++ b/apps/web/src/modules/dashboard/dashboard.css.ts @@ -1,6 +1,8 @@ import { style } from '@vanilla-extract/css' import { atoms, theme } from '@zoralabs/zord' +import { skeletonAnimation } from 'src/styles/animations.css' + export const bidInput = style([ { width: '100%', @@ -25,3 +27,28 @@ export const bidInput = style([ lineHeight: 24, }), ]) + +export const feed = style([ + atoms({ + m: 'auto', + }), + { + maxWidth: 912, + }, +]) + +export const auctionCardSkeleton = style({ + animation: skeletonAnimation, + height: '96px', +}) + +export const daoCardSkeleton = style({ + animation: skeletonAnimation, + height: '52px', + width: '175px', +}) + +export const proposalCardSkeleton = style({ + animation: skeletonAnimation, + height: '88px', +}) From 952c875ee8fb15ae47bce9c25900f5cfc706c4d3 Mon Sep 17 00:00:00 2001 From: jordan Date: Sun, 17 Sep 2023 16:18:21 -0700 Subject: [PATCH 24/48] fix propogate event bug --- apps/web/src/components/ContractButton.tsx | 6 +- .../src/modules/dashboard/BidActionButton.tsx | 11 +- .../src/modules/dashboard/DaoAuctionCard.tsx | 148 +++++++++--------- 3 files changed, 87 insertions(+), 78 deletions(-) diff --git a/apps/web/src/components/ContractButton.tsx b/apps/web/src/components/ContractButton.tsx index 1e7cf8d7..ac6fbb4b 100644 --- a/apps/web/src/components/ContractButton.tsx +++ b/apps/web/src/components/ContractButton.tsx @@ -6,7 +6,7 @@ import { useBridgeModal } from 'src/hooks/useBridgeModal' import { useChainStore } from 'src/stores/useChainStore' interface ContractButtonProps extends ButtonProps { - handleClick: () => void + handleClick: (e?: any) => void } export const ContractButton = ({ @@ -28,11 +28,11 @@ export const ContractButton = ({ const handleSwitchNetwork = () => switchNetwork?.(appChain.id) - const handleClickWithValidation = () => { + const handleClickWithValidation = (e?: any) => { if (!userAddress) return openConnectModal?.() if (canUserBridge && userBalance?.decimals === 0) return openBridgeModal() if (userChain?.id !== appChain.id) return handleSwitchNetwork() - handleClick() + handleClick(e) } return ( diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx index 0771384d..76165ee4 100644 --- a/apps/web/src/modules/dashboard/BidActionButton.tsx +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -89,6 +89,7 @@ export const BidActionButton = ({ max={balance?.formatted} value={bidAmount} onChange={(e) => setBidAmount(e.target.value)} + onClick={(e) => e.stopPropagation()} /> setBidAmount(minBidAmount.toString())} + onClick={(e: any) => { + e.stopPropagation() + setBidAmount(minBidAmount.toString()) + }} disabled={Number(bidAmount) >= minBidAmount} > Min @@ -121,7 +125,10 @@ export const BidActionButton = ({ borderRadius={'curved'} disabled={!isValidBid || !isValidChain} loading={isLoading} - handleClick={() => handleCreateBid()} + handleClick={(e: any) => { + e.stopPropagation() + handleCreateBid() + }} > Bid
diff --git a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx index 04b1f771..1fe14f58 100644 --- a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx +++ b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx @@ -1,7 +1,6 @@ import { Box, Flex, Text } from '@zoralabs/zord' import dayjs from 'dayjs' import Image from 'next/image' -import Link from 'next/link' import { useRouter } from 'next/router' import React, { useState } from 'react' import { formatEther } from 'viem' @@ -59,84 +58,87 @@ export const DaoAuctionCard = ( }, }) const currentChainSlug = PUBLIC_ALL_CHAINS.find((chain) => chain.id === chainId)?.slug + + const handleSelectAuction = () => { + router.push(`/dao/${currentChainSlug}/${tokenAddress}`) + } return ( - + + + + - - - - - - {chainIcon && ( - - )} - - {chainName} - - - - {currentAuction.token.name} - - - - - Current Bid - - - {bidText} - - - - - Ends In + + {chainIcon && ( + + )} + + {chainName} - - + + {currentAuction.token.name} + + + + + Current Bid + + + {bidText} + + + + + Ends In + + - + + ) } From 800b792f7b6f7e132e183c66c2e3463a53f28783 Mon Sep 17 00:00:00 2001 From: jordan Date: Sun, 17 Sep 2023 17:10:01 -0700 Subject: [PATCH 25/48] fix propagation drag effect bug --- apps/web/src/modules/dashboard/BidActionButton.tsx | 3 +++ apps/web/src/modules/dashboard/DaoAuctionCard.tsx | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx index 76165ee4..39791439 100644 --- a/apps/web/src/modules/dashboard/BidActionButton.tsx +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -35,6 +35,7 @@ export const BidActionButton = ({ const [bidAmount, setBidAmount] = useState('') const [isLoading, setIsLoading] = useState(false) + const [showTooltip, setShowTooltip] = useState(false) const isMinBid = Number(bidAmount) >= minBidAmount @@ -55,6 +56,7 @@ export const BidActionButton = ({ args: [BigInt(currentAuction.token.tokenId)], value: parseEther(bidAmount.toString()), }) + console.log('config', config) const tx = await writeContract(config) if (tx?.hash) await waitForTransaction({ hash: tx.hash }) setBidAmount('') @@ -129,6 +131,7 @@ export const BidActionButton = ({ e.stopPropagation() handleCreateBid() }} + position={'relative'} > Bid diff --git a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx index 1fe14f58..4b90d807 100644 --- a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx +++ b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx @@ -64,19 +64,17 @@ export const DaoAuctionCard = ( } return ( - + {chainIcon && ( From c9963eea371b99d783cde74308e5ed75410476a8 Mon Sep 17 00:00:00 2001 From: jordan Date: Sun, 17 Sep 2023 17:40:26 -0700 Subject: [PATCH 26/48] settle button styles --- .../modules/auction/components/Auction.css.ts | 5 ++++ .../components/CurrentAuction/Settle.tsx | 29 ++++++++++++++----- .../src/modules/dashboard/BidActionButton.tsx | 24 ++++++++++----- .../src/modules/dashboard/dashboard.css.ts | 1 - 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/apps/web/src/modules/auction/components/Auction.css.ts b/apps/web/src/modules/auction/components/Auction.css.ts index 04fc48b2..bf037c5c 100644 --- a/apps/web/src/modules/auction/components/Auction.css.ts +++ b/apps/web/src/modules/auction/components/Auction.css.ts @@ -157,6 +157,10 @@ export const auctionActionButton = style({ height: 56, }) +export const auctionActionDash = style({ + borderRadius: '12px', +}) + export const auctionActionButtonVariants = styleVariants({ bid: [auctionActionButton], bidding: [ @@ -168,6 +172,7 @@ export const auctionActionButtonVariants = styleVariants({ auctionActionButton, { width: '100%', background: '#F1F1F1', color: '#808080' }, ], + dashSettle: [auctionActionDash, { width: '100%' }], }) export const bidForm = style({ diff --git a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx index 0ec26842..cf688f13 100644 --- a/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx +++ b/apps/web/src/modules/auction/components/CurrentAuction/Settle.tsx @@ -21,13 +21,15 @@ interface SettleProps { collectionAddress?: string owner?: string | undefined externalAuctionAddress?: AddressType - customStyles?: { - settle: string - settling: string - } + compact?: boolean } -export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) => { +export const Settle = ({ + isEnding, + owner, + externalAuctionAddress, + compact = false, +}: SettleProps) => { const chain = useChainStore((x) => x.chain) const addresses = useDaoStore?.((state) => state.addresses) || {} @@ -81,7 +83,15 @@ export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) if (settling) { return ( - @@ -92,7 +102,12 @@ export const Settle = ({ isEnding, owner, externalAuctionAddress }: SettleProps) {isWinner ? 'Claim NFT' : 'Start next auction'} diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx index 39791439..fd3bd888 100644 --- a/apps/web/src/modules/dashboard/BidActionButton.tsx +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -69,19 +69,31 @@ export const BidActionButton = ({ if (isEnded || isOver) { return ( - + ) } return ( - <> -
+ + { - e.stopPropagation() setBidAmount(minBidAmount.toString()) }} disabled={Number(bidAmount) >= minBidAmount} @@ -127,14 +138,13 @@ export const BidActionButton = ({ borderRadius={'curved'} disabled={!isValidBid || !isValidChain} loading={isLoading} - handleClick={(e: any) => { - e.stopPropagation() + handleClick={() => { handleCreateBid() }} position={'relative'} > Bid - + ) } diff --git a/apps/web/src/modules/dashboard/dashboard.css.ts b/apps/web/src/modules/dashboard/dashboard.css.ts index e41f8f58..9c14f0dc 100644 --- a/apps/web/src/modules/dashboard/dashboard.css.ts +++ b/apps/web/src/modules/dashboard/dashboard.css.ts @@ -6,7 +6,6 @@ import { skeletonAnimation } from 'src/styles/animations.css' export const bidInput = style([ { width: '100%', - maxWidth: '150px', border: 'none', borderRadius: '12px', height: '48px', From 4e65b51cf71f24888a3d3233612bb6b95f5a5794 Mon Sep 17 00:00:00 2001 From: jordan Date: Sun, 17 Sep 2023 17:45:33 -0700 Subject: [PATCH 27/48] expand section paddings --- apps/web/src/modules/dashboard/DashboardLayout.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/modules/dashboard/DashboardLayout.tsx b/apps/web/src/modules/dashboard/DashboardLayout.tsx index 11c393a5..cbd697a5 100644 --- a/apps/web/src/modules/dashboard/DashboardLayout.tsx +++ b/apps/web/src/modules/dashboard/DashboardLayout.tsx @@ -19,10 +19,10 @@ export const DashboardLayout = ({ > - + Dashboard - + DAOs From 890e83603231fe820ae869379fd56759046b79d8 Mon Sep 17 00:00:00 2001 From: jordan Date: Wed, 20 Sep 2023 23:46:27 -0700 Subject: [PATCH 28/48] mobile for daoAuctionCards --- .../src/modules/dashboard/BidActionButton.tsx | 77 ++++------- .../src/modules/dashboard/DaoAuctionCard.tsx | 129 ++++++++---------- .../src/modules/dashboard/dashboard.css.ts | 120 ++++++++++++++++ 3 files changed, 203 insertions(+), 123 deletions(-) diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx index fd3bd888..91e0f9b2 100644 --- a/apps/web/src/modules/dashboard/BidActionButton.tsx +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Flex } from '@zoralabs/zord' +import { Box, Button } from '@zoralabs/zord' import React, { useState } from 'react' import { Address, parseEther } from 'viem' import { useBalance, useNetwork } from 'wagmi' @@ -12,7 +12,7 @@ import { maxChar } from 'src/utils/helpers' import { useMinBidIncrement } from '../auction' import { Settle } from '../auction/components/CurrentAuction/Settle' import { DashboardDao } from './Dashboard' -import { bidInput } from './dashboard.css' +import { bidButton, bidForm, bidInput, inputBox, minButton } from './dashboard.css' export const BidActionButton = ({ userAddress, @@ -69,32 +69,19 @@ export const BidActionButton = ({ if (isEnded || isOver) { return ( - - - + ) } return ( - - - + <> + + setBidAmount(e.target.value)} onClick={(e) => e.stopPropagation()} /> - { + setBidAmount(minBidAmount.toString()) + }} + disabled={Number(bidAmount) >= minBidAmount} > - - + Min + Bid - + ) } diff --git a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx index 4b90d807..53ef7050 100644 --- a/apps/web/src/modules/dashboard/DaoAuctionCard.tsx +++ b/apps/web/src/modules/dashboard/DaoAuctionCard.tsx @@ -13,6 +13,16 @@ import { AddressType } from 'src/typings' import { BidActionButton } from './BidActionButton' import { DashboardDao } from './Dashboard' +import { + auctionCardBrand, + bidBox, + daoAvatar, + daoAvatarBox, + daoTokenName, + outerAuctionCard, + stats, + statsBox, +} from './dashboard.css' export const DaoAuctionCard = ( props: DashboardDao & { userAddress: AddressType; handleMutate: () => void } @@ -40,7 +50,6 @@ export const DaoAuctionCard = ( eventName: 'AuctionCreated', chainId, listener: async () => { - console.log('AuctionCreated') setTimeout(() => { handleMutate() }, 3000) @@ -63,81 +72,55 @@ export const DaoAuctionCard = ( router.push(`/dao/${currentChainSlug}/${tokenAddress}`) } return ( - - - - - - - {chainIcon && ( - - )} - - {chainName} - - - - {currentAuction.token.name} - + + + + + + + + {chainIcon && ( + + )} + + {chainName} + + + {currentAuction.token.name} + - - - Current Bid - - - {bidText} - + + + + Current Bid + + + {bidText} + + + + + Ends In + + + - - - Ends In - - + + - ) } diff --git a/apps/web/src/modules/dashboard/dashboard.css.ts b/apps/web/src/modules/dashboard/dashboard.css.ts index 9c14f0dc..78515b94 100644 --- a/apps/web/src/modules/dashboard/dashboard.css.ts +++ b/apps/web/src/modules/dashboard/dashboard.css.ts @@ -3,6 +3,117 @@ import { atoms, theme } from '@zoralabs/zord' import { skeletonAnimation } from 'src/styles/animations.css' +export const outerAuctionCard = style([ + { + marginBottom: '24px', + width: '100%', + alignItems: 'center', + padding: '12px 24px', + '@media': { + 'screen and (max-width: 768px)': { + flexDirection: 'column', + padding: '16px 8px', + alignItems: 'flex-start', + gap: '16px', + }, + }, + }, + atoms({ + borderColor: 'border', + borderStyle: 'solid', + borderRadius: 'curved', + borderWidth: 'normal', + }), +]) + +export const daoTokenName = style([ + { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + width: '200px', + '@media': { + 'screen and (max-width: 912px)': { + width: '150px', + }, + 'screen and (max-width:768px)': { + width: '220px', + }, + }, + }, + atoms({ + fontWeight: 'label', + fontSize: 20, + }), +]) + +export const daoAvatar = style({ + objectFit: 'contain', + borderRadius: '16px', + height: 64, + width: 64, +}) +export const daoAvatarBox = style({ + marginRight: '24px', + width: '64px', +}) + +export const auctionCardBrand = style({ + alignItems: 'center', + width: '40%', + cursor: 'pointer', + '@media': { + 'screen and (max-width: 912px)': { + width: '35%', + }, + 'screen and (max-width: 768px)': { + width: '100%', + }, + }, +}) + +export const stats = style({ + width: '50%', +}) +export const statsBox = style({ + width: '30%', + '@media': { + 'screen and (max-width: 768px)': { + width: '80%', + }, + }, +}) + +export const bidBox = style({ + marginLeft: 'auto', + width: '220px', + '@media': { + 'screen and (max-width: 768px)': { + width: '100%', + marginLeft: 0, + }, + }, +}) + +export const bidForm = style({ + width: '70%', + '@media': { + 'screen and (max-width: 768px)': { + width: '80%', + }, + }, +}) +export const inputBox = style({ + // width: '80%', +}) +export const bidButton = style({ + width: '30%', + '@media': { + 'screen and (max-width: 768px)': { + width: '20%', + }, + }, +}) export const bidInput = style([ { width: '100%', @@ -51,3 +162,12 @@ export const proposalCardSkeleton = style({ animation: skeletonAnimation, height: '88px', }) +export const minButton = style({ + minWidth: 'fit-content', + fontWeight: 500, + paddingLeft: 0, + paddingRight: 0, + top: 0, + right: 0, + bottom: 0, +}) From 0e383b48620e7b3e3949f434911aabfa8b830e89 Mon Sep 17 00:00:00 2001 From: jordan Date: Wed, 20 Sep 2023 23:53:25 -0700 Subject: [PATCH 29/48] bid auctionbox corrections --- .../src/modules/dashboard/BidActionButton.tsx | 4 ++-- .../src/modules/dashboard/dashboard.css.ts | 23 ++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/apps/web/src/modules/dashboard/BidActionButton.tsx b/apps/web/src/modules/dashboard/BidActionButton.tsx index 91e0f9b2..8bccb77a 100644 --- a/apps/web/src/modules/dashboard/BidActionButton.tsx +++ b/apps/web/src/modules/dashboard/BidActionButton.tsx @@ -12,7 +12,7 @@ import { maxChar } from 'src/utils/helpers' import { useMinBidIncrement } from '../auction' import { Settle } from '../auction/components/CurrentAuction/Settle' import { DashboardDao } from './Dashboard' -import { bidButton, bidForm, bidInput, inputBox, minButton } from './dashboard.css' +import { bidButton, bidForm, bidInput, minButton } from './dashboard.css' export const BidActionButton = ({ userAddress, @@ -81,7 +81,7 @@ export const BidActionButton = ({ return ( <>
- + Date: Thu, 21 Sep 2023 00:13:14 -0700 Subject: [PATCH 30/48] mobile DAO proposal headers --- .../src/modules/dashboard/DaoProposals.tsx | 26 +++++++++++-------- .../src/modules/dashboard/dashboard.css.ts | 11 ++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/apps/web/src/modules/dashboard/DaoProposals.tsx b/apps/web/src/modules/dashboard/DaoProposals.tsx index cfcd31b5..9b9eaee4 100644 --- a/apps/web/src/modules/dashboard/DaoProposals.tsx +++ b/apps/web/src/modules/dashboard/DaoProposals.tsx @@ -9,6 +9,7 @@ import { PUBLIC_ALL_CHAINS } from 'src/constants/defaultChains' import { DaoProposalCard } from './DaoProposalCard' import { DashboardDao } from './Dashboard' +import { daoName } from './dashboard.css' export const DaoProposals = ({ daoImage, @@ -27,7 +28,7 @@ export const DaoProposals = ({ return ( - + {daoImageSrc ? ( @@ -46,7 +47,7 @@ export const DaoProposals = ({ )} - + {name} @@ -54,6 +55,7 @@ export const DaoProposals = ({ - {proposals.map((proposal) => ( - - ))} + + {proposals.map((proposal) => ( + + ))} + ) } diff --git a/apps/web/src/modules/dashboard/dashboard.css.ts b/apps/web/src/modules/dashboard/dashboard.css.ts index dd91d90a..0708dfc8 100644 --- a/apps/web/src/modules/dashboard/dashboard.css.ts +++ b/apps/web/src/modules/dashboard/dashboard.css.ts @@ -162,3 +162,14 @@ export const minButton = style({ right: 0, bottom: 0, }) +export const daoName = style({ + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + width: 300, + '@media': { + 'screen and (max-width: 484px)': { + width: '200px', + }, + }, +}) From de516b6dd34b46951d60ac0b9459a293bffd18a5 Mon Sep 17 00:00:00 2001 From: jordan Date: Thu, 21 Sep 2023 13:59:50 -0700 Subject: [PATCH 31/48] dash proposal card mobile --- .../src/modules/dashboard/DaoProposalCard.tsx | 42 +++++++++++++---- .../src/modules/dashboard/DaoProposals.tsx | 47 ++++++++++--------- .../src/modules/dashboard/dashboard.css.ts | 4 +- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/apps/web/src/modules/dashboard/DaoProposalCard.tsx b/apps/web/src/modules/dashboard/DaoProposalCard.tsx index 7882d0fc..6b1e0387 100644 --- a/apps/web/src/modules/dashboard/DaoProposalCard.tsx +++ b/apps/web/src/modules/dashboard/DaoProposalCard.tsx @@ -30,22 +30,41 @@ export const DaoProposalCard = ({ > - - - {proposalNumber} - - - {title} - + + {proposalNumber} + + + + {title} + + + + + {proposalNumber} + + diff --git a/apps/web/src/modules/dashboard/DaoProposals.tsx b/apps/web/src/modules/dashboard/DaoProposals.tsx index 9b9eaee4..03b63ed6 100644 --- a/apps/web/src/modules/dashboard/DaoProposals.tsx +++ b/apps/web/src/modules/dashboard/DaoProposals.tsx @@ -1,6 +1,7 @@ import { Box, Button, Flex, Text } from '@zoralabs/zord' import { getFetchableUrl } from 'ipfs-service' import Image from 'next/image' +import Link from 'next/link' import { useRouter } from 'next/router' import React from 'react' @@ -29,28 +30,30 @@ export const DaoProposals = ({ return ( - - {daoImageSrc ? ( - - - - ) : ( - - - - )} - - {name} - - + + + {daoImageSrc ? ( + + + + ) : ( + + + + )} + + {name} + + +