update routing and use new sign in function
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import React, { useContext } from 'react'
|
import React, { useContext, useEffect } from 'react'
|
||||||
import {
|
import {
|
||||||
CardContent,
|
CardContent,
|
||||||
|
CircularProgress,
|
||||||
IconButton,
|
IconButton,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme,
|
useTheme,
|
||||||
@@ -8,10 +9,16 @@ import {
|
|||||||
import { ClientContext } from '../context/main'
|
import { ClientContext } from '../context/main'
|
||||||
import { FileCopy, Refresh } from '@material-ui/icons'
|
import { FileCopy, Refresh } from '@material-ui/icons'
|
||||||
import { NymCard } from './NymCard'
|
import { NymCard } from './NymCard'
|
||||||
|
import { Alert } from '@material-ui/lab'
|
||||||
|
|
||||||
export const BalanceCard = () => {
|
export const BalanceCard = () => {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const { client } = useContext(ClientContext)
|
const { balance, balanceError, balanceLoading, getBalance } =
|
||||||
|
useContext(ClientContext)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getBalance()
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ margin: theme.spacing(3) }}>
|
<div style={{ margin: theme.spacing(3) }}>
|
||||||
@@ -20,13 +27,23 @@ export const BalanceCard = () => {
|
|||||||
subheader="Current wallet balance"
|
subheader="Current wallet balance"
|
||||||
noPadding
|
noPadding
|
||||||
Action={
|
Action={
|
||||||
<IconButton>
|
<IconButton onClick={getBalance}>
|
||||||
<Refresh />
|
<Refresh />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography>{client.balance}</Typography>
|
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||||
|
{balanceLoading ? (
|
||||||
|
<CircularProgress size={28} />
|
||||||
|
) : balanceError ? (
|
||||||
|
<Alert severity="error" style={{ width: '100%' }}>
|
||||||
|
{balanceError}
|
||||||
|
</Alert>
|
||||||
|
) : (
|
||||||
|
<Typography>{balance}</Typography>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</NymCard>
|
</NymCard>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,7 +52,7 @@ export const BalanceCard = () => {
|
|||||||
|
|
||||||
export const AddressCard = () => {
|
export const AddressCard = () => {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const { client } = useContext(ClientContext)
|
const { address } = useContext(ClientContext)
|
||||||
return (
|
return (
|
||||||
<div style={{ margin: theme.spacing(3) }}>
|
<div style={{ margin: theme.spacing(3) }}>
|
||||||
<NymCard
|
<NymCard
|
||||||
@@ -48,7 +65,7 @@ export const AddressCard = () => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CardContent>{client.address}</CardContent>
|
<CardContent>{address}</CardContent>
|
||||||
</NymCard>
|
</NymCard>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
import {
|
import {
|
||||||
List,
|
List,
|
||||||
@@ -18,8 +18,7 @@ import {
|
|||||||
MoneyOff,
|
MoneyOff,
|
||||||
} from '@material-ui/icons'
|
} from '@material-ui/icons'
|
||||||
import { makeStyles } from '@material-ui/styles'
|
import { makeStyles } from '@material-ui/styles'
|
||||||
import clsx from 'clsx'
|
import { ClientContext } from '../context/main'
|
||||||
import { theme } from '../theme'
|
|
||||||
|
|
||||||
const routesSchema = [
|
const routesSchema = [
|
||||||
{
|
{
|
||||||
@@ -57,11 +56,6 @@ const routesSchema = [
|
|||||||
route: '/undelegate',
|
route: '/undelegate',
|
||||||
Icon: <Cancel />,
|
Icon: <Cancel />,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'Log out',
|
|
||||||
route: '/signin',
|
|
||||||
Icon: <ExitToApp />,
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
@@ -76,7 +70,7 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||||||
|
|
||||||
export const Nav = () => {
|
export const Nav = () => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const location = useLocation()
|
const { logOut } = useContext(ClientContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -89,25 +83,26 @@ export const Nav = () => {
|
|||||||
<List>
|
<List>
|
||||||
{routesSchema.map((r, i) => (
|
{routesSchema.map((r, i) => (
|
||||||
<ListItem button component={Link} to={r.route} key={i}>
|
<ListItem button component={Link} to={r.route} key={i}>
|
||||||
<ListItemIcon
|
<ListItemIcon className={classes.navItem}>{r.Icon}</ListItemIcon>
|
||||||
className={clsx([
|
|
||||||
classes.navItem,
|
|
||||||
location.pathname === r.route ? classes.selected : undefined,
|
|
||||||
])}
|
|
||||||
>
|
|
||||||
{r.Icon}
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={r.label}
|
primary={r.label}
|
||||||
primaryTypographyProps={{
|
primaryTypographyProps={{
|
||||||
className: clsx([
|
className: classes.navItem,
|
||||||
classes.navItem,
|
|
||||||
location.pathname === r.route ? classes.selected : undefined,
|
|
||||||
]),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
|
<ListItem button onClick={logOut}>
|
||||||
|
<ListItemIcon className={classes.navItem}>
|
||||||
|
<ExitToApp />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary="Log out"
|
||||||
|
primaryTypographyProps={{
|
||||||
|
className: classes.navItem,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
import React, { createContext } from 'react'
|
import { invoke } from '@tauri-apps/api/tauri'
|
||||||
|
import React, { createContext, useEffect, useState } from 'react'
|
||||||
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
||||||
type TClientContext = {
|
type TClientContext = {
|
||||||
client: { address: string; balance: string }
|
isLoggedIn: boolean
|
||||||
|
address: string
|
||||||
|
balance?: string
|
||||||
|
balanceLoading: boolean
|
||||||
|
balanceError?: string
|
||||||
|
logIn: () => void
|
||||||
|
logOut: () => void
|
||||||
|
getBalance: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ClientContext = createContext({} as TClientContext)
|
export const ClientContext = createContext({} as TClientContext)
|
||||||
@@ -11,12 +20,44 @@ export const ClientContextProvider = ({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}) => {
|
}) => {
|
||||||
const client = {
|
const [isLoggedIn, setIsLoggedIn] = useState(false)
|
||||||
address: 'punk1s63y29jf8f3ft64z0vh80g3c76ty8lnyr74eur',
|
const [balance, setBalance] = useState<string>()
|
||||||
balance: '2000 PUNKS',
|
const [balanceError, setBalanceError] = useState<string>()
|
||||||
|
const [balanceLoading, setBalanceLoading] = useState(false)
|
||||||
|
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const getBalance = () => {
|
||||||
|
setBalanceLoading(true)
|
||||||
|
setBalanceError(undefined)
|
||||||
|
invoke('get_balance')
|
||||||
|
.then((balance) => {
|
||||||
|
setBalance(balance as string)
|
||||||
|
})
|
||||||
|
.catch((e) => setBalanceError(e))
|
||||||
|
setBalanceLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logIn = () => setIsLoggedIn(true)
|
||||||
|
const logOut = () => setIsLoggedIn(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
!isLoggedIn ? history.push('/signin') : history.push('/bond')
|
||||||
|
}, [isLoggedIn])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClientContext.Provider value={{ client }}>
|
<ClientContext.Provider
|
||||||
|
value={{
|
||||||
|
isLoggedIn,
|
||||||
|
balance,
|
||||||
|
balanceError,
|
||||||
|
address: 'punk1s63y29jf8f3ft64z0vh80g3c76ty8lnyr74eur',
|
||||||
|
balanceLoading,
|
||||||
|
logIn,
|
||||||
|
logOut,
|
||||||
|
getBalance,
|
||||||
|
}}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</ClientContext.Provider>
|
</ClientContext.Provider>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { CssBaseline, ThemeProvider } from '@material-ui/core'
|
import { CssBaseline, ThemeProvider } from '@material-ui/core'
|
||||||
|
import { BrowserRouter as Router } from 'react-router-dom'
|
||||||
import { Routes } from './routes'
|
import { Routes } from './routes'
|
||||||
import { theme } from './theme'
|
import { theme } from './theme'
|
||||||
import { ClientContextProvider } from './context/main'
|
import { ClientContextProvider } from './context/main'
|
||||||
@@ -8,9 +9,11 @@ import { ClientContextProvider } from './context/main'
|
|||||||
const App = () => (
|
const App = () => (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<ClientContextProvider>
|
<Router>
|
||||||
<Routes />
|
<ClientContextProvider>
|
||||||
</ClientContextProvider>
|
<Routes />
|
||||||
|
</ClientContextProvider>
|
||||||
|
</Router>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -9,47 +9,45 @@ import { Alert } from '@material-ui/lab'
|
|||||||
import { theme } from '../theme'
|
import { theme } from '../theme'
|
||||||
|
|
||||||
export const Balance = () => {
|
export const Balance = () => {
|
||||||
const { client } = useContext(ClientContext)
|
const { balance, balanceError, getBalance } = useContext(ClientContext)
|
||||||
|
|
||||||
|
const RefreshAction = () => (
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
type="submit"
|
||||||
|
onClick={getBalance}
|
||||||
|
disabled={false}
|
||||||
|
disableElevation
|
||||||
|
startIcon={<Refresh />}
|
||||||
|
>
|
||||||
|
Refresh
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<Layout>
|
<Layout>
|
||||||
<NymCard title="Check Balance">
|
<NymCard title="Check Balance">
|
||||||
{client === null ? (
|
<Grid container direction="column" spacing={2}>
|
||||||
<NoClientError />
|
<Grid item>
|
||||||
) : (
|
{balanceError && (
|
||||||
<Grid container direction="column" spacing={2}>
|
<Alert severity="error" action={<RefreshAction />}>
|
||||||
<Grid item>
|
{balanceError}
|
||||||
<Confirmation
|
</Alert>
|
||||||
isLoading={false}
|
)}
|
||||||
error={null}
|
{!balanceError && (
|
||||||
progressMessage="Checking balance..."
|
<Alert
|
||||||
SuccessMessage={
|
severity="success"
|
||||||
<Alert
|
style={{ padding: theme.spacing(2, 3) }}
|
||||||
severity="success"
|
action={<RefreshAction />}
|
||||||
style={{ padding: theme.spacing(2, 3) }}
|
>
|
||||||
action={
|
{'The current balance is ' + balance}
|
||||||
<Button
|
</Alert>
|
||||||
variant="contained"
|
)}
|
||||||
size="small"
|
|
||||||
color="primary"
|
|
||||||
type="submit"
|
|
||||||
onClick={() => {}}
|
|
||||||
disabled={false}
|
|
||||||
disableElevation
|
|
||||||
startIcon={<Refresh />}
|
|
||||||
>
|
|
||||||
Refresh
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{'The current balance is ' + client.balance}
|
|
||||||
</Alert>
|
|
||||||
}
|
|
||||||
failureMessage="Failed to check the account balance!"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
</Grid>
|
||||||
</NymCard>
|
</NymCard>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Switch, Route } from 'react-router-dom'
|
import { Switch, Route } from 'react-router-dom'
|
||||||
import { BrowserRouter as Router } from 'react-router-dom'
|
|
||||||
import { NotFound } from './404'
|
import { NotFound } from './404'
|
||||||
import { Balance } from './balance'
|
import { Balance } from './balance'
|
||||||
import { Bond } from './bond'
|
import { Bond } from './bond'
|
||||||
@@ -12,38 +11,36 @@ import { Unbond } from './unbond'
|
|||||||
import { Undelegate } from './undelegate'
|
import { Undelegate } from './undelegate'
|
||||||
|
|
||||||
export const Routes = () => (
|
export const Routes = () => (
|
||||||
<Router>
|
<Switch>
|
||||||
<Switch>
|
<Route path="/" exact>
|
||||||
<Route path="/" exact>
|
<SignIn />
|
||||||
<SignIn />
|
</Route>
|
||||||
</Route>
|
<Route path="/balance">
|
||||||
<Route path="/balance">
|
<Balance />
|
||||||
<Balance />
|
</Route>
|
||||||
</Route>
|
<Route path="/send">
|
||||||
<Route path="/send">
|
<Send />
|
||||||
<Send />
|
</Route>
|
||||||
</Route>
|
<Route path="/receive">
|
||||||
<Route path="/receive">
|
<Receive />
|
||||||
<Receive />
|
</Route>
|
||||||
</Route>
|
<Route path="/bond">
|
||||||
<Route path="/bond">
|
<Bond />
|
||||||
<Bond />
|
</Route>
|
||||||
</Route>
|
<Route path="/unbond">
|
||||||
<Route path="/unbond">
|
<Unbond />
|
||||||
<Unbond />
|
</Route>
|
||||||
</Route>
|
<Route path="/delegate">
|
||||||
<Route path="/delegate">
|
<Delegate />
|
||||||
<Delegate />
|
</Route>
|
||||||
</Route>
|
<Route path="/undelegate">
|
||||||
<Route path="/undelegate">
|
<Undelegate />
|
||||||
<Undelegate />
|
</Route>
|
||||||
</Route>
|
<Route path="/signin">
|
||||||
<Route path="/signin">
|
<SignIn />
|
||||||
<SignIn />
|
</Route>
|
||||||
</Route>
|
<Route path="*">
|
||||||
<Route path="*">
|
<NotFound />
|
||||||
<NotFound />
|
</Route>
|
||||||
</Route>
|
</Switch>
|
||||||
</Switch>
|
|
||||||
</Router>
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,43 +7,41 @@ import { theme } from '../theme'
|
|||||||
import { ClientContext } from '../context/main'
|
import { ClientContext } from '../context/main'
|
||||||
|
|
||||||
export const Receive = () => {
|
export const Receive = () => {
|
||||||
const { client } = useContext(ClientContext)
|
const { address } = useContext(ClientContext)
|
||||||
const matches = useMediaQuery('(min-width:769px)')
|
const matches = useMediaQuery('(min-width:769px)')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<Layout>
|
<Layout>
|
||||||
<>
|
<NymCard title="Receive Nym">
|
||||||
<NymCard title="Receive Nym">
|
<Grid container direction="column" spacing={1}>
|
||||||
<Grid container direction="column" spacing={1}>
|
<Grid item>
|
||||||
<Grid item>
|
<Alert severity="info">
|
||||||
<Alert severity="info">
|
You can receive tokens by providing this address to the sender
|
||||||
You can receive tokens by providing this address to the sender
|
</Alert>
|
||||||
</Alert>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Card
|
|
||||||
style={{
|
|
||||||
margin: theme.spacing(1, 0),
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
padding: theme.spacing(3),
|
|
||||||
}}
|
|
||||||
variant="outlined"
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
variant={matches ? 'h5' : 'subtitle1'}
|
|
||||||
style={{ wordBreak: 'break-word' }}
|
|
||||||
>
|
|
||||||
{client.address}
|
|
||||||
</Typography>
|
|
||||||
<CopyToClipboard text={client.address} />
|
|
||||||
</Card>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</NymCard>
|
<Grid item>
|
||||||
</>
|
<Card
|
||||||
|
style={{
|
||||||
|
margin: theme.spacing(1, 0),
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
}}
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant={matches ? 'h5' : 'subtitle1'}
|
||||||
|
style={{ wordBreak: 'break-word' }}
|
||||||
|
>
|
||||||
|
{address}
|
||||||
|
</Typography>
|
||||||
|
<CopyToClipboard text={address} />
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</NymCard>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const SendForm = ({
|
|||||||
updateRecipAddress: (address: string) => void
|
updateRecipAddress: (address: string) => void
|
||||||
updateAmount: (amount: string) => void
|
updateAmount: (amount: string) => void
|
||||||
}) => {
|
}) => {
|
||||||
const { client } = useContext(ClientContext)
|
const { address } = useContext(ClientContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
@@ -23,7 +23,7 @@ export const SendForm = ({
|
|||||||
name="sender"
|
name="sender"
|
||||||
label="Sender address"
|
label="Sender address"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={client.address}
|
value={address}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useContext, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
TextField,
|
TextField,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
@@ -14,12 +14,15 @@ import { useTheme } from '@material-ui/styles'
|
|||||||
import logo from '../images/logo.png'
|
import logo from '../images/logo.png'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
import { invoke } from '@tauri-apps/api'
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
import { ClientContext } from '../context/main'
|
||||||
|
|
||||||
export const SignIn = () => {
|
export const SignIn = () => {
|
||||||
const [mnemonic, setMnemonic] = useState<string>('')
|
const [mnemonic, setMnemonic] = useState<string>('')
|
||||||
const [inputError, setInputError] = useState<string | undefined>()
|
const [inputError, setInputError] = useState<string | undefined>()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
const { logIn } = useContext(ClientContext)
|
||||||
|
|
||||||
const theme: Theme = useTheme()
|
const theme: Theme = useTheme()
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
@@ -30,15 +33,14 @@ export const SignIn = () => {
|
|||||||
setInputError(undefined)
|
setInputError(undefined)
|
||||||
|
|
||||||
invoke('connect_with_mnemonic', { mnemonic })
|
invoke('connect_with_mnemonic', { mnemonic })
|
||||||
.then((res) => {
|
.then(() => {
|
||||||
setIsLoading(false)
|
logIn()
|
||||||
console.log(res)
|
|
||||||
history.push('/bond')
|
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
setIsLoading(false)
|
|
||||||
setInputError(e)
|
setInputError(e)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ export const theme = createTheme({
|
|||||||
containedPrimary: {
|
containedPrimary: {
|
||||||
color: 'white',
|
color: 'white',
|
||||||
},
|
},
|
||||||
text: {
|
|
||||||
padding: 'default',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
MuiStepIcon: {
|
MuiStepIcon: {
|
||||||
|
|||||||
Reference in New Issue
Block a user