Skip to content

Commit

Permalink
Merge pull request #215 from AmbireTech/admin-panel-on-steroids
Browse files Browse the repository at this point in the history
Admin panel on steroids
  • Loading branch information
ivopaunov authored Jul 12, 2024
2 parents 436a933 + 7e55749 commit 3891487
Show file tree
Hide file tree
Showing 18 changed files with 635 additions and 211 deletions.
28 changes: 25 additions & 3 deletions public/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,31 @@
<link rel="icon" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="title" content="AdEx Platform" />
<meta name="description" content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />

<meta name="title" content="AdEx Platform" /> <meta name="title" content="AdEx Platform" />
<meta
name="description"
content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space"
/>

<meta property="og:type" content="website">
<meta name="og:title" content="AdEx Platform" />
<meta
name="og:description"
content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space"
/>
<meta name="og:image" content="/adex-reach-beyond-web3-ai-powered.png" />

<meta property="twitter:type" content="website">
<meta name="twitter:title" content="AdEx Platform" />
<meta
name="twitter:description"
content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space"
/>
<meta name="twitter:image" content="/adex-reach-beyond-web3-ai-powered.png" />
<meta name="twitter:card" content="/adex-reach-beyond-web3-ai-powered.png" />


<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
Expand Down
Binary file added public/adex-reach-beyond-web3-ai-powered.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 18 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,24 @@
name="description"
content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space"
/>
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />

<meta property="og:type" content="website">
<meta name="og:title" content="AdEx Platform" />
<meta
name="og:description"
content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space"
/>
<meta name="og:image" content="/adex-reach-beyond-web3-ai-powered.png" />

<meta property="twitter:type" content="website">
<meta name="twitter:title" content="AdEx Platform" />
<meta
name="twitter:description"
content="With the AdEx ad platform, you target the untapped market of Web2 users entering the Web3 space"
/>
<meta name="twitter:image" content="/adex-reach-beyond-web3-ai-powered.png" />
<meta name="twitter:card" content="/adex-reach-beyond-web3-ai-powered.png" />

<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
Expand Down
19 changes: 11 additions & 8 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Global, MantineProvider, Progress } from '@mantine/core'
import { ModalsProvider } from '@mantine/modals'
import { AccountProvider } from 'contexts/AccountContext'
import { AdminProvider } from 'contexts/AdminContext'

import { RouterProvider } from 'react-router-dom'
import { router } from 'Router'
Expand Down Expand Up @@ -41,14 +42,16 @@ ReactGA.initialize('G-PX5B4P9KKM')
function App() {
return (
<AccountProvider>
<MantineProvider withGlobalStyles withNormalizeCSS theme={lightTheme}>
<ModalsProvider>
<GlobalStyles />
<Notifications />
{ENV && <EnvBanner />}
<RouterProvider router={router} />
</ModalsProvider>
</MantineProvider>
<AdminProvider>
<MantineProvider withGlobalStyles withNormalizeCSS theme={lightTheme}>
<ModalsProvider>
<GlobalStyles />
<Notifications />
{ENV && <EnvBanner />}
<RouterProvider router={router} />
</ModalsProvider>
</MantineProvider>
</AdminProvider>
</AccountProvider>
)
}
Expand Down
11 changes: 9 additions & 2 deletions src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { CreateCampaignContextProvider } from 'contexts/CreateCampaignContext/Cr
import { CampaignsDataProvider, CampaignsAnalyticsProvider } from 'contexts/CampaignsContext'
import NotFound404 from 'components/404/404'
// import AdminPanel from './admin/Admin'
import { AccountDetails } from 'components/AdminPanel/AccountDetails'
import CampaignDetails from './components/CampaignDetails'

function ErrorBoundary() {
Expand Down Expand Up @@ -105,14 +106,20 @@ export const router = createBrowserRouter(
element: <CreateCampaign />
},
{
path: 'admin',
path: 'admin/:tabValue',
element: (
<RequireAuth>
<CampaignsDataProvider type="admin">
<AdminPanel />
</CampaignsDataProvider>
</RequireAuth>
)
),
children: [
{
path: ':accountId',
element: <AccountDetails />
}
]
}
]
},
Expand Down
41 changes: 41 additions & 0 deletions src/components/AdminPanel/AccountDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useMemo } from 'react'
import {
SimpleGrid,
Box
// Accordion
} from '@mantine/core'
import useAdmin from 'hooks/useAdmin'
import { useParams } from 'react-router-dom'
import { FundsActivity } from './AccountDetailsElements'
import { AccountInfo } from './AccoutInfo'
import { AdminDeposit } from './AdminDeposit'

function AccountDetails() {
const { accountId = '' } = useParams()
const { accounts, initialDataLoading } = useAdmin()
const accountData = useMemo(() => accounts.get(accountId), [accounts, accountId])

if (!accountData || initialDataLoading) {
return <div>{`Invalid account id ${accountId}`}</div>
}

return (
<Box>
<SimpleGrid
cols={2}
breakpoints={[
{ maxWidth: 'xl', cols: 2, spacing: 'md' },
{ maxWidth: 'md', cols: 1, spacing: 'md' }
]}
>
<AccountInfo accountData={accountData} />
<AdminDeposit accountData={accountData} />
</SimpleGrid>
<SimpleGrid spacing="md" mt="md">
<FundsActivity accountData={accountData} />
</SimpleGrid>
</Box>
)
}

export { AccountDetails }
38 changes: 38 additions & 0 deletions src/components/AdminPanel/AccountDetailsElements.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useMemo } from 'react'
import { Account } from 'types'
import { Box, Text } from '@mantine/core'

import CustomTable from 'components/common/CustomTable'
import { parseBigNumTokenAmountToDecimal } from 'helpers/balances'

export const FundsActivity = ({ accountData }: { accountData: Account }) => {
const elements = useMemo(() => {
const data = accountData.fundsDeposited.deposits
.sort((a, b) => Number(b.created) - Number(a.created))
.map((x) => {
return {
id: x.created?.toString() || '',
date: new Date(x.created).toLocaleDateString(),
amount: parseBigNumTokenAmountToDecimal(x.amount, x.token.decimals),
token: x.token.name,
txHash: x.txHash
}
})

console.log({ data })

return data
}, [accountData])

return (
<Box>
<Text />
<CustomTable
background
headings={['Date', 'Amount', 'Token', 'Tx hash']}
elements={elements}
pageSize={10}
/>
</Box>
)
}
80 changes: 43 additions & 37 deletions src/components/AdminPanel/Accounts.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useState, useMemo } from 'react'
import { useEffect, useMemo, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import {
Container,
Loader,
Expand All @@ -10,68 +11,56 @@ import {
} from '@mantine/core'

import CustomTable from 'components/common/CustomTable'
import { useAdExApi } from 'hooks/useAdexServices'
import { Account } from 'types'
import useAdmin from 'hooks/useAdmin'

import { parseBigNumTokenAmountToDecimal } from 'helpers/balances'

const headingsDefault = ['Id', 'email', 'balance', 'campaigns launched', 'total spend', 'created']
const headingsDefault = [
'Id',
'verified billing',
'email',
'balance',
'campaigns launched',
'total spend',
'created'
]

const AdminAnalytics = () => {
const { adexServicesRequest } = useAdExApi()
const [loading, setLoading] = useState(true)
const [accounts, setAccounts] = useState<Array<Account>>([])
const navigate = useNavigate()
const { accounts, initialDataLoading, updateAccounts } = useAdmin()
const headings = useMemo(() => [...headingsDefault], [])

useEffect(() => {
const getData = async () => {
try {
const res = await adexServicesRequest<Array<Account>>('backend', {
route: '/dsp/admin/accounts/all',
method: 'GET',
headers: {
'content-type': 'application/json'
}
})

console.log({ res })
setAccounts(res)
} catch (err) {
console.log({ err })
}
setLoading(false)
}

getData()
}, [adexServicesRequest])

const data = useMemo(() => {
if (!accounts.length) {
if (!accounts.size) {
return {
elements: [],
totalDeposits: 0,
totalCampaignsLocked: 0
}
}

const accArr = Array.from(accounts.values())
// TODO: fix this when multy token
const decimals = accounts[0]?.balanceToken?.decimals
const decimals = accArr[0].balanceToken?.decimals
const totalDeposits = parseBigNumTokenAmountToDecimal(
accounts?.reduce((sum, a) => sum + BigInt(a.fundsDeposited.total), 0n),
accArr.reduce((sum, a) => sum + BigInt(a.fundsDeposited.total), 0n),
decimals
).toLocaleString()
const totalCampaignsLocked = parseBigNumTokenAmountToDecimal(
accounts?.reduce(
accArr.reduce(
(sum, a) => sum + BigInt(a.fundsOnCampaigns.total - a.refundsFromCampaigns.total),
0n
),
decimals
).toLocaleString()

const elements = accounts
const elements = accArr
.sort((a, b) => Number(b.availableBalance) - Number(a.availableBalance))
.map((a) => {
return {
id: a.id,
accountId: a.id,
accountId: a.name || a.id,
verified: a?.billingDetails?.verified ? '✅' : '❌',
email: a.info?.email,
balance: parseBigNumTokenAmountToDecimal(
a.availableBalance,
Expand All @@ -93,9 +82,20 @@ const AdminAnalytics = () => {
}
}, [accounts])

useEffect(() => {
updateAccounts()
}, [updateAccounts])

const handlePreview = useCallback(
(item: { id: string }) => {
navigate(`/dashboard/admin/user-account/${item.id}`, {})
},
[navigate]
)

return (
<Container fluid>
{loading ? (
{initialDataLoading ? (
<Loader size="xl" variant="dots" color="violet" />
) : (
<Flex direction="column">
Expand All @@ -111,7 +111,13 @@ const AdminAnalytics = () => {
({data.totalCampaignsLocked} USDC)
</Badge>
</Flex>
<CustomTable background headings={headings} elements={data.elements} pageSize={10} />
<CustomTable
background
headings={headings}
elements={data.elements}
pageSize={10}
onPreview={handlePreview}
/>
</Flex>
)}
</Container>
Expand Down
Loading

0 comments on commit 3891487

Please sign in to comment.