react-garden
Version:
React + TypeScript + ThreeJS app using Material UI on NextJS, Apollo Client, GraphQL + WordPress REST APIs, for ThreeD web development.. a part of the threed.ai code family.
243 lines (221 loc) • 6.75 kB
JavaScript
// ** React Imports
import { useEffect, useCallback, useState } from 'react'
// ** Next Images
import Link from 'next/link'
// ** MUI Imports
import Box from '@mui/material/Box'
import Card from '@mui/material/Card'
import Grid from '@mui/material/Grid'
import { DataGrid } from '@mui/x-data-grid'
import { styled } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
// ** Icons Imports
import Laptop from 'mdi-material-ui/Laptop'
import ChartDonut from 'mdi-material-ui/ChartDonut'
import CogOutline from 'mdi-material-ui/CogOutline'
import EyeOutline from 'mdi-material-ui/EyeOutline'
import PencilOutline from 'mdi-material-ui/PencilOutline'
import AccountOutline from 'mdi-material-ui/AccountOutline'
// ** Store Imports
import { useDispatch, useSelector } from 'react-redux'
// ** Custom Components Imports
import CustomChip from '~/@core/components/mui/chip'
import CustomAvatar from '~/@core/components/mui/avatar'
// ** Utils Import
import { getInitials } from '~/@core/utils/get-initials'
// ** Actions Imports
import { fetchData } from '~/store/apps/user'
// ** Custom Components Imports
import TableHeader from '~/views/apps/roles/TableHeader'
// ** Vars
const userRoleObj = {
admin: <Laptop fontSize='small' sx={{ mr: 3, color: 'error.main' }} />,
author: <CogOutline fontSize='small' sx={{ mr: 3, color: 'warning.main' }} />,
editor: <PencilOutline fontSize='small' sx={{ mr: 3, color: 'info.main' }} />,
maintainer: <ChartDonut fontSize='small' sx={{ mr: 3, color: 'success.main' }} />,
subscriber: <AccountOutline fontSize='small' sx={{ mr: 3, color: 'primary.main' }} />
}
const userStatusObj = {
active: 'success',
pending: 'warning',
inactive: 'secondary'
}
// ** Styled component for the link for the avatar with image
const AvatarWithImageLink = styled(Link)(({ theme }) => ({
marginRight: theme.spacing(3)
}))
// ** Styled component for the link for the avatar without image
const AvatarWithoutImageLink = styled(Link)(({ theme }) => ({
textDecoration: 'none',
marginRight: theme.spacing(3)
}))
// ** renders client column
const renderClient = row => {
if (row.avatar.length) {
return (
<AvatarWithImageLink href={`/apps/user/view/${row.id}`}>
<CustomAvatar src={row.avatar} sx={{ mr: 3, width: 30, height: 30 }} />
</AvatarWithImageLink>
)
} else {
return (
<AvatarWithoutImageLink href={`/apps/user/view/${row.id}`}>
<CustomAvatar skin='light' color={row.avatarColor} sx={{ mr: 3, width: 30, height: 30, fontSize: '.875rem' }}>
{getInitials(row.fullName ? row.fullName : 'Marty McGee')}
</CustomAvatar>
</AvatarWithoutImageLink>
)
}
}
const columns = [
{
flex: 0.2,
minWidth: 230,
field: 'fullName',
headerName: 'User',
renderCell: ({ row }) => {
const { id, fullName, username } = row
return (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
{renderClient(row)}
<Box sx={{ display: 'flex', alignItems: 'flex-start', flexDirection: 'column' }}>
<Link href={`/apps/user/view/${id}`} passHref>
<Typography
noWrap
component='a'
variant='body2'
sx={{ fontWeight: 600, color: 'text.primary', textDecoration: 'none' }}
>
{fullName}
</Typography>
</Link>
<Link href={`/apps/user/view/${id}`} passHref>
<Typography noWrap component='a' variant='caption' sx={{ textDecoration: 'none' }}>
@{username}
</Typography>
</Link>
</Box>
</Box>
)
}
},
{
flex: 0.2,
minWidth: 250,
field: 'email',
headerName: 'Email',
renderCell: ({ row }) => {
return (
<Typography variant='body2' noWrap>
{row.email}
</Typography>
)
}
},
{
flex: 0.15,
field: 'role',
minWidth: 150,
headerName: 'Role',
renderCell: ({ row }) => {
return (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
{userRoleObj[row.role]}
<Typography noWrap sx={{ color: 'text.secondary', textTransform: 'capitalize' }}>
{row.role}
</Typography>
</Box>
)
}
},
{
flex: 0.15,
minWidth: 120,
headerName: 'Plan',
field: 'currentPlan',
renderCell: ({ row }) => {
return (
<Typography noWrap sx={{ textTransform: 'capitalize' }}>
{row.currentPlan}
</Typography>
)
}
},
{
flex: 0.1,
minWidth: 110,
field: 'status',
headerName: 'Status',
renderCell: ({ row }) => {
return (
<CustomChip
skin='light'
size='small'
label={row.status}
color={userStatusObj[row.status]}
sx={{ textTransform: 'capitalize' }}
/>
)
}
},
{
flex: 0.1,
minWidth: 100,
sortable: false,
field: 'actions',
headerName: 'Actions',
renderCell: ({ row }) => (
<Link href={`/apps/user/view/${row.id}`} passHref>
<IconButton>
<EyeOutline />
</IconButton>
</Link>
)
}
]
const UserList = () => {
// ** State
const [plan, setPlan] = useState('')
const [value, setValue] = useState('')
const [pageSize, setPageSize] = useState(10)
// ** Hooks
const dispatch = useDispatch()
const store = useSelector(state => state.user)
useEffect(() => {
dispatch(
fetchData({
role: '',
q: value,
status: '',
currentPlan: plan
})
)
}, [dispatch, plan, value])
const handleFilter = useCallback(val => {
setValue(val)
}, [])
const handlePlanChange = useCallback(e => {
setPlan(e.target.value)
}, [])
return (
<Grid container spacing={6}>
<Grid item xs={12}>
<Card>
<TableHeader plan={plan} value={value} handleFilter={handleFilter} handlePlanChange={handlePlanChange} />
<DataGrid
autoHeight
rows={store.data}
columns={columns}
checkboxSelection
pageSize={pageSize}
disableSelectionOnClick
rowsPerPageOptions={[10, 25, 50]}
onPageSizeChange={newPageSize => setPageSize(newPageSize)}
/>
</Card>
</Grid>
</Grid>
)
}
export default UserList