diff --git a/components/LaunchPad/Sale/CreateTokenSale.tsx b/components/LaunchPad/Sale/CreateTokenSale.tsx
index 1feefc053..97631819c 100644
--- a/components/LaunchPad/Sale/CreateTokenSale.tsx
+++ b/components/LaunchPad/Sale/CreateTokenSale.tsx
@@ -14,7 +14,7 @@
* along with this program. If not, see .
*/
-import React, { useContext, useState } from 'react'
+import React, { useContext, useEffect, useState } from 'react'
import { CreatorAddress } from '../CreatorAddress'
import { Note } from '../note'
@@ -28,6 +28,27 @@ import Button from '@mui/material/Button'
import OutlinedInput from '@/components/Input/OutlinedInput'
import { styles } from '../styles.css'
import { WalletReducerContext } from '@/hooks/WalletsReducerProvider'
+import { TokenSearchInput } from '../TokenSearchInput'
+
+const columns = [
+ {
+ id: 'symbol',
+ label: 'Symbol'
+ },
+ {
+ id: 'assetName',
+ label: 'Name'
+ },
+ {
+ id: 'assetId',
+ label: 'AssetId'
+ },
+ {
+ id: 'availableBalance',
+ label: 'Available Balance',
+ format: (value) => value.toLocaleString('en-US')
+ }
+]
const initialValues = {
assetId: '',
@@ -39,12 +60,71 @@ export const CreateTokenSale = () => {
const { activeWallet } = useContext(WalletReducerContext)
const [loading, setLoading] = useState(false)
const [formData, setFormData] = useState(initialValues)
+ const [assetList, setAssetList] = useState([])
+
const { assetId, quantity, perUnit } = formData
const onChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value })
}
+ const fetchUserAssets = () => {
+ setAssetList([
+ {
+ assetId: 7789624,
+ symbol: 'BUSD',
+ assetName: 'BUSD Token',
+ availableBalance: 300000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC Token',
+ availableBalance: 200000
+ },
+ {
+ assetId: 3789654,
+ symbol: 'goBTC',
+ assetName: 'goBTC',
+ availableBalance: 240000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 100000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ }
+ ])
+ }
+
+ useEffect(() => {
+ fetchUserAssets()
+ }, [])
+
const onSubmit = async (e) => {
e.preventDefault()
@@ -80,16 +160,14 @@ export const CreateTokenSale = () => {
Choose Asset:
-
- onChange(e)}
- sx={styles.input}
- />
-
+
diff --git a/components/LaunchPad/Sale/ManageTokenSale.tsx b/components/LaunchPad/Sale/ManageTokenSale.tsx
index 5fc001de6..ae9cdfdc8 100644
--- a/components/LaunchPad/Sale/ManageTokenSale.tsx
+++ b/components/LaunchPad/Sale/ManageTokenSale.tsx
@@ -14,7 +14,7 @@
* along with this program. If not, see .
*/
-import React, { useContext, useState } from 'react'
+import React, { useContext, useEffect, useState } from 'react'
import { CreatorAddress } from '../CreatorAddress'
import { Icon } from '@iconify/react'
@@ -30,6 +30,7 @@ import { styles } from '../styles.css'
import { CopyIcon } from '../copyIcon'
import { LinearProgressWithLabel } from '../progressBar'
import { WalletReducerContext } from '@/hooks/WalletsReducerProvider'
+import { TokenSearchInput } from '../TokenSearchInput'
const initialValues = {
tokenName: '',
@@ -39,9 +40,30 @@ const initialValues = {
showTotalForSale: false
}
+const columns = [
+ {
+ id: 'symbol',
+ label: 'Symbol'
+ },
+ {
+ id: 'assetName',
+ label: 'Name'
+ },
+ {
+ id: 'assetId',
+ label: 'AssetId'
+ },
+ {
+ id: 'availableBalance',
+ label: 'Available Balance',
+ format: (value) => value.toLocaleString('en-US')
+ }
+]
+
export const ManageTokenSale = () => {
const { activeWallet } = useContext(WalletReducerContext)
const [formData, setFormData] = useState(initialValues)
+ const [assetList, setAssetList] = useState([])
const { tokenName, pricePerToken, showPricePerToken, totalForSale, showTotalForSale } = formData
const onChange = (e) => {
@@ -61,6 +83,63 @@ export const ManageTokenSale = () => {
e.preventDefault()
}
+ const fetchUserAssets = () => {
+ setAssetList([
+ {
+ assetId: 7789624,
+ symbol: 'BUSD',
+ assetName: 'BUSD Token',
+ availableBalance: 300000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC Token',
+ availableBalance: 200000
+ },
+ {
+ assetId: 3789654,
+ symbol: 'goBTC',
+ assetName: 'goBTC',
+ availableBalance: 240000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 100000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ availableBalance: 200000
+ }
+ ])
+ }
+
+ useEffect(() => {
+ fetchUserAssets()
+ }, [])
+
return (
<>
@@ -89,16 +168,15 @@ export const ManageTokenSale = () => {
Choose Sale to Manage:
-
- onChange(e)}
- sx={styles.input}
- />
-
+
+
Search with Asset Name or Asset ID - Only ASAs created by the currently connected wallet
will show as options.
diff --git a/components/LaunchPad/Sale/SearchTable.tsx b/components/LaunchPad/Sale/SearchTable.tsx
new file mode 100644
index 000000000..fb9f2dc45
--- /dev/null
+++ b/components/LaunchPad/Sale/SearchTable.tsx
@@ -0,0 +1,176 @@
+import React, { MutableRefObject, useEffect, useMemo, useState } from 'react'
+import Icon from '@/components/Icon'
+
+//MUI components
+import Paper from '@mui/material/Paper'
+import Table from '@mui/material/Table'
+import TableBody from '@mui/material/TableBody'
+import TableCell, { tableCellClasses } from '@mui/material/TableCell'
+import TableContainer from '@mui/material/TableContainer'
+import TableHead from '@mui/material/TableHead'
+import TableRow from '@mui/material/TableRow'
+import { styled } from '@mui/material/styles'
+import Box from '@mui/material/Box'
+import TableSortLabel from '@mui/material/TableSortLabel'
+
+const StyledTableCell = styled(TableCell)(({ theme }) => ({
+ color: 'gray.800',
+ [`&.${tableCellClasses.head}`]: {
+ backgroundColor: 'white',
+ border: '0.1px solid',
+ borderColor: theme.palette.primary.light,
+ fontSize: 10,
+ textTransform: 'uppercase',
+ paddingBlock: '3px'
+ },
+ [`&.${tableCellClasses.body}`]: {
+ fontWeight: 600,
+ fontSize: 14,
+ border: '0.1px solid',
+ borderColor: theme.palette.primary.light,
+ paddingBlock: '8px'
+ }
+}))
+
+const SortIcon = styled(Icon)`
+ margin-left: 0.25rem;
+`
+
+export type TableColumnType = {
+ id: string
+ label: string
+ align?: 'left' | 'center' | 'right' | 'justify' | 'inherit'
+ minWidth?: number
+ format?: (val: number) => string
+}
+
+export const SearchTable = ({
+ columns,
+ rowData,
+ showTable,
+ setShowTable,
+ dropdownRef
+}: {
+ columns: Array
+ rowData: Array
+ showTable: boolean
+ setShowTable: (v: boolean) => void
+ dropdownRef: MutableRefObject
+}) => {
+ const [order, setOrder] = useState<'asc' | 'desc'>('desc')
+ const [orderBy, setOrderBy] = useState('assetName')
+
+ const createSortHandler = (property: string) => {
+ const isAsc = orderBy === property && order === 'asc'
+ setOrder(isAsc ? 'desc' : 'asc')
+ setOrderBy(property)
+ }
+
+ const sortedData = useMemo(() => {
+ if (order === 'asc') {
+ return rowData.sort((a, b) => `${a[orderBy]}`.localeCompare(`${b[orderBy]}`))
+ } else {
+ return rowData.sort((a, b) => `${b[orderBy]}`.localeCompare(`${a[orderBy]}`))
+ }
+ }, [rowData, order, orderBy])
+
+ const handleClickOutside = (event) => {
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
+ setShowTable(false)
+ }
+ }
+
+ useEffect(() => {
+ document.addEventListener('click', handleClickOutside, true)
+ return () => {
+ document.removeEventListener('click', handleClickOutside, true)
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
+
+ if (rowData.length === 0 || !showTable) {
+ return null
+ }
+
+ return (
+
+
+
+
+
+ {columns.map((col) => (
+
+ createSortHandler(col.id)}
+ sx={{
+ '.css-1vweko9-MuiSvgIcon-root-MuiTableSortLabel-icon, .css-3l415a-MuiSvgIcon-root-MuiTableSortLabel-icon, .css-s6n6v6, .css-tqymag':
+ {
+ display: 'none'
+ }
+ }}
+ >
+ {col.label}
+
+
+
+
+
+ ))}
+
+
+
+ {sortedData.map((row, index) => {
+ return (
+
+ {columns.map((column) => {
+ return (
+
+ {column.format && typeof row[column.id] === 'number'
+ ? column.format(row[column.id])
+ : row[column.id]}
+
+ )
+ })}
+
+ )
+ })}
+
+
+
+
+ )
+}
diff --git a/components/LaunchPad/Token/ManageToken.tsx b/components/LaunchPad/Token/ManageToken.tsx
index 14ed4fbdb..1dd9669af 100644
--- a/components/LaunchPad/Token/ManageToken.tsx
+++ b/components/LaunchPad/Token/ManageToken.tsx
@@ -14,7 +14,7 @@
* along with this program. If not, see .
*/
-import React, { ChangeEvent, useContext, useState } from 'react'
+import React, { ChangeEvent, useContext, useEffect, useState } from 'react'
import { CreatorAddress } from '../CreatorAddress'
import { Icon } from '@iconify/react'
@@ -32,6 +32,7 @@ import { CopyIcon } from '../copyIcon'
import { WalletReducerContext } from '@/hooks/WalletsReducerProvider'
import { isValidAddr, truncatedWalletAddress } from '@/components/helpers'
import { ErrorMessage } from '../ErrorMessage'
+import { TokenSearchInput } from '../TokenSearchInput'
const initialValues = {
tokenName: '',
@@ -46,10 +47,30 @@ const initialValues = {
freezeAddr: 'V537CZGHERY87634WVQCAGFYTRYH'
}
+const columns = [
+ {
+ id: 'symbol',
+ label: 'Symbol'
+ },
+ {
+ id: 'assetName',
+ label: 'Name'
+ },
+ {
+ id: 'assetId',
+ label: 'AssetId'
+ },
+ {
+ id: 'totalQuantity',
+ label: 'Quantity'
+ }
+]
+
export const ManageToken = () => {
const { activeWallet } = useContext(WalletReducerContext)
const [loading, setLoading] = useState(false)
const [formData, setFormData] = useState(initialValues)
+ const [assetList, setAssetList] = useState([])
const [error, setError] = useState({})
const {
tokenName,
@@ -116,6 +137,62 @@ export const ManageToken = () => {
setLoading(false)
}
+ const fetchUserAssets = () => {
+ setAssetList([
+ {
+ assetId: 7789624,
+ symbol: 'BUSD',
+ assetName: 'BUSD Token',
+ totalQuantity: 300000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC Token',
+ totalQuantity: 200000
+ },
+ {
+ assetId: 3789654,
+ symbol: 'goBTC',
+ assetName: 'goBTC',
+ totalQuantity: 240000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ totalQuantity: 100000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ totalQuantity: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ totalQuantity: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ totalQuantity: 200000
+ },
+ {
+ assetId: 6789654,
+ symbol: 'UCDC',
+ assetName: 'UCDC',
+ totalQuantity: 200000
+ }
+ ])
+ }
+
+ useEffect(() => {
+ fetchUserAssets()
+ }, [])
return (
<>
@@ -144,16 +221,15 @@ export const ManageToken = () => {
Choose Token to Manage:
-
- onChange(e)}
- sx={styles.input}
- />
-
+
+
Search with Asset Name or Asset ID - Only ASAs created by the currently connected wallet
will show as options.
diff --git a/components/LaunchPad/TokenSearchInput.tsx b/components/LaunchPad/TokenSearchInput.tsx
new file mode 100644
index 000000000..24386646d
--- /dev/null
+++ b/components/LaunchPad/TokenSearchInput.tsx
@@ -0,0 +1,49 @@
+import React, { useRef, useState } from 'react'
+import { SearchTable, TableColumnType } from './Sale/SearchTable'
+import { styles } from './styles.css'
+
+//MUI Components
+import Box from '@mui/material/Box'
+
+// Custom Styled Components
+import OutlinedInput from '@/components/Input/OutlinedInput'
+
+export const TokenSearchInput = ({
+ value,
+ name,
+ onChange,
+ columns,
+ rowData,
+ placeholder
+}: {
+ value: string | number
+ name: string
+ onChange: (e: unknown) => void
+ columns: TableColumnType[]
+ rowData: unknown[]
+ placeholder: string
+}) => {
+ const [showTable, setShowTable] = useState(false)
+ const dropdownRef = useRef(null)
+
+ return (
+
+ onChange(e)}
+ onFocus={() => setShowTable(true)}
+ sx={styles.input}
+ />
+
+
+ )
+}