tidy up
This commit is contained in:
parent
74447f8482
commit
a759b0fe6f
|
@ -28,7 +28,7 @@ import { useTheme } from 'next-themes'
|
|||
import { IconButton } from './shared/Button'
|
||||
|
||||
const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { t } = useTranslation(['common', 'search'])
|
||||
const { connected } = useWallet()
|
||||
const group = mangoStore.getState().group
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
|
@ -125,7 +125,7 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
|||
active={pathname === '/search'}
|
||||
collapsed={false}
|
||||
icon={<MagnifyingGlassIcon className="h-5 w-5" />}
|
||||
title={t('search-accounts')}
|
||||
title={t('search:search-accounts')}
|
||||
pagePath="/search"
|
||||
hideIconBg
|
||||
showTooltip={false}
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
Cog8ToothIcon,
|
||||
BuildingLibraryIcon,
|
||||
ArrowTrendingUpIcon,
|
||||
MagnifyingGlassIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import SolanaTps from '@components/SolanaTps'
|
||||
|
||||
|
@ -103,7 +104,7 @@ const MoreMenuPanel = ({
|
|||
showPanel: boolean
|
||||
setShowPanel: (showPanel: boolean) => void
|
||||
}) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { t } = useTranslation(['common', 'search'])
|
||||
return (
|
||||
<div
|
||||
className={`fixed bottom-0 z-30 h-96 w-full overflow-hidden rounded-t-3xl bg-th-bkg-2 px-4 transition duration-300 ease-in-out ${
|
||||
|
@ -125,6 +126,11 @@ const MoreMenuPanel = ({
|
|||
path="/stats"
|
||||
icon={<ChartBarIcon className="h-5 w-5" />}
|
||||
/>
|
||||
<MoreMenuItem
|
||||
title={t('search:search-accounts')}
|
||||
path="/search"
|
||||
icon={<MagnifyingGlassIcon className="h-5 w-5" />}
|
||||
/>
|
||||
<MoreMenuItem
|
||||
title={t('learn')}
|
||||
path="https://docs.mango.markets/"
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
import Input from '@components/forms/Input'
|
||||
import Label from '@components/forms/Label'
|
||||
import Button from '@components/shared/Button'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
MagnifyingGlassIcon,
|
||||
NoSymbolIcon,
|
||||
UserIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ChangeEvent, useState } from 'react'
|
||||
import { abbreviateAddress } from 'utils/formatting'
|
||||
import { notify } from 'utils/notifications'
|
||||
|
||||
const SEARCH_TYPES = [
|
||||
'mango-account',
|
||||
'mango-account-name',
|
||||
'profile-name',
|
||||
'wallet-pk',
|
||||
]
|
||||
|
||||
const SearchPage = () => {
|
||||
const { t } = useTranslation('search')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [searchString, setSearchString] = useState('')
|
||||
const [searchResults, setSearchResults] = useState([])
|
||||
const [searchType, setSearchType] = useState('mango-account')
|
||||
const [showNoResults, setShowNoResults] = useState(false)
|
||||
|
||||
const handleSearch = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const response = await fetch(
|
||||
`https://mango-transaction-log.herokuapp.com/v4/user-data/profile-search?search-string=${searchString}&search-method=${searchType}`
|
||||
)
|
||||
const data = await response.json()
|
||||
setSearchResults(data)
|
||||
if (!data.length) {
|
||||
setShowNoResults(true)
|
||||
}
|
||||
} catch {
|
||||
notify({
|
||||
title: t('search-failed'),
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const isAccountSearch =
|
||||
searchType === 'mango-account' || searchType === 'mango-account-name'
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-12 p-8 pb-20 md:pb-16 lg:p-10">
|
||||
<div className="col-span-12 lg:col-span-8 lg:col-start-3">
|
||||
<h1 className="mb-4">{t('search-accounts')}</h1>
|
||||
<div className="mb-4">
|
||||
<Label text={t('search-by')} />
|
||||
<ButtonGroup
|
||||
activeValue={searchType}
|
||||
onChange={(t) => setSearchType(t)}
|
||||
names={SEARCH_TYPES.map((val) => t(val))}
|
||||
values={SEARCH_TYPES}
|
||||
/>
|
||||
</div>
|
||||
<Label text={t('search-for')} />
|
||||
<div className="flex space-x-2">
|
||||
<Input
|
||||
type="text"
|
||||
name="search"
|
||||
id="search"
|
||||
value={searchString}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
setSearchString(e.target.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="flex items-center"
|
||||
onClick={() => handleSearch()}
|
||||
disabled={!searchString}
|
||||
size="large"
|
||||
>
|
||||
<MagnifyingGlassIcon className="mr-2 h-5 w-5" />
|
||||
{t('search')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="space-y-2 pt-8">
|
||||
{searchResults.length || showNoResults ? (
|
||||
<h2 className="mb-4 border-t border-th-bkg-3 pt-4 text-base">
|
||||
{t('results')}
|
||||
</h2>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{loading ? (
|
||||
<>
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-20 w-full rounded-md bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-20 w-full rounded-md bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
</>
|
||||
) : searchResults.length ? (
|
||||
searchResults.map((r) =>
|
||||
isAccountSearch ? (
|
||||
<MangoAccountItem item={r} type={searchType} />
|
||||
) : (
|
||||
<WalletItem item={r} />
|
||||
)
|
||||
)
|
||||
) : showNoResults ? (
|
||||
<div className="flex flex-col items-center rounded-md border border-th-bkg-3 p-4">
|
||||
<NoSymbolIcon className="mb-1 h-6 w-6 text-th-fgd-3" />
|
||||
<p className="mb-0.5 text-base font-bold text-th-fgd-2">
|
||||
{t('no-results')}
|
||||
</p>
|
||||
<p>{t('no-results-desc')}</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface MangoAccountItem {
|
||||
mango_account_name: string
|
||||
mango_account_pk: string
|
||||
wallet_pk: string
|
||||
profile_name: string
|
||||
}
|
||||
|
||||
const MangoAccountItem = ({
|
||||
item,
|
||||
type,
|
||||
}: {
|
||||
item: MangoAccountItem
|
||||
type: 'mango-account' | 'mango-account-name'
|
||||
}) => {
|
||||
const { mango_account_name, mango_account_pk, profile_name } = item
|
||||
return (
|
||||
<a
|
||||
className="default-transition flex items-center justify-between rounded-md border border-th-bkg-3 p-4 md:hover:border-th-bkg-4"
|
||||
href={`/?address=${mango_account_pk}`}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<div className="">
|
||||
<p className="mb-1 text-base font-bold text-th-fgd-2">
|
||||
{type === 'mango-account'
|
||||
? abbreviateAddress(new PublicKey(mango_account_pk))
|
||||
: mango_account_name}
|
||||
</p>
|
||||
<div className="flex items-center space-x-1.5">
|
||||
<UserIcon className="h-4 w-4 text-th-fgd-3" />
|
||||
<p className="capitalize">{profile_name}</p>
|
||||
</div>
|
||||
</div>
|
||||
<ChevronRightIcon className="h-6 w-6 text-th-fgd-3" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
interface WalletItem {
|
||||
mango_accounts: { mango_account_name: string; mango_account_pk: string }[]
|
||||
owner: string
|
||||
profile_name: string
|
||||
}
|
||||
|
||||
const WalletItem = ({ item }: { item: WalletItem }) => {
|
||||
const { mango_accounts, profile_name } = item
|
||||
return (
|
||||
<>
|
||||
{mango_accounts.length
|
||||
? mango_accounts.map((a) => (
|
||||
<a
|
||||
className="default-transition flex items-center justify-between rounded-md border border-th-bkg-3 p-4 md:hover:border-th-bkg-4"
|
||||
href={`/?address=${a.mango_account_pk}`}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
key={a.mango_account_pk}
|
||||
>
|
||||
<div className="">
|
||||
<p className="mb-1 text-base font-bold text-th-fgd-2">
|
||||
{a.mango_account_name}
|
||||
</p>
|
||||
<div className="flex items-center space-x-1.5">
|
||||
<UserIcon className="h-4 w-4 text-th-fgd-3" />
|
||||
<p className="capitalize">{profile_name}</p>
|
||||
</div>
|
||||
</div>
|
||||
<ChevronRightIcon className="h-6 w-6 text-th-fgd-3" />
|
||||
</a>
|
||||
))
|
||||
: null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchPage
|
|
@ -8,6 +8,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
...(await serverSideTranslations(locale, [
|
||||
'common',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
])),
|
||||
// Will be passed to the page component as props
|
||||
|
|
|
@ -22,6 +22,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'common',
|
||||
'onboarding',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'token',
|
||||
'trade',
|
||||
|
|
|
@ -10,6 +10,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'onboarding',
|
||||
'onboarding-tours',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'swap',
|
||||
'trade',
|
||||
|
|
188
pages/search.tsx
188
pages/search.tsx
|
@ -1,195 +1,21 @@
|
|||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
import Input from '@components/forms/Input'
|
||||
import Label from '@components/forms/Label'
|
||||
import Button from '@components/shared/Button'
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
MagnifyingGlassIcon,
|
||||
UserIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import SearchPage from '@components/search/SearchPage'
|
||||
import type { NextPage } from 'next'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { ChangeEvent, useState } from 'react'
|
||||
import { abbreviateAddress } from 'utils/formatting'
|
||||
import { notify } from 'utils/notifications'
|
||||
|
||||
export async function getStaticProps({ locale }: { locale: string }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common'])),
|
||||
...(await serverSideTranslations(locale, [
|
||||
'common',
|
||||
'profile',
|
||||
'search',
|
||||
])),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const Search: NextPage = () => {
|
||||
const { t } = useTranslation('search')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [searchString, setSearchString] = useState('')
|
||||
const [searchResults, setSearchResults] = useState([])
|
||||
const [searchType, setSearchType] = useState('mango-account')
|
||||
const [showNoResults, setShowNoResults] = useState(false)
|
||||
|
||||
const handleSearch = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const response = await fetch(
|
||||
`https://mango-transaction-log.herokuapp.com/v4/user-data/profile-search?search-string=${searchString}&search-method=${searchType}`
|
||||
)
|
||||
const data = await response.json()
|
||||
setSearchResults(data)
|
||||
if (!data.length) {
|
||||
setShowNoResults(true)
|
||||
}
|
||||
} catch {
|
||||
notify({
|
||||
title: t('search-failed'),
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const isAccountSearch =
|
||||
searchType === 'mango-account' || searchType === 'mango-account-name'
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-12 p-8 pb-20 md:pb-16 lg:p-10">
|
||||
<div className="col-span-12 lg:col-span-8 lg:col-start-3">
|
||||
<h1 className="mb-4">{t('search-accounts')}</h1>
|
||||
<div className="mb-4">
|
||||
<Label text={t('search-by')} />
|
||||
<ButtonGroup
|
||||
activeValue={searchType}
|
||||
onChange={(t) => setSearchType(t)}
|
||||
values={[
|
||||
'mango-account',
|
||||
'mango-account-name',
|
||||
'profile-name',
|
||||
'wallet-pk',
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<Label text={t('search-for')} />
|
||||
<div className="flex space-x-2">
|
||||
<Input
|
||||
type="text"
|
||||
name="search"
|
||||
id="search"
|
||||
value={searchString}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
setSearchString(e.target.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="flex items-center"
|
||||
onClick={() => handleSearch()}
|
||||
disabled={!searchString}
|
||||
size="large"
|
||||
>
|
||||
<MagnifyingGlassIcon className="mr-2 h-5 w-5" />
|
||||
{t('search')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="space-y-2 py-6">
|
||||
{searchResults.length || showNoResults ? (
|
||||
<h2 className="text-base">
|
||||
{t('results')}{' '}
|
||||
<span className="font-mono text-sm font-normal text-th-fgd-4">
|
||||
({searchResults.length})
|
||||
</span>
|
||||
</h2>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{loading ? (
|
||||
'Loading...'
|
||||
) : searchResults.length ? (
|
||||
searchResults.map((r) =>
|
||||
isAccountSearch ? (
|
||||
<MangoAccountItem item={r} type={searchType} />
|
||||
) : (
|
||||
<WalletItem item={r} />
|
||||
)
|
||||
)
|
||||
) : showNoResults ? (
|
||||
<div className="flex flex-col items-center rounded-md border border-th-bkg-3 p-4">
|
||||
<p className="mb-1 text-base font-bold text-th-fgd-2">
|
||||
{t('no-results')}
|
||||
</p>
|
||||
<p>{t('no-results-desc')}</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface MangoAccountItem {
|
||||
mango_account_name: string
|
||||
mango_account_pk: string
|
||||
wallet_pk: string
|
||||
profile_name: string
|
||||
}
|
||||
|
||||
const MangoAccountItem = ({
|
||||
item,
|
||||
type,
|
||||
}: {
|
||||
item: MangoAccountItem
|
||||
type: 'mango-account' | 'mango-account-name'
|
||||
}) => {
|
||||
const { mango_account_name, mango_account_pk, profile_name } = item
|
||||
return (
|
||||
<a
|
||||
className="default-transition flex items-center justify-between rounded-md border border-th-bkg-3 p-4 md:hover:border-th-bkg-4"
|
||||
href={`/?address=${mango_account_pk}`}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<div className="">
|
||||
<p className="mb-1 text-base font-bold text-th-fgd-2">
|
||||
{type === 'mango-account'
|
||||
? abbreviateAddress(new PublicKey(mango_account_pk))
|
||||
: mango_account_name}
|
||||
</p>
|
||||
<div className="flex items-center space-x-1.5">
|
||||
<UserIcon className="h-4 w-4 text-th-fgd-3" />
|
||||
<p className="capitalize">{profile_name}</p>
|
||||
</div>
|
||||
</div>
|
||||
<ChevronRightIcon className="h-6 w-6 text-th-fgd-3" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
interface WalletItem {
|
||||
mango_accounts: { mango_account_name: string; mango_account_pk: string }[]
|
||||
owner: string
|
||||
profile_name: string
|
||||
}
|
||||
|
||||
const WalletItem = ({ item }: { item: WalletItem }) => {
|
||||
const { mango_accounts, owner, profile_name } = item
|
||||
return (
|
||||
<div className="rounded-md border border-th-bkg-3 p-4">
|
||||
<div className="">
|
||||
<p>{profile_name}</p>
|
||||
<p>{owner}</p>
|
||||
</div>
|
||||
{mango_accounts.length
|
||||
? mango_accounts.map((a) => (
|
||||
<div key={a.mango_account_pk}>
|
||||
<p>{a.mango_account_name}</p>
|
||||
<p>{a.mango_account_pk}</p>
|
||||
</div>
|
||||
))
|
||||
: 'No Mango Accounts'}
|
||||
</div>
|
||||
)
|
||||
return <SearchPage />
|
||||
}
|
||||
|
||||
export default Search
|
||||
|
|
|
@ -14,6 +14,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'common',
|
||||
'onboarding',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
])),
|
||||
},
|
||||
|
|
|
@ -9,6 +9,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'common',
|
||||
'onboarding',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'token',
|
||||
'trade',
|
||||
|
|
|
@ -10,6 +10,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'onboarding',
|
||||
'onboarding-tours',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'swap',
|
||||
'settings',
|
||||
|
|
|
@ -9,6 +9,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
...(await serverSideTranslations(locale, [
|
||||
'common',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'token',
|
||||
])),
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
} from '@blockworks-foundation/mango-v4'
|
||||
import TradeAdvancedPage from '@components/trade/TradeAdvancedPage'
|
||||
import mangoStore, { DEFAULT_TRADE_FORM } from '@store/mangoStore'
|
||||
// import mangoStore from '@store/mangoStore'
|
||||
import type { NextPage } from 'next'
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { useRouter } from 'next/router'
|
||||
|
@ -20,6 +19,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'onboarding',
|
||||
'onboarding-tours',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'trade',
|
||||
])),
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"mango-account": "Account Address",
|
||||
"mango-account-name": "Account Name",
|
||||
"no-results": "No Results",
|
||||
"no-results-desc": "Try another search. Searches are case-sensitive execpt for profile names which are lowercase",
|
||||
"profile-name": "Profile Name",
|
||||
"results": "Results",
|
||||
"search": "Search",
|
||||
"search-accounts": "Search Accounts",
|
||||
"search-by": "Search By",
|
||||
"search-for": "Search For",
|
||||
"search-failed": "Failed to search",
|
||||
"wallet-pk": "Wallet Address"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"mango-account": "Account Address",
|
||||
"mango-account-name": "Account Name",
|
||||
"no-results": "No Results",
|
||||
"no-results-desc": "Try another search. Searches are case-sensitive execpt for profile names which are lowercase",
|
||||
"profile-name": "Profile Name",
|
||||
"results": "Results",
|
||||
"search": "Search",
|
||||
"search-accounts": "Search Accounts",
|
||||
"search-by": "Search By",
|
||||
"search-for": "Search For",
|
||||
"search-failed": "Failed to search",
|
||||
"wallet-pk": "Wallet Address"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"mango-account": "Account Address",
|
||||
"mango-account-name": "Account Name",
|
||||
"no-results": "No Results",
|
||||
"no-results-desc": "Try another search. Searches are case-sensitive execpt for profile names which are lowercase",
|
||||
"profile-name": "Profile Name",
|
||||
"results": "Results",
|
||||
"search": "Search",
|
||||
"search-accounts": "Search Accounts",
|
||||
"search-by": "Search By",
|
||||
"search-for": "Search For",
|
||||
"search-failed": "Failed to search",
|
||||
"wallet-pk": "Wallet Address"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"mango-account": "Account Address",
|
||||
"mango-account-name": "Account Name",
|
||||
"no-results": "No Results",
|
||||
"no-results-desc": "Try another search. Searches are case-sensitive execpt for profile names which are lowercase",
|
||||
"profile-name": "Profile Name",
|
||||
"results": "Results",
|
||||
"search": "Search",
|
||||
"search-accounts": "Search Accounts",
|
||||
"search-by": "Search By",
|
||||
"search-for": "Search For",
|
||||
"search-failed": "Failed to search",
|
||||
"wallet-pk": "Wallet Address"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"mango-account": "Account Address",
|
||||
"mango-account-name": "Account Name",
|
||||
"no-results": "No Results",
|
||||
"no-results-desc": "Try another search. Searches are case-sensitive execpt for profile names which are lowercase",
|
||||
"profile-name": "Profile Name",
|
||||
"results": "Results",
|
||||
"search": "Search",
|
||||
"search-accounts": "Search Accounts",
|
||||
"search-by": "Search By",
|
||||
"search-for": "Search For",
|
||||
"search-failed": "Failed to search",
|
||||
"wallet-pk": "Wallet Address"
|
||||
}
|
Loading…
Reference in New Issue