fix: clean folder

This commit is contained in:
ferdiansyah783
2025-08-07 03:53:40 +07:00
parent 5f24ec7899
commit a72a64215a
208 changed files with 174 additions and 29968 deletions
@@ -1,67 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import FormControlLabel from '@mui/material/FormControlLabel'
import Checkbox from '@mui/material/Checkbox'
import Button from '@mui/material/Button'
import FormControl from '@mui/material/FormControl'
import FormHelperText from '@mui/material/FormHelperText'
// Third-party Imports
import { useForm, Controller } from 'react-hook-form'
// Component Imports
import ConfirmationDialog from '@components/dialogs/confirmation-dialog'
const AccountDelete = () => {
// States
const [open, setOpen] = useState(false)
// Hooks
const {
control,
watch,
handleSubmit,
formState: { errors }
} = useForm({ defaultValues: { checkbox: false } })
// Vars
const checkboxValue = watch('checkbox')
const onSubmit = () => {
setOpen(true)
}
return (
<Card>
<CardHeader title='Delete Account' />
<CardContent>
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl error={Boolean(errors.checkbox)} className='is-full mbe-6'>
<Controller
name='checkbox'
control={control}
rules={{ required: true }}
render={({ field }) => (
<FormControlLabel control={<Checkbox {...field} />} label='I confirm my account deactivation' />
)}
/>
{errors.checkbox && <FormHelperText error>Please confirm you want to delete account</FormHelperText>}
</FormControl>
<Button variant='contained' color='error' type='submit' disabled={!checkboxValue}>
Deactivate Account
</Button>
<ConfirmationDialog open={open} setOpen={setOpen} type='delete-account' />
</form>
</CardContent>
</Card>
)
}
export default AccountDelete
@@ -1,300 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
import type { ChangeEvent } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
import MenuItem from '@mui/material/MenuItem'
import Chip from '@mui/material/Chip'
import type { SelectChangeEvent } from '@mui/material/Select'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
type Data = {
firstName: string
lastName: string
email: string
organization: string
phoneNumber: number | string
address: string
state: string
zipCode: string
country: string
language: string
timezone: string
currency: string
}
// Vars
const initialData: Data = {
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@example.com',
organization: 'Pixinvent',
phoneNumber: '+1 (917) 543-9876',
address: '123 Main St, New York, NY 10001',
state: 'New York',
zipCode: '634880',
country: 'usa',
language: 'english',
timezone: 'gmt-12',
currency: 'usd'
}
const languageData = ['English', 'Arabic', 'French', 'German', 'Portuguese']
const AccountDetails = () => {
// States
const [formData, setFormData] = useState<Data>(initialData)
const [fileInput, setFileInput] = useState<string>('')
const [imgSrc, setImgSrc] = useState<string>('/images/avatars/1.png')
const [language, setLanguage] = useState<string[]>(['English'])
const handleDelete = (value: string) => {
setLanguage(current => current.filter(item => item !== value))
}
const handleChange = (event: SelectChangeEvent<string[]>) => {
setLanguage(event.target.value as string[])
}
const handleFormChange = (field: keyof Data, value: Data[keyof Data]) => {
setFormData({ ...formData, [field]: value })
}
const handleFileInputChange = (file: ChangeEvent) => {
const reader = new FileReader()
const { files } = file.target as HTMLInputElement
if (files && files.length !== 0) {
reader.onload = () => setImgSrc(reader.result as string)
reader.readAsDataURL(files[0])
if (reader.result !== null) {
setFileInput(reader.result as string)
}
}
}
const handleFileInputReset = () => {
setFileInput('')
setImgSrc('/images/avatars/1.png')
}
return (
<Card>
<CardContent className='mbe-4'>
<div className='flex max-sm:flex-col items-center gap-6'>
<img height={100} width={100} className='rounded' src={imgSrc} alt='Profile' />
<div className='flex flex-grow flex-col gap-4'>
<div className='flex flex-col sm:flex-row gap-4'>
<Button component='label' variant='contained' htmlFor='account-settings-upload-image'>
Upload New Photo
<input
hidden
type='file'
value={fileInput}
accept='image/png, image/jpeg'
onChange={handleFileInputChange}
id='account-settings-upload-image'
/>
</Button>
<Button variant='tonal' color='secondary' onClick={handleFileInputReset}>
Reset
</Button>
</div>
<Typography>Allowed JPG, GIF or PNG. Max size of 800K</Typography>
</div>
</div>
</CardContent>
<CardContent>
<form onSubmit={e => e.preventDefault()}>
<Grid container spacing={6}>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='First Name'
value={formData.firstName}
placeholder='John'
onChange={e => handleFormChange('firstName', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Last Name'
value={formData.lastName}
placeholder='Doe'
onChange={e => handleFormChange('lastName', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Email'
value={formData.email}
placeholder='john.doe@gmail.com'
onChange={e => handleFormChange('email', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Organization'
value={formData.organization}
placeholder='Pixinvent'
onChange={e => handleFormChange('organization', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Phone Number'
value={formData.phoneNumber}
placeholder='+1 (234) 567-8901'
onChange={e => handleFormChange('phoneNumber', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Address'
value={formData.address}
placeholder='Address'
onChange={e => handleFormChange('address', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='State'
value={formData.state}
placeholder='New York'
onChange={e => handleFormChange('state', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
type='number'
label='Zip Code'
value={formData.zipCode}
placeholder='123456'
onChange={e => handleFormChange('zipCode', e.target.value)}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='Country'
value={formData.country}
onChange={e => handleFormChange('country', e.target.value)}
>
<MenuItem value='usa'>USA</MenuItem>
<MenuItem value='uk'>UK</MenuItem>
<MenuItem value='australia'>Australia</MenuItem>
<MenuItem value='germany'>Germany</MenuItem>
</CustomTextField>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='Language'
value={language}
slotProps={{
select: {
multiple: true, // @ts-ignore
onChange: handleChange,
renderValue: selected => (
<div className='flex flex-wrap gap-2'>
{(selected as string[]).map(value => (
<Chip
key={value}
clickable
onMouseDown={event => event.stopPropagation()}
size='small'
label={value}
onDelete={() => handleDelete(value)}
/>
))}
</div>
)
}
}}
>
{languageData.map(name => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</CustomTextField>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='TimeZone'
value={formData.timezone}
onChange={e => handleFormChange('timezone', e.target.value)}
slotProps={{
select: { MenuProps: { PaperProps: { style: { maxHeight: 250 } } } }
}}
>
<MenuItem value='gmt-12'>(GMT-12:00) International Date Line West</MenuItem>
<MenuItem value='gmt-11'>(GMT-11:00) Midway Island, Samoa</MenuItem>
<MenuItem value='gmt-10'>(GMT-10:00) Hawaii</MenuItem>
<MenuItem value='gmt-09'>(GMT-09:00) Alaska</MenuItem>
<MenuItem value='gmt-08'>(GMT-08:00) Pacific Time (US & Canada)</MenuItem>
<MenuItem value='gmt-08-baja'>(GMT-08:00) Tijuana, Baja California</MenuItem>
<MenuItem value='gmt-07'>(GMT-07:00) Chihuahua, La Paz, Mazatlan</MenuItem>
<MenuItem value='gmt-07-mt'>(GMT-07:00) Mountain Time (US & Canada)</MenuItem>
<MenuItem value='gmt-06'>(GMT-06:00) Central America</MenuItem>
<MenuItem value='gmt-06-ct'>(GMT-06:00) Central Time (US & Canada)</MenuItem>
<MenuItem value='gmt-06-mc'>(GMT-06:00) Guadalajara, Mexico City, Monterrey</MenuItem>
<MenuItem value='gmt-06-sk'>(GMT-06:00) Saskatchewan</MenuItem>
<MenuItem value='gmt-05'>(GMT-05:00) Bogota, Lima, Quito, Rio Branco</MenuItem>
<MenuItem value='gmt-05-et'>(GMT-05:00) Eastern Time (US & Canada)</MenuItem>
<MenuItem value='gmt-05-ind'>(GMT-05:00) Indiana (East)</MenuItem>
<MenuItem value='gmt-04'>(GMT-04:00) Atlantic Time (Canada)</MenuItem>
<MenuItem value='gmt-04-clp'>(GMT-04:00) Caracas, La Paz</MenuItem>
</CustomTextField>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='Currency'
value={formData.currency}
onChange={e => handleFormChange('currency', e.target.value)}
>
<MenuItem value='usd'>USD</MenuItem>
<MenuItem value='euro'>EUR</MenuItem>
<MenuItem value='pound'>Pound</MenuItem>
<MenuItem value='bitcoin'>Bitcoin</MenuItem>
</CustomTextField>
</Grid>
<Grid size={{ xs: 12 }} className='flex gap-4 flex-wrap'>
<Button variant='contained' type='submit'>
Save Changes
</Button>
<Button variant='tonal' type='reset' color='secondary' onClick={() => setFormData(initialData)}>
Reset
</Button>
</Grid>
</Grid>
</form>
</CardContent>
</Card>
)
}
export default AccountDetails
@@ -1,21 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Component Imports
import AccountDetails from './AccountDetails'
import AccountDelete from './AccountDelete'
const Account = () => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<AccountDetails />
</Grid>
<Grid size={{ xs: 12 }}>
<AccountDelete />
</Grid>
</Grid>
)
}
export default Account
@@ -1,85 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Button from '@mui/material/Button'
import MenuItem from '@mui/material/MenuItem'
import InputAdornment from '@mui/material/InputAdornment'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
const Address = () => {
// States
const [state, setState] = useState('')
return (
<Card>
<CardHeader title='Billing Address' />
<CardContent>
<form>
<Grid container spacing={6}>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField fullWidth label='Company Name' variant='outlined' placeholder='Pixinvent' />
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField fullWidth label='Billing Email' variant='outlined' placeholder='john.doe@example.com' />
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField fullWidth label='TAX ID' variant='outlined' placeholder='Enter TAX ID' />
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField fullWidth label='VAT Number' variant='outlined' placeholder='Enter VAT Number' />
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
type='number'
label='Mobile Number'
placeholder='202 555 0111'
slotProps={{
input: {
startAdornment: <InputAdornment position='start'>US (+1)</InputAdornment>
}
}}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField select fullWidth label='Country' value={state} onChange={e => setState(e.target.value)}>
<MenuItem value=''>Select Country</MenuItem>
<MenuItem value='australia'>Australia</MenuItem>
<MenuItem value='canada'>Canada</MenuItem>
<MenuItem value='france'>France</MenuItem>
<MenuItem value='united-kingdom'>United Kingdom</MenuItem>
<MenuItem value='united-states'>United States</MenuItem>
</CustomTextField>
</Grid>
<Grid size={{ xs: 12 }}>
<CustomTextField fullWidth label='Billing Address' variant='outlined' placeholder='Billing Address' />
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField fullWidth label='State' variant='outlined' placeholder='California' />
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField fullWidth type='number' label='Zip Code' variant='outlined' placeholder='231465' />
</Grid>
<Grid size={{ xs: 12 }} className='flex gap-4 flex-wrap'>
<Button variant='contained'>Save Changes</Button>
<Button variant='tonal' type='reset' color='secondary' onClick={() => setState('')}>
Discard
</Button>
</Grid>
</Grid>
</form>
</CardContent>
</Card>
)
}
export default Address
@@ -1,96 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Grid from '@mui/material/Grid2'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
import Chip from '@mui/material/Chip'
import Alert from '@mui/material/Alert'
import AlertTitle from '@mui/material/AlertTitle'
import LinearProgress from '@mui/material/LinearProgress'
import type { ButtonProps } from '@mui/material/Button'
// Type Imports
import type { PricingPlanType } from '@/types/pages/pricingTypes'
import type { ThemeColor } from '@core/types'
// Component Imports
import ConfirmationDialog from '@components/dialogs/confirmation-dialog'
import UpgradePlan from '@components/dialogs/upgrade-plan'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
const CurrentPlan = ({ data }: { data?: PricingPlanType[] }) => {
const buttonProps = (children: string, color: ThemeColor, variant: ButtonProps['variant']): ButtonProps => ({
children,
variant,
color
})
return (
<Card>
<CardHeader title='Current Plan' />
<CardContent>
<Grid container spacing={6}>
<Grid size={{ xs: 12, md: 6 }} className='flex flex-col gap-6'>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Your Current Plan is Basic
</Typography>
<Typography>A simple start for everyone</Typography>
</div>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Active until Dec 09, 2021
</Typography>
<Typography>We will send you a notification upon Subscription expiration</Typography>
</div>
<div className='flex flex-col gap-1'>
<div className='flex items-center gap-1.5'>
<Typography color='text.primary' className='font-medium'>
$199 Per Month
</Typography>
<Chip color='primary' variant='tonal' label='Popular' size='small' />
</div>
<Typography>Standard plan for small to medium businesses</Typography>
</div>
</Grid>
<Grid size={{ xs: 12, md: 6 }} className='flex flex-col gap-6'>
<Alert severity='warning'>
<AlertTitle>We need your attention!</AlertTitle>
Your plan requires update
</Alert>
<div className='flex flex-col gap-1'>
<div className='flex items-center justify-between'>
<Typography color='text.primary' className='font-medium'>
Days
</Typography>
<Typography color='text.primary' className='font-medium'>
12 of 30 Days
</Typography>
</div>
<LinearProgress variant='determinate' value={20} />
<Typography variant='body2'>18 days remaining until your plan requires update</Typography>
</div>
</Grid>
<Grid size={{ xs: 12 }} className='flex gap-4 flex-wrap'>
<OpenDialogOnElementClick
element={Button}
elementProps={buttonProps('Upgrade Plan', 'primary', 'contained')}
dialog={UpgradePlan}
dialogProps={{ data: data }}
/>
<OpenDialogOnElementClick
element={Button}
elementProps={buttonProps('Cancel Subscription', 'error', 'tonal')}
dialog={ConfirmationDialog}
dialogProps={{ type: 'unsubscribe' }}
/>
</Grid>
</Grid>
</CardContent>
</Card>
)
}
export default CurrentPlan
@@ -1,461 +0,0 @@
'use client'
// React Imports
import { useEffect, useMemo, useState } from 'react'
// Next Imports
import Link from 'next/link'
import { useParams } from 'next/navigation'
// MUI Imports
import Button from '@mui/material/Button'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Checkbox from '@mui/material/Checkbox'
import Chip from '@mui/material/Chip'
import IconButton from '@mui/material/IconButton'
import MenuItem from '@mui/material/MenuItem'
import type { TextFieldProps } from '@mui/material/TextField'
import Tooltip from '@mui/material/Tooltip'
import Typography from '@mui/material/Typography'
// Third-party Imports
import type { RankingInfo } from '@tanstack/match-sorter-utils'
import { rankItem } from '@tanstack/match-sorter-utils'
import type { ColumnDef, FilterFn } from '@tanstack/react-table'
import {
createColumnHelper,
flexRender,
getCoreRowModel,
getFacetedMinMaxValues,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from '@tanstack/react-table'
import classnames from 'classnames'
// Type Imports
import type { InvoiceType } from '@/types/apps/invoiceTypes'
import type { Locale } from '@configs/i18n'
import type { ThemeColor } from '@core/types'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import CustomTextField from '@core/components/mui/TextField'
import OptionMenu from '@core/components/option-menu'
// Util Imports
import { getInitials } from '@/utils/getInitials'
import { getLocalizedUrl } from '@/utils/i18n'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
declare module '@tanstack/table-core' {
interface FilterFns {
fuzzy: FilterFn<unknown>
}
interface FilterMeta {
itemRank: RankingInfo
}
}
type InvoiceTypeWithAction = InvoiceType & {
action?: string
}
type InvoiceStatusObj = {
[key: string]: {
icon: string
color: ThemeColor
}
}
const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
// Rank the item
const itemRank = rankItem(row.getValue(columnId), value)
// Store the itemRank info
addMeta({
itemRank
})
// Return if the item should be filtered in/out
return itemRank.passed
}
const DebouncedInput = ({
value: initialValue,
onChange,
debounce = 500,
...props
}: {
value: string | number
onChange: (value: string | number) => void
debounce?: number
} & Omit<TextFieldProps, 'onChange'>) => {
// States
const [value, setValue] = useState(initialValue)
useEffect(() => {
setValue(initialValue)
}, [initialValue])
useEffect(() => {
const timeout = setTimeout(() => {
onChange(value)
}, debounce)
return () => clearTimeout(timeout)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value])
return <CustomTextField {...props} value={value} onChange={e => setValue(e.target.value)} />
}
// Vars
const invoiceStatusObj: InvoiceStatusObj = {
Sent: { color: 'secondary', icon: 'tabler-send-2' },
Paid: { color: 'success', icon: 'tabler-check' },
Draft: { color: 'primary', icon: 'tabler-mail' },
'Partial Payment': { color: 'warning', icon: 'tabler-chart-pie-2' },
'Past Due': { color: 'error', icon: 'tabler-alert-circle' },
Downloaded: { color: 'info', icon: 'tabler-arrow-down' }
}
// Column Definitions
const columnHelper = createColumnHelper<InvoiceTypeWithAction>()
const InvoiceListTable = ({ invoiceData }: { invoiceData?: InvoiceType[] }) => {
// States
const [status, setStatus] = useState<InvoiceType['invoiceStatus']>('')
const [rowSelection, setRowSelection] = useState({})
const [data, setData] = useState(...[invoiceData])
const [filteredData, setFilteredData] = useState(data)
const [globalFilter, setGlobalFilter] = useState('')
// Hooks
const { lang: locale } = useParams()
const columns = useMemo<ColumnDef<InvoiceTypeWithAction, any>[]>(
() => [
{
id: 'select',
header: ({ table }) => (
<Checkbox
{...{
checked: table.getIsAllRowsSelected(),
indeterminate: table.getIsSomeRowsSelected(),
onChange: table.getToggleAllRowsSelectedHandler()
}}
/>
),
cell: ({ row }) => (
<Checkbox
{...{
checked: row.getIsSelected(),
disabled: !row.getCanSelect(),
indeterminate: row.getIsSomeSelected(),
onChange: row.getToggleSelectedHandler()
}}
/>
)
},
columnHelper.accessor('id', {
header: '#',
cell: ({ row }) => (
<Typography
component={Link}
href={getLocalizedUrl(`/apps/invoice/preview/${row.original.id}`, locale as Locale)}
color='primary.main'
>{`#${row.original.id}`}</Typography>
)
}),
columnHelper.accessor('invoiceStatus', {
header: 'Status',
cell: ({ row }) => (
<Tooltip
title={
<div>
<Typography variant='body2' component='span' className='text-inherit'>
{row.original.invoiceStatus}
</Typography>
<br />
<Typography variant='body2' component='span' className='text-inherit'>
Balance:
</Typography>{' '}
{row.original.balance}
<br />
<Typography variant='body2' component='span' className='text-inherit'>
Due Date:
</Typography>{' '}
{row.original.dueDate}
</div>
}
>
<CustomAvatar skin='light' color={invoiceStatusObj[row.original.invoiceStatus].color} size={28}>
<i className={classnames('bs-4 is-4', invoiceStatusObj[row.original.invoiceStatus].icon)} />
</CustomAvatar>
</Tooltip>
)
}),
columnHelper.accessor('name', {
header: 'Client',
cell: ({ row }) => (
<div className='flex items-center gap-3'>
{getAvatar({ avatar: row.original.avatar, name: row.original.name })}
<div className='flex flex-col'>
<Typography className='font-medium' color='text.primary'>
{row.original.name}
</Typography>
<Typography variant='body2'>{row.original.companyEmail}</Typography>
</div>
</div>
)
}),
columnHelper.accessor('total', {
header: 'Total',
cell: ({ row }) => <Typography>{`$${row.original.total}`}</Typography>
}),
columnHelper.accessor('issuedDate', {
header: 'Issued Date',
cell: ({ row }) => <Typography>{row.original.issuedDate}</Typography>
}),
columnHelper.accessor('balance', {
header: 'Balance',
cell: ({ row }) => {
return row.original.balance === 0 ? (
<Chip label='Paid' color='success' size='small' variant='tonal' />
) : (
<Typography color='text.primary'>{row.original.balance}</Typography>
)
}
}),
columnHelper.accessor('action', {
header: 'Action',
cell: ({ row }) => (
<div className='flex items-center'>
<IconButton onClick={() => setData(data?.filter(invoice => invoice.id !== row.original.id))}>
<i className='tabler-trash text-textSecondary' />
</IconButton>
<IconButton>
<Link
href={getLocalizedUrl(`/apps/invoice/preview/${row.original.id}`, locale as Locale)}
className='flex'
>
<i className='tabler-eye text-textSecondary' />
</Link>
</IconButton>
<OptionMenu
iconButtonProps={{ size: 'medium' }}
iconClassName='text-textSecondary'
options={[
{
text: 'Download',
icon: 'tabler-download',
menuItemProps: { className: 'flex items-center gap-2 text-textSecondary' }
},
{
text: 'Edit',
icon: 'tabler-pencil',
href: getLocalizedUrl(`/apps/invoice/edit/${row.original.id}`, locale as Locale),
linkProps: {
className: 'flex items-center is-full plb-2 pli-4 gap-2 text-textSecondary'
}
},
{
text: 'Duplicate',
icon: 'tabler-copy',
menuItemProps: { className: 'flex items-center gap-2 text-textSecondary' }
}
]}
/>
</div>
),
enableSorting: false
})
],
// eslint-disable-next-line react-hooks/exhaustive-deps
[data, filteredData]
)
const table = useReactTable({
data: filteredData as InvoiceType[],
columns,
filterFns: {
fuzzy: fuzzyFilter
},
state: {
rowSelection,
globalFilter
},
initialState: {
pagination: {
pageSize: 10
}
},
enableRowSelection: true, //enable row selection for all rows
// enableRowSelection: row => row.original.age > 18, // or enable row selection conditionally per row
globalFilterFn: fuzzyFilter,
onRowSelectionChange: setRowSelection,
getCoreRowModel: getCoreRowModel(),
onGlobalFilterChange: setGlobalFilter,
getFilteredRowModel: getFilteredRowModel(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
getFacetedMinMaxValues: getFacetedMinMaxValues()
})
const getAvatar = (params: Pick<InvoiceType, 'avatar' | 'name'>) => {
const { avatar, name } = params
if (avatar) {
return <CustomAvatar src={avatar} skin='light' size={34} />
} else {
return (
<CustomAvatar skin='light' size={34}>
{getInitials(name as string)}
</CustomAvatar>
)
}
}
useEffect(() => {
const filteredData = data?.filter(invoice => {
if (status && invoice.invoiceStatus.toLowerCase().replace(/\s+/g, '-') !== status) return false
return true
})
setFilteredData(filteredData)
}, [status, data])
return (
<Card>
<CardContent className='flex justify-between flex-col items-start md:items-center md:flex-row gap-4'>
<div className='flex items-center justify-between gap-4'>
<div className='flex items-center gap-2'>
<Typography className='hidden sm:block'>Show</Typography>
<CustomTextField
select
value={table.getState().pagination.pageSize}
onChange={e => table.setPageSize(Number(e.target.value))}
className='max-sm:is-full sm:is-[70px]'
>
<MenuItem value='10'>10</MenuItem>
<MenuItem value='25'>25</MenuItem>
<MenuItem value='50'>50</MenuItem>
</CustomTextField>
</div>
<Button
variant='contained'
component={Link}
startIcon={<i className='tabler-plus' />}
href={getLocalizedUrl('apps/invoice/add', locale as Locale)}
className='max-sm:is-full'
>
Create Invoice
</Button>
</div>
<div className='flex flex-col sm:flex-row max-sm:is-full items-start sm:items-center gap-4'>
<DebouncedInput
value={globalFilter ?? ''}
onChange={value => setGlobalFilter(String(value))}
placeholder='Search Invoice'
className='max-sm:is-full sm:is-[250px]'
/>
<CustomTextField
select
id='select-status'
value={status}
onChange={e => setStatus(e.target.value)}
className='max-sm:is-full sm:is-[160px]'
slotProps={{
select: { displayEmpty: true }
}}
>
<MenuItem value=''>Invoice Status</MenuItem>
<MenuItem value='downloaded'>Downloaded</MenuItem>
<MenuItem value='draft'>Draft</MenuItem>
<MenuItem value='paid'>Paid</MenuItem>
<MenuItem value='partial-payment'>Partial Payment</MenuItem>
<MenuItem value='past-due'>Past Due</MenuItem>
<MenuItem value='sent'>Sent</MenuItem>
</CustomTextField>
</div>
</CardContent>
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id}>
{headerGroup.headers.map(header => (
<th key={header.id}>
{header.isPlaceholder ? null : (
<>
<div
className={classnames({
'flex items-center': header.column.getIsSorted(),
'cursor-pointer select-none': header.column.getCanSort()
})}
onClick={header.column.getToggleSortingHandler()}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: <i className='tabler-chevron-up text-xl' />,
desc: <i className='tabler-chevron-down text-xl' />
}[header.column.getIsSorted() as 'asc' | 'desc'] ?? null}
</div>
</>
)}
</th>
))}
</tr>
))}
</thead>
{table.getFilteredRowModel().rows.length === 0 ? (
<tbody>
<tr>
<td colSpan={table.getVisibleFlatColumns().length} className='text-center'>
No data available
</td>
</tr>
</tbody>
) : (
<tbody>
{table
.getRowModel()
.rows.slice(0, table.getState().pagination.pageSize)
.map(row => {
return (
<tr key={row.id} className={classnames({ selected: row.getIsSelected() })}>
{row.getVisibleCells().map(cell => (
<td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
))}
</tr>
)
})}
</tbody>
)}
</table>
</div>
{/* <TablePagination
component={() => <TablePaginationComponent table={table} />}
count={table.getFilteredRowModel().rows.length}
rowsPerPage={table.getState().pagination.pageSize}
page={table.getState().pagination.pageIndex}
onPageChange={(_, page) => {
table.setPageIndex(page)
}}
onRowsPerPageChange={e => table.setPageSize(Number(e.target.value))}
/> */}
</Card>
)
}
export default InvoiceListTable
@@ -1,225 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import Chip from '@mui/material/Chip'
import Grid from '@mui/material/Grid2'
import Radio from '@mui/material/Radio'
import Switch from '@mui/material/Switch'
import Button from '@mui/material/Button'
import RadioGroup from '@mui/material/RadioGroup'
import Typography from '@mui/material/Typography'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import FormControlLabel from '@mui/material/FormControlLabel'
import type { ButtonProps } from '@mui/material/Button'
// Type Imports
import type { ThemeColor } from '@core/types'
// Component Imports
import BillingCard from '@components/dialogs/billing-card'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
import CustomTextField from '@core/components/mui/TextField'
type DataType = {
cardNumber?: string
name?: string
expiryDate?: string
cardCvv?: string
imgSrc?: string
imgAlt?: string
cardStatus?: string
badgeColor?: ThemeColor
}
// Vars
const data: DataType[] = [
{
cardCvv: '587',
name: 'Tom McBride',
expiryDate: '12/24',
imgAlt: 'Mastercard',
badgeColor: 'primary',
cardStatus: 'Primary',
cardNumber: '5577 0000 5577 9865',
imgSrc: '/images/logos/mastercard.png'
},
{
cardCvv: '681',
name: 'Mildred Wagner',
expiryDate: '02/24',
imgAlt: 'Visa card',
cardNumber: '4532 3616 2070 5678',
imgSrc: '/images/logos/visa.png'
}
]
const PaymentMethod = () => {
// States
const [paymentMethod, setPaymentMethod] = useState<'credit' | 'cod'>('credit')
const [creditCard, setCreditCard] = useState(0)
// Hooks
const [cardData, setCardData] = useState({
cardNumber: '',
name: '',
expiryDate: '',
cardCvv: ''
})
const handleReset = () => {
setCardData({
cardNumber: '',
name: '',
expiryDate: '',
cardCvv: ''
})
}
const buttonProps = (index: number): ButtonProps => ({
variant: 'tonal',
children: 'Edit',
size: 'small',
onClick: () => setCreditCard(index)
})
return (
<Card>
<CardHeader title='Payment Method' />
<CardContent>
<Grid container spacing={6}>
<Grid size={{ xs: 12, md: 6 }}>
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<RadioGroup
row
name='payment-method-radio'
value={paymentMethod}
onChange={e => setPaymentMethod(e.target.value as 'credit' | 'cod')}
className='flex gap-4'
>
<FormControlLabel value='credit' control={<Radio />} label='Credit/Debit/ATM Card' />
<FormControlLabel value='cash' control={<Radio />} label='COD/Cheque' />
</RadioGroup>
</Grid>
{paymentMethod === 'credit' ? (
<>
<Grid size={{ xs: 12 }}>
<CustomTextField
fullWidth
name='number'
autoComplete='off'
label='Card Number'
placeholder='0000 0000 0000 0000'
value={cardData.cardNumber}
onChange={e => setCardData({ ...cardData, cardNumber: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, md: 6 }}>
<CustomTextField
fullWidth
name='name'
label='Name'
autoComplete='off'
placeholder='John Doe'
value={cardData.name}
onChange={e => setCardData({ ...cardData, name: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 6, md: 3 }}>
<CustomTextField
fullWidth
name='expiry'
autoComplete='off'
label='Expiry Date'
placeholder='MM/YY'
value={cardData.expiryDate}
onChange={e => setCardData({ ...cardData, expiryDate: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 6, md: 3 }}>
<CustomTextField
fullWidth
name='cvv'
label='CVV Code'
autoComplete='off'
placeholder='654'
value={cardData.cardCvv}
onChange={e => setCardData({ ...cardData, cardCvv: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<FormControlLabel control={<Switch defaultChecked />} label='Save Card for future billing?' />
</Grid>
</>
) : (
<Grid size={{ xs: 12 }}>
<Typography>
Cash on delivery is a mode of payment where you make the payment after the goods/services are
received.
</Typography>
<Typography>
You can pay cash or make the payment via debit/credit card directly to the delivery person.
</Typography>
</Grid>
)}
<Grid size={{ xs: 12 }} className='flex gap-4 flex-wrap'>
<Button type='submit' variant='contained'>
Save Changes
</Button>
<Button type='reset' variant='tonal' color='secondary' onClick={handleReset}>
Cancel
</Button>
</Grid>
</Grid>
</Grid>
<Grid size={{ xs: 12, md: 6 }} className='flex flex-col gap-6'>
<Typography color='text.primary' className='font-medium'>
My Cards
</Typography>
{data.map((item: DataType, index: number) => (
<div
key={index}
className='flex flex-col rounded bg-actionHover sm:flex-row items-start sm:justify-between max-sm:gap-4 p-6'
>
<div className='flex flex-col items-start gap-2'>
<img src={item.imgSrc} alt={item.imgAlt} />
<div className='flex items-center gap-4'>
<Typography className='text-textPrimary font-medium'>{item.name}</Typography>
{item.cardStatus ? (
<Chip color={item.badgeColor} variant='tonal' label={item.cardStatus} size='small' />
) : null}
</div>
<Typography>
{item.cardNumber && item.cardNumber.slice(0, -4).replace(/[0-9]/g, '*') + item.cardNumber.slice(-4)}
</Typography>
</div>
<div className='flex flex-col sm:items-end gap-4'>
<div className='flex gap-4'>
<OpenDialogOnElementClick
element={Button}
elementProps={buttonProps(index)}
dialog={BillingCard}
dialogProps={{ data: data[creditCard] }}
/>
<Button variant='tonal' color='error' size='small'>
Delete
</Button>
</div>
<Typography variant='body2'>Card expires at {item.expiryDate}</Typography>
</div>
</div>
))}
</Grid>
</Grid>
</CardContent>
</Card>
)
}
export default PaymentMethod
@@ -1,65 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Component Imports
import CurrentPlan from './CurrentPlan'
import Address from './Address'
import PaymentMethod from './PaymentMethod'
import InvoiceListTable from './InvoiceListTable'
// Data Imports
import { getPricingData, getInvoiceData } from '@/app/server/actions'
/**
* ! If you need data using an API call, uncomment the below API code, update the `process.env.API_URL` variable in the
* ! `.env` file found at root of your project and also update the API endpoints like `/pages/pricing` in below example.
* ! Also, remove the above server action import and the action itself from the `src/app/server/actions.ts` file to clean up unused code
* ! because we've used the server action for getting our static data.
*/
/* const getPricingData = async () => {
// Vars
const res = await fetch(`${process.env.API_URL}/pages/pricing`)
if (!res.ok) {
throw new Error('Failed to fetch data')
}
return res.json()
} */
/* const getInvoiceData = async () => {
// Vars
const res = await fetch(`${process.env.API_URL}/apps/invoice`)
if (!res.ok) {
throw new Error('Failed to fetch invoice data')
}
return res.json()
} */
const BillingPlans = async () => {
// Vars
const data = await getPricingData()
const invoiceData = await getInvoiceData()
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CurrentPlan data={data} />
</Grid>
<Grid size={{ xs: 12 }}>
<PaymentMethod />
</Grid>
<Grid size={{ xs: 12 }}>
<Address />
</Grid>
<Grid size={{ xs: 12 }}>
<InvoiceListTable invoiceData={invoiceData} />
</Grid>
</Grid>
)
}
export default BillingPlans
@@ -1,156 +0,0 @@
// Next Imports
import Link from 'next/link'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Grid from '@mui/material/Grid2'
import Typography from '@mui/material/Typography'
import Switch from '@mui/material/Switch'
// Component Imports
import CustomIconButton from '@core/components/mui/IconButton'
type ConnectedAccountsType = {
title: string
logo: string
checked: boolean
subtitle: string
}
type SocialAccountsType = {
title: string
logo: string
username?: string
isConnected: boolean
href?: string
}
// Vars
const connectedAccountsArr: ConnectedAccountsType[] = [
{
checked: true,
title: 'Google',
logo: '/images/logos/google.png',
subtitle: 'Calendar and Contacts'
},
{
checked: false,
title: 'Slack',
logo: '/images/logos/slack.png',
subtitle: 'Communications'
},
{
checked: true,
title: 'Github',
logo: '/images/logos/github.png',
subtitle: 'Manage your Git repositories'
},
{
checked: true,
title: 'Mailchimp',
subtitle: 'Email marketing service',
logo: '/images/logos/mailchimp.png'
},
{
title: 'Asana',
checked: false,
subtitle: 'Task Communication',
logo: '/images/logos/asana.png'
}
]
const socialAccountsArr: SocialAccountsType[] = [
{
title: 'Facebook',
isConnected: false,
logo: '/images/logos/facebook.png'
},
{
title: 'Twitter',
isConnected: true,
username: '@Pixinvent',
logo: '/images/logos/twitter.png',
href: 'https://twitter.com/pixinvents'
},
{
title: 'Linkedin',
isConnected: true,
username: '@Pixinvent',
logo: '/images/logos/linkedin.png',
href: 'https://in.linkedin.com/company/pixinvent'
},
{
title: 'Dribbble',
isConnected: false,
logo: '/images/logos/dribbble.png'
},
{
title: 'Behance',
isConnected: false,
logo: '/images/logos/behance.png'
}
]
const Connections = () => {
return (
<Card>
<Grid container>
<Grid size={{ xs: 12, md: 6 }}>
<CardHeader
title='Connected Accounts'
subheader='Display content from your connected accounts on your site'
/>
<CardContent className='flex flex-col gap-4'>
{connectedAccountsArr.map((item, index) => (
<div key={index} className='flex items-center justify-between gap-4'>
<div className='flex flex-grow items-center gap-4'>
<img height={32} width={32} src={item.logo} alt={item.title} />
<div className='flex-grow'>
<Typography className='text-textPrimary font-medium'>{item.title}</Typography>
<Typography variant='body2'>{item.subtitle}</Typography>
</div>
</div>
<Switch defaultChecked={item.checked} />
</div>
))}
</CardContent>
</Grid>
<Grid size={{ xs: 12, md: 6 }}>
<CardHeader title='Social Accounts' subheader='Display content from social accounts on your site' />
<CardContent className='flex flex-col gap-4'>
{socialAccountsArr.map((item, index) => (
<div key={index} className='flex items-center justify-between gap-4'>
<div className='flex flex-grow items-center gap-4'>
<img height={32} width={32} src={item.logo} alt={item.title} />
<div className='flex-grow'>
<Typography className='text-textPrimary font-medium'>{item.title}</Typography>
{item.isConnected ? (
<Typography
variant='body2'
color='primary.main'
component={Link}
href={item.href || '/'}
target='_blank'
>
{item.username}
</Typography>
) : (
<Typography variant='body2'>Not Connected</Typography>
)}
</div>
</div>
<CustomIconButton variant='tonal' color={item.isConnected ? 'error' : 'secondary'}>
<i className={item.isConnected ? 'tabler-trash' : 'tabler-link'} />
</CustomIconButton>
</div>
))}
</CardContent>
</Grid>
</Grid>
</Card>
)
}
export default Connections
@@ -1,56 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
import type { SyntheticEvent, ReactElement } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Tab from '@mui/material/Tab'
import TabContext from '@mui/lab/TabContext'
import TabPanel from '@mui/lab/TabPanel'
// Component Imports
import CustomTabList from '@core/components/mui/TabList'
const AccountSettings = ({ tabContentList }: { tabContentList: { [key: string]: ReactElement } }) => {
// States
const [activeTab, setActiveTab] = useState('account')
const handleChange = (event: SyntheticEvent, value: string) => {
setActiveTab(value)
}
return (
<TabContext value={activeTab}>
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomTabList onChange={handleChange} variant='scrollable' pill='true'>
<Tab label='Account' icon={<i className='tabler-users' />} iconPosition='start' value='account' />
<Tab label='Security' icon={<i className='tabler-lock' />} iconPosition='start' value='security' />
<Tab
label='Billing & Plans'
icon={<i className='tabler-bookmark' />}
iconPosition='start'
value='billing-plans'
/>
<Tab
label='Notifications'
icon={<i className='tabler-bell' />}
iconPosition='start'
value='notifications'
/>
<Tab label='Connections' icon={<i className='tabler-link' />} iconPosition='start' value='connections' />
</CustomTabList>
</Grid>
<Grid size={{ xs: 12 }}>
<TabPanel value={activeTab} className='p-0'>
{tabContentList[activeTab]}
</TabPanel>
</Grid>
</Grid>
</TabContext>
)
}
export default AccountSettings
@@ -1,123 +0,0 @@
'use client'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Checkbox from '@mui/material/Checkbox'
import MenuItem from '@mui/material/MenuItem'
import Grid from '@mui/material/Grid2'
import Button from '@mui/material/Button'
// Component Imports
import Link from '@components/Link'
import Form from '@components/Form'
import CustomTextField from '@core/components/mui/TextField'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
type TableDataType = {
type: string
app: boolean
email: boolean
browser: boolean
}
// Vars
const tableData: TableDataType[] = [
{
app: true,
email: true,
browser: true,
type: 'New for you'
},
{
app: true,
email: true,
browser: true,
type: 'Account activity'
},
{
app: false,
email: true,
browser: true,
type: 'A new browser used to sign in'
},
{
app: false,
email: true,
browser: false,
type: 'A new device is linked'
}
]
const Notifications = () => {
return (
<Card>
<CardHeader
title='Recent Devices'
subheader={
<>
We need permission from your browser to show notifications.
<Link className='text-primary'> Request Permission</Link>
</>
}
/>
<Form>
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
<tr>
<th>Type</th>
<th>Email</th>
<th>Browser</th>
<th>App</th>
</tr>
</thead>
<tbody className='border-be'>
{tableData.map((data, index) => (
<tr key={index}>
<td>
<Typography color='text.primary'>{data.type}</Typography>
</td>
<td>
<Checkbox defaultChecked={data.email} />
</td>
<td>
<Checkbox defaultChecked={data.browser} />
</td>
<td>
<Checkbox defaultChecked={data.app} />
</td>
</tr>
))}
</tbody>
</table>
</div>
<CardContent>
<Typography className='mbe-6 font-medium'>When should we send you notifications?</Typography>
<Grid container spacing={6}>
<Grid size={{ xs: 12, sm: 6, md: 4 }}>
<CustomTextField select fullWidth defaultValue='online'>
<MenuItem value='online'>Only when I&#39;m online</MenuItem>
<MenuItem value='anytime'>Anytime</MenuItem>
</CustomTextField>
</Grid>
<Grid size={{ xs: 12 }} className='flex gap-4 flex-wrap'>
<Button variant='contained' type='submit'>
Save Changes
</Button>
<Button variant='tonal' color='secondary' type='reset'>
Discard
</Button>
</Grid>
</Grid>
</CardContent>
</Form>
</Card>
)
}
export default Notifications
@@ -1,70 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Chip from '@mui/material/Chip'
import IconButton from '@mui/material/IconButton'
type ApiKeyListType = {
title: string
access: string
date: string
key: string
}
// Vars
const apiKeyList: ApiKeyListType[] = [
{
title: 'Server Key 1',
access: 'Full Access',
date: '28 Apr 2021, 18:20 GTM+4:10',
key: '23eaf7f0-f4f7-495e-8b86-fad3261282ac'
},
{
title: 'Server Key 2',
access: 'Read Only',
date: '12 Feb 2021, 10:30 GTM+2:30',
key: 'bb98e571-a2e2-4de8-90a9-2e231b5e99'
},
{
title: 'Server Key 3',
access: 'Full Access',
date: '28 Dec 2021, 12:21 GTM+4:10',
key: '2e915e59-3105-47f2-8838-6e46bf83b711'
}
]
const ApiKeyList = () => {
return (
<Card>
<CardHeader title='API Key List & Access' className='pbe-4' />
<CardContent className='flex flex-col gap-6'>
<Typography>
An API key is a simple encrypted string that identifies an application without any principal. They are useful
for accessing public data anonymously, and are used to associate API requests with your project for quota and
billing.
</Typography>
{apiKeyList.map((item, index) => (
<div key={index} className='flex flex-col gap-2 p-4 rounded bg-actionHover'>
<div className='flex items-center gap-3'>
<Typography variant='h5'>{item.title}</Typography>
<Chip color='primary' variant='tonal' label={item.access} size='small' />
</div>
<div className='flex items-center gap-1'>
<Typography className='font-medium'>{item.key}</Typography>
<div className='flex'>
<IconButton size='small'>
<i className='tabler-copy text-textSecondary' />
</IconButton>
</div>
</div>
<Typography color='text.disabled'>{`Created on ${item.date}`}</Typography>
</div>
))}
</CardContent>
</Card>
)
}
export default ApiKeyList
@@ -1,136 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Grid from '@mui/material/Grid2'
import InputAdornment from '@mui/material/InputAdornment'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
//Component Imports
import CustomTextField from '@core/components/mui/TextField'
const ChangePasswordCard = () => {
// States
const [isCurrentPasswordShown, setIsCurrentPasswordShown] = useState(false)
const [isConfirmPasswordShown, setIsConfirmPasswordShown] = useState(false)
const [isNewPasswordShown, setIsNewPasswordShown] = useState(false)
const handleClickShowCurrentPassword = () => {
setIsCurrentPasswordShown(!isCurrentPasswordShown)
}
return (
<Card>
<CardHeader title='Change Password' />
<CardContent>
<form>
<Grid container spacing={6}>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Current Password'
type={isCurrentPasswordShown ? 'text' : 'password'}
placeholder='············'
slotProps={{
input: {
endAdornment: (
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={handleClickShowCurrentPassword}
onMouseDown={e => e.preventDefault()}
>
<i className={isCurrentPasswordShown ? 'tabler-eye-off' : 'tabler-eye'} />
</IconButton>
</InputAdornment>
)
}
}}
/>
</Grid>
</Grid>
<Grid container className='mbs-0' spacing={6}>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='New Password'
type={isNewPasswordShown ? 'text' : 'password'}
placeholder='············'
slotProps={{
input: {
endAdornment: (
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={() => setIsNewPasswordShown(!isNewPasswordShown)}
onMouseDown={e => e.preventDefault()}
>
<i className={isNewPasswordShown ? 'tabler-eye-off' : 'tabler-eye'} />
</IconButton>
</InputAdornment>
)
}
}}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Confirm New Password'
type={isConfirmPasswordShown ? 'text' : 'password'}
placeholder='············'
slotProps={{
input: {
endAdornment: (
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={() => setIsConfirmPasswordShown(!isConfirmPasswordShown)}
onMouseDown={e => e.preventDefault()}
>
<i className={isConfirmPasswordShown ? 'tabler-eye-off' : 'tabler-eye'} />
</IconButton>
</InputAdornment>
)
}
}}
/>
</Grid>
<Grid size={{ xs: 12 }} className='flex flex-col gap-4'>
<Typography variant='h6'>Password Requirements:</Typography>
<div className='flex flex-col gap-4'>
<div className='flex items-center gap-2.5'>
<i className='tabler-circle-filled text-[8px]' />
Minimum 8 characters long - the more, the better
</div>
<div className='flex items-center gap-2.5'>
<i className='tabler-circle-filled text-[8px]' />
At least one lowercase & one uppercase character
</div>
<div className='flex items-center gap-2.5'>
<i className='tabler-circle-filled text-[8px]' />
At least one number, symbol, or whitespace character
</div>
</div>
</Grid>
<Grid size={{ xs: 12 }} className='flex gap-4'>
<Button variant='contained'>Save Changes</Button>
<Button variant='tonal' type='reset' color='secondary'>
Reset
</Button>
</Grid>
</Grid>
</form>
</CardContent>
</Card>
)
}
export default ChangePasswordCard
@@ -1,45 +0,0 @@
'use client'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Grid from '@mui/material/Grid2'
import Button from '@mui/material/Button'
import MenuItem from '@mui/material/MenuItem'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
const CreateApiKey = () => {
return (
<Card>
<CardHeader title='Create an API Key' />
<CardContent className='!pb-0'>
<Grid container spacing={6}>
<Grid size={{ xs: 12, md: 6 }}>
<form className='flex justify-end items-end bs-full flex-col gap-5 pbe-6'>
<CustomTextField select fullWidth label='Choose the API key type you want to create' defaultValue=''>
<MenuItem value='full-control'>Full Control</MenuItem>
<MenuItem value='modify'>Modify</MenuItem>
<MenuItem value='read-execute'>Read & Execute</MenuItem>
<MenuItem value='list-folder-contents'>List Folder Contents</MenuItem>
<MenuItem value='read-only'>Read Only</MenuItem>
<MenuItem value='read-write'>Read & Write</MenuItem>
</CustomTextField>
<CustomTextField label='Name the API key' placeholder='Server key 1' fullWidth />
<Button variant='contained' fullWidth>
Create Key
</Button>
</form>
</Grid>
<Grid size={{ xs: 12, md: 6 }} className='flex items-end justify-center '>
<img src='/images/illustrations/characters/4.png' width={197} height={224} alt='api illustration' />
</Grid>
</Grid>
</CardContent>
</Card>
)
}
export default CreateApiKey
@@ -1,109 +0,0 @@
// React Imports
import type { ReactElement } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import Typography from '@mui/material/Typography'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
type RecentDeviceDataType = {
browserIcon: ReactElement
browserName: string
device: string
location: string
date: string
}
// Vars
const recentDeviceData: RecentDeviceDataType[] = [
{
location: 'Switzerland',
device: 'HP Spectre 360',
date: '10, Sept 20:07',
browserName: 'Chrome on Windows',
browserIcon: <i className='tabler-brand-windows text-[22px] text-info' />
},
{
location: 'Los Angeles, CA',
device: 'Google Pixel 3a',
date: '20 Apr 2022, 10:20',
browserName: 'Chrome on Android',
browserIcon: <i className='tabler-brand-android text-[22px] text-success' />
},
{
location: 'San Francisco, CA',
device: 'iPhone 12x',
date: '16 Apr 2022, 04:20',
browserName: 'Chrome on iPhone',
browserIcon: <i className='tabler-device-mobile text-[22px] text-error' />
},
{
location: 'India',
device: 'Apple iMac',
date: '28 Apr 2022, 18:20',
browserName: 'Chrome on MacOS',
browserIcon: <i className='tabler-brand-apple text-[22px] text-secondary' />
},
{
location: 'Switzerland',
device: 'Macbook Pro',
date: '20 Apr 2022, 10:20',
browserName: 'Chrome on Windows',
browserIcon: <i className='tabler-brand-apple text-[22px] text-warning' />
},
{
location: 'Dubai',
device: 'Oneplus 9 Pro',
date: '16 Apr 2022, 04:20',
browserName: 'Chrome on Android',
browserIcon: <i className='tabler-brand-android text-[22px] text-success' />
}
]
const RecentDevicesTable = () => {
return (
<Card>
<CardHeader title='Recent Devices' />
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
<tr>
<th>Browser</th>
<th>Device</th>
<th>Location</th>
<th>Recent Activities</th>
</tr>
</thead>
<tbody>
{recentDeviceData.map((device, index) => (
<tr key={index}>
<td>
<div className='flex items-center gap-2.5'>
{device.browserIcon}
<Typography className='font-medium' color='text.primary'>
{device.browserName}
</Typography>
</div>
</td>
<td>
<Typography>{device.device}</Typography>
</td>
<td>
<Typography>{device.location}</Typography>
</td>
<td>
<Typography>{device.date}</Typography>
</td>
</tr>
))}
</tbody>
</table>
</div>
</Card>
)
}
export default RecentDevicesTable
@@ -1,45 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import Button from '@mui/material/Button'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import type { ButtonProps } from '@mui/material/Button'
// Type Imports
import Link from '@components/Link'
// Component Imports
import TwoFactorAuth from '@components/dialogs/two-factor-auth'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
const TwoFactorAuthenticationCard = () => {
// Vars
const buttonProps: ButtonProps = {
variant: 'contained',
children: 'Enable two-factor authentication'
}
return (
<>
<Card>
<CardHeader title='Two-steps verification' />
<CardContent className='flex flex-col items-start gap-6'>
<div className='flex flex-col gap-4'>
<Typography variant='h5' color='text.secondary'>
Two factor authentication is not enabled yet.
</Typography>
<Typography>
Two-factor authentication adds an additional layer of security to your account by requiring more than just
a password to log in.
<Link className='text-primary'>Learn more.</Link>
</Typography>
</div>
<OpenDialogOnElementClick element={Button} elementProps={buttonProps} dialog={TwoFactorAuth} />
</CardContent>
</Card>
</>
)
}
export default TwoFactorAuthenticationCard
@@ -1,33 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Component Imports
import ChangePasswordCard from './ChangePasswordCard'
import TwoFactorAuthenticationCard from './TwoFactorAuthenticationCard'
import CreateApiKey from './CreateApiKey'
import ApiKeyList from './ApiKeyList'
import RecentDevicesTable from './RecentDevicesTable'
const Security = () => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<ChangePasswordCard />
</Grid>
<Grid size={{ xs: 12 }}>
<TwoFactorAuthenticationCard />
</Grid>
<Grid size={{ xs: 12 }}>
<CreateApiKey />
</Grid>
<Grid size={{ xs: 12 }}>
<ApiKeyList />
</Grid>
<Grid size={{ xs: 12 }}>
<RecentDevicesTable />
</Grid>
</Grid>
)
}
export default Security
-48
View File
@@ -1,48 +0,0 @@
// MUI Imports
import Chip from '@mui/material/Chip'
import Grid from '@mui/material/Grid2'
import Typography from '@mui/material/Typography'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
const FaqFooter = () => {
return (
<>
<div className='flex justify-center items-center flex-col text-center gap-2 plb-6'>
<Chip label='Question' color='primary' variant='tonal' size='small' />
<Typography variant='h4'>You still have a question?</Typography>
<Typography>
If you cannot find a question in our FAQ, you can always contact us. We will answer you shortly!
</Typography>
</div>
<Grid container spacing={6} className='mbs-6'>
<Grid size={{ xs: 12, md: 6 }}>
<div className='flex justify-center items-center flex-col gap-4 p-6 rounded bg-actionHover'>
<CustomAvatar variant='rounded' color='primary' skin='light' size={46}>
<i className='tabler-phone text-[26px]' />
</CustomAvatar>
<div className='flex items-center flex-col gap-1'>
<Typography variant='h5'>+ (810) 2548 2568</Typography>
<Typography>We are always happy to help!</Typography>
</div>
</div>
</Grid>
<Grid size={{ xs: 12, md: 6 }}>
<div className='flex justify-center items-center flex-col gap-4 p-6 rounded bg-actionHover'>
<CustomAvatar variant='rounded' color='primary' skin='light' size={46}>
<i className='tabler-mail text-[26px]' />
</CustomAvatar>
<div className='flex items-center flex-col gap-1'>
<Typography variant='h5'>hello@help.com</Typography>
<Typography>Best way to get answer faster!</Typography>
</div>
</div>
</Grid>
</Grid>
</>
)
}
export default FaqFooter
-60
View File
@@ -1,60 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import Typography from '@mui/material/Typography'
import CardContent from '@mui/material/CardContent'
import InputAdornment from '@mui/material/InputAdornment'
import { styled } from '@mui/material/styles'
import type { TextFieldProps } from '@mui/material/TextField'
// Third-party Imports
import classnames from 'classnames'
// Styles imports
import styles from './styles.module.css'
import CustomTextField from '@core/components/mui/TextField'
// Styled CustomTextField component
const CustomTextFieldStyled = styled(CustomTextField)<TextFieldProps>(({ theme }) => ({
'& .MuiInputBase-root.MuiFilledInput-root': {
width: '100%',
backgroundColor: 'var(--mui-palette-background-paper) !important'
},
[theme.breakpoints.up('sm')]: {
width: '55%'
}
}))
type Props = {
searchValue: string
setSearchValue: (value: string) => void
}
const FaqHeader = ({ searchValue, setSearchValue }: Props) => {
return (
<Card className={classnames('shadow-none bg-transparent bg-cover', styles.bgImage)} elevation={0}>
<CardContent className='flex flex-col items-center is-full text-center !plb-[5.8125rem] pli-5'>
<Typography variant='h4' className='mbe-2.5'>
Hello, how can we help?
</Typography>
<Typography className='mbe-4'>or choose a category to quickly find the help you need</Typography>
<CustomTextFieldStyled
className='is-full sm:max-is-[55%] md:max-is-[600px]'
placeholder='search articles...'
value={searchValue}
onChange={e => setSearchValue(e.target.value)}
slotProps={{
input: {
startAdornment: (
<InputAdornment position='start'>
<i className='tabler-search' />
</InputAdornment>
)
}
}}
/>
</CardContent>
</Card>
)
}
export default FaqHeader
-122
View File
@@ -1,122 +0,0 @@
// React Imports
import { useMemo, useState } from 'react'
import type { SyntheticEvent } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Tab from '@mui/material/Tab'
import TabPanel from '@mui/lab/TabPanel'
import TabContext from '@mui/lab/TabContext'
import Accordion from '@mui/material/Accordion'
import Typography from '@mui/material/Typography'
import AccordionSummary from '@mui/material/AccordionSummary'
import AccordionDetails from '@mui/material/AccordionDetails'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { FaqType } from '@/types/pages/faqTypes'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import CustomTabList from '@core/components/mui/TabList'
type props = {
faqData?: FaqType[]
searchValue: string
}
const FAQ = ({ faqData, searchValue }: props) => {
// States
const [activeTab, setActiveTab] = useState('payment')
// Hooks
const filteredData = useMemo(() => {
let returnVal = faqData
if (searchValue) {
returnVal =
faqData
?.filter(category =>
category.questionsAnswers.some(item => item.question.toLowerCase().includes(searchValue.toLowerCase()))
)
.map(category => ({
...category,
questionsAnswers: category.questionsAnswers.filter(item =>
item.question.toLowerCase().includes(searchValue.toLowerCase())
)
})) ?? []
}
setActiveTab(returnVal?.[0]?.id ?? '')
return returnVal
}, [faqData, searchValue])
const handleChange = (event: SyntheticEvent, newValue: string) => {
setActiveTab(newValue)
}
return filteredData && filteredData.length > 0 ? (
<TabContext value={activeTab}>
<Grid container spacing={6}>
<Grid size={{ xs: 12, sm: 5, md: 4, xl: 3 }} className='flex flex-col items-center gap-4'>
<CustomTabList orientation='vertical' onChange={handleChange} className='is-full' pill='true'>
{filteredData?.map((faq, index) => (
<Tab
key={index}
label={faq.title}
value={faq.id}
icon={<i className={classnames(faq.icon, '!mbe-0 mie-1.5')} />}
className='flex-row justify-start !min-is-full'
/>
))}
</CustomTabList>
<img
src='/images/illustrations/characters-with-objects/1.png'
className='max-md:hidden is-[230px]'
alt='john image'
/>
</Grid>
<Grid size={{ xs: 12, sm: 7, md: 8, xl: 9 }}>
{filteredData?.map((faq, index) => (
<TabPanel key={index} value={faq.id} className='p-0'>
<div className='flex items-center gap-4 mbe-4'>
<CustomAvatar skin='light' color='primary' variant='rounded' size={50}>
<i className={classnames(faq.icon, 'text-3xl')} />
</CustomAvatar>
<div>
<Typography variant='h5'>{faq.title}</Typography>
<Typography>{faq.subtitle}</Typography>
</div>
</div>
<div>
{faq.questionsAnswers.map((items, index) => (
<Accordion key={index}>
<AccordionSummary
expandIcon={<i className='tabler-chevron-right' />}
aria-controls='panel1a-content'
>
<Typography>{items.question}</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>{items.answer}</Typography>
</AccordionDetails>
</Accordion>
))}
</div>
</TabPanel>
))}
</Grid>
</Grid>
</TabContext>
) : (
<div className='flex justify-center items-center'>
<i className='tabler-alert-circle' />
<Typography>No results found</Typography>
</div>
)
}
export default FAQ
-36
View File
@@ -1,36 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
// Type Imports
import type { FaqType } from '@/types/pages/faqTypes'
// Component Imports
import FaqHeader from '@views/pages/faq/FaqHeader'
import Faqs from '@views/pages/faq/Faqs'
import FaqFooter from '@views/pages/faq/FaqFooter'
const FAQ = ({ data }: { data?: FaqType[] }) => {
// States
const [searchValue, setSearchValue] = useState('')
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<FaqHeader searchValue={searchValue} setSearchValue={setSearchValue} />
</Grid>
<Grid size={{ xs: 12 }}>
<Faqs faqData={data} searchValue={searchValue} />
</Grid>
<Grid size={{ xs: 12 }}>
<FaqFooter />
</Grid>
</Grid>
)
}
export default FAQ
-3
View File
@@ -1,3 +0,0 @@
.bgImage {
background: url('/images/pages/faq-header.png');
}
-23
View File
@@ -1,23 +0,0 @@
'use client'
// MUI Imports
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
// Type Imports
import type { PricingPlanType } from '@/types/pages/pricingTypes'
// Component Imports
import Pricing from '@components/pricing'
const PricingPage = ({ data }: { data?: PricingPlanType[] }) => {
return (
<Card>
<CardContent className='xl:!plb-16 xl:pli-[6.25rem] pbs-10 pbe-5 pli-5 sm:p-16'>
<Pricing data={data} />
</CardContent>
</Card>
)
}
export default PricingPage
@@ -1,47 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardMedia from '@mui/material/CardMedia'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
// Type Imports
import type { ProfileHeaderType } from '@/types/pages/profileTypes'
const UserProfileHeader = ({ data }: { data?: ProfileHeaderType }) => {
return (
<Card>
<CardMedia image={data?.coverImg} className='bs-[250px]' />
<CardContent className='flex gap-5 justify-center flex-col items-center md:items-end md:flex-row !pt-0 md:justify-start'>
<div className='flex rounded-bs-md mbs-[-40px] border-[5px] mis-[-5px] border-be-0 border-backgroundPaper bg-backgroundPaper'>
<img height={120} width={120} src={data?.profileImg} className='rounded' alt='Profile Background' />
</div>
<div className='flex is-full justify-start self-end flex-col items-center gap-6 sm-gap-0 sm:flex-row sm:justify-between sm:items-end '>
<div className='flex flex-col items-center sm:items-start gap-2'>
<Typography variant='h4'>{data?.fullName}</Typography>
<div className='flex flex-wrap gap-6 justify-center sm:justify-normal'>
<div className='flex items-center gap-2'>
{data?.designationIcon && <i className={data?.designationIcon} />}
<Typography className='font-medium'>{data?.designation}</Typography>
</div>
<div className='flex items-center gap-2'>
<i className='tabler-map-pin' />
<Typography className='font-medium'>{data?.location}</Typography>
</div>
<div className='flex items-center gap-2'>
<i className='tabler-calendar' />
<Typography className='font-medium'>{data?.joiningDate}</Typography>
</div>
</div>
</div>
<Button variant='contained' className='flex gap-2'>
<i className='tabler-user-check !text-base'></i>
<span>Connected</span>
</Button>
</div>
</CardContent>
</Card>
)
}
export default UserProfileHeader
@@ -1,86 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Avatar from '@mui/material/Avatar'
import Chip from '@mui/material/Chip'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
// Type Imports
import type { ConnectionsTabType } from '@/types/pages/profileTypes'
// Component Imports
import OptionMenu from '@core/components/option-menu'
import Link from '@components/Link'
import CustomIconButton from '@core/components/mui/IconButton'
const Connections = ({ data }: { data?: ConnectionsTabType[] }) => {
return (
<Grid container spacing={6}>
{data &&
data.map((item, index) => {
return (
<Grid size={{ xs: 12, sm: 6, md: 4 }} key={index}>
<Card className='relative'>
<OptionMenu
iconClassName='text-textDisabled'
options={[
'Share Connection',
'Block Connection',
{ divider: true },
{
text: 'Delete',
menuItemProps: { className: 'text-error hover:bg-[var(--mui-palette-error-lightOpacity)]' }
}
]}
iconButtonProps={{ className: 'absolute top-6 end-5 text-textDisabled' }}
/>
<CardContent className='flex items-center flex-col gap-6'>
<Avatar src={item.avatar} className='!mbs-5 bs-[100px] is-[100px]' />
<div className='flex flex-col items-center'>
<Typography variant='h5'>{item.name}</Typography>
<Typography>{item.designation}</Typography>
</div>
<div className='flex items-center gap-4'>
{item.chips.map((chip, index) => (
<Link key={index}>
<Chip variant='tonal' label={chip.title} color={chip.color} size='small' />
</Link>
))}
</div>
<div className='flex is-full items-center justify-around flex-wrap'>
<div className='flex items-center flex-col'>
<Typography variant='h5'>{item.projects}</Typography>
<Typography>Projects</Typography>
</div>
<div className='flex items-center flex-col'>
<Typography variant='h5'>{item.tasks}</Typography>
<Typography>Tasks</Typography>
</div>
<div className='flex items-center flex-col'>
<Typography variant='h5'>{item.connections}</Typography>
<Typography>Connections</Typography>
</div>
</div>
<div className='flex items-center gap-4'>
<Button
variant={item.isConnected ? 'contained' : 'tonal'}
startIcon={<i className={item.isConnected ? 'tabler-user-check' : 'tabler-user-plus'} />}
>
{item.isConnected ? 'Connected' : 'Connect'}
</Button>
<CustomIconButton variant='tonal' color='secondary'>
<i className='tabler-mail' />
</CustomIconButton>
</div>
</CardContent>
</Card>
</Grid>
)
})}
</Grid>
)
}
export default Connections
-85
View File
@@ -1,85 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
import type { ReactElement, SyntheticEvent } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Tab from '@mui/material/Tab'
import TabContext from '@mui/lab/TabContext'
import TabPanel from '@mui/lab/TabPanel'
// Type Imports
import type { Data } from '@/types/pages/profileTypes'
// Component Imports
import UserProfileHeader from './UserProfileHeader'
import CustomTabList from '@core/components/mui/TabList'
const UserProfile = ({ tabContentList, data }: { tabContentList: { [key: string]: ReactElement }; data?: Data }) => {
// States
const [activeTab, setActiveTab] = useState('profile')
const handleChange = (event: SyntheticEvent, value: string) => {
setActiveTab(value)
}
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<UserProfileHeader data={data?.profileHeader} />
</Grid>
{activeTab === undefined ? null : (
<Grid size={{ xs: 12 }} className='flex flex-col gap-6'>
<TabContext value={activeTab}>
<CustomTabList onChange={handleChange} variant='scrollable' pill='true'>
<Tab
label={
<div className='flex items-center gap-1.5'>
<i className='tabler-user-check text-lg' />
Profile
</div>
}
value='profile'
/>
<Tab
label={
<div className='flex items-center gap-1.5'>
<i className='tabler-users text-lg' />
Teams
</div>
}
value='teams'
/>
<Tab
label={
<div className='flex items-center gap-1.5'>
<i className='tabler-layout-grid text-lg' />
Projects
</div>
}
value='projects'
/>
<Tab
label={
<div className='flex items-center gap-1.5'>
<i className='tabler-link text-lg' />
Connections
</div>
}
value='connections'
/>
</CustomTabList>
<TabPanel value={activeTab} className='p-0'>
{tabContentList[activeTab]}
</TabPanel>
</TabContext>
</Grid>
)}
</Grid>
)
}
export default UserProfile
@@ -1,88 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Card from '@mui/material/Card'
import Typography from '@mui/material/Typography'
import CardContent from '@mui/material/CardContent'
// Type Imports
import type { ProfileTeamsType, ProfileCommonType, ProfileTabType } from '@/types/pages/profileTypes'
const renderList = (list: ProfileCommonType[]) => {
return (
list.length > 0 &&
list.map((item, index) => {
return (
<div key={index} className='flex items-center gap-2'>
<i className={item.icon} />
<div className='flex items-center flex-wrap gap-2'>
<Typography className='font-medium'>
{`${item.property.charAt(0).toUpperCase() + item.property.slice(1)}:`}
</Typography>
<Typography> {item.value.charAt(0).toUpperCase() + item.value.slice(1)}</Typography>
</div>
</div>
)
})
)
}
const renderTeams = (teams: ProfileTeamsType[]) => {
return (
teams.length > 0 &&
teams.map((item, index) => {
return (
<div key={index} className='flex items-center flex-wrap gap-2'>
<Typography className='font-medium'>
{item.property.charAt(0).toUpperCase() + item.property.slice(1)}
</Typography>
<Typography>{item.value.charAt(0).toUpperCase() + item.value.slice(1)}</Typography>
</div>
)
})
)
}
const AboutOverview = ({ data }: { data?: ProfileTabType }) => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<Card>
<CardContent className='flex flex-col gap-6'>
<div className='flex flex-col gap-4'>
<Typography className='uppercase' variant='body2' color='text.disabled'>
About
</Typography>
{data?.about && renderList(data?.about)}
</div>
<div className='flex flex-col gap-4'>
<Typography className='uppercase' variant='body2' color='text.disabled'>
Contacts
</Typography>
{data?.contacts && renderList(data?.contacts)}
</div>
<div className='flex flex-col gap-4'>
<Typography className='uppercase' variant='body2' color='text.disabled'>
Teams
</Typography>
{data?.teams && renderTeams(data?.teams)}
</div>
</CardContent>
</Card>
</Grid>
<Grid size={{ xs: 12 }}>
<Card>
<CardContent className='flex flex-col gap-6'>
<div className='flex flex-col gap-4'>
<Typography className='uppercase' variant='body2' color='text.disabled'>
Overview
</Typography>
{data?.overview && renderList(data?.overview)}
</div>
</CardContent>
</Card>
</Grid>
</Grid>
)
}
export default AboutOverview
@@ -1,106 +0,0 @@
'use client'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import TimelineItem from '@mui/lab/TimelineItem'
import TimelineSeparator from '@mui/lab/TimelineSeparator'
import TimelineConnector from '@mui/lab/TimelineConnector'
import TimelineContent from '@mui/lab/TimelineContent'
import TimelineDot from '@mui/lab/TimelineDot'
import Avatar from '@mui/material/Avatar'
import AvatarGroup from '@mui/material/AvatarGroup'
import { styled } from '@mui/material/styles'
import MuiTimeline from '@mui/lab/Timeline'
import type { TimelineProps } from '@mui/lab/Timeline'
//Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
// Styled Components
const Timeline = styled(MuiTimeline)<TimelineProps>({
'& .MuiTimelineItem-root': {
'&:before': {
display: 'none'
}
}
})
const ActivityTimeline = () => {
return (
<Card>
<CardHeader
title='Activity Timeline'
avatar={<i className='tabler-chart-bar text-textSecondary' />}
titleTypographyProps={{ variant: 'h5' }}
/>
<CardContent>
<Timeline>
<TimelineItem>
<TimelineSeparator>
<TimelineDot color='primary' />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<div className='flex items-center justify-between flex-wrap gap-x-4 pbe-[7px]'>
<Typography className='text-textPrimary font-medium'>12 Invoices have been paid</Typography>
<Typography variant='caption'>12 min ago</Typography>
</div>
<Typography className='mbe-2'>Invoices have been paid to the company.</Typography>
<div className='flex'>
<div className='flex gap-2.5 items-center pli-2.5 bg-actionHover plb-[0.3125rem] rounded'>
<img alt='invoice.pdf' src='/images/icons/pdf-document.png' className='bs-5' />
<Typography className='font-medium'>invoice.pdf</Typography>
</div>
</div>
</TimelineContent>
</TimelineItem>
<TimelineItem>
<TimelineSeparator>
<TimelineDot color='success' />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<div className='flex items-center justify-between flex-wrap gap-x-4 pbe-[7px]'>
<Typography className='text-textPrimary font-medium'>Client Meeting</Typography>
<Typography variant='caption'>45 min ago</Typography>
</div>
<Typography className='mbe-2'>Project meeting with john @10:15am</Typography>
<div className='flex items-center gap-2.5'>
<CustomAvatar src='/images/avatars/1.png' size={32} />
<div>
<Typography className='font-medium' variant='body2'>
Lester McCarthy (Client)
</Typography>
<Typography variant='body2'>CEO of Pixinvent</Typography>
</div>
</div>
</TimelineContent>
</TimelineItem>
<TimelineItem>
<TimelineSeparator>
<TimelineDot color='info' />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<div className='flex items-center justify-between flex-wrap gap-x-4 pbe-[7px]'>
<Typography className='text-textPrimary font-medium'>Create a new project for client</Typography>
<Typography variant='caption'>2 Day Ago</Typography>
</div>
<Typography className='mbe-2'>6 team members in a project</Typography>
<AvatarGroup total={6}>
<Avatar alt='Remy Sharp' src='/images/avatars/1.png' />
<Avatar alt='Travis Howard' src='/images/avatars/2.png' />
<Avatar alt='Cindy Baker' src='/images/avatars/3.png' />
</AvatarGroup>
</TimelineContent>
</TimelineItem>
</Timeline>
</CardContent>
</Card>
)
}
export default ActivityTimeline
@@ -1,96 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import CardActions from '@mui/material/CardActions'
import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid2'
import Chip from '@mui/material/Chip'
// Type Imports
import type { ProfileTeamsTechType, ProfileConnectionsType } from '@/types/pages/profileTypes'
// Component Imports
import OptionMenu from '@core/components/option-menu'
import CustomAvatar from '@core/components/mui/Avatar'
import CustomIconButton from '@core/components/mui/IconButton'
import Link from '@components/Link'
type Props = {
teamsTech?: ProfileTeamsTechType[]
connections?: ProfileConnectionsType[]
}
const ConnectionsTeams = (props: Props) => {
// props
const { teamsTech, connections } = props
return (
<>
<Grid size={{ xs: 12, md: 6 }}>
<Card>
<CardHeader
title='Connections'
action={<OptionMenu options={['Share Connections', 'Suggest Edits', { divider: true }, 'Report Bug']} />}
/>
<CardContent className='flex flex-col gap-4'>
{connections &&
connections.map((connection, index) => (
<div key={index} className='flex items-center gap-2'>
<div className='flex items-center flex-grow gap-2'>
<CustomAvatar src={connection.avatar} size={38} />
<div className='flex flex-grow flex-col'>
<Typography className='font-medium' color='text.primary'>
{connection.name}
</Typography>
<Typography variant='body2'>{connection.connections} Connections</Typography>
</div>
</div>
<CustomIconButton color='primary' variant={connection.isFriend ? 'tonal' : 'contained'}>
<i className={connection.isFriend ? 'tabler-user-check' : 'tabler-user-x'} />
</CustomIconButton>
</div>
))}
</CardContent>
<CardActions className='flex justify-center'>
<Typography component={Link} color='primary.main'>
View all connections
</Typography>
</CardActions>
</Card>
</Grid>
<Grid size={{ xs: 12, md: 6 }}>
<Card>
<CardHeader
title='Teams'
action={<OptionMenu options={['Share Teams', 'Suggest Edits', { divider: true }, 'Report Bug']} />}
/>
<CardContent className='flex flex-col gap-4'>
{teamsTech &&
teamsTech.map((team: ProfileTeamsTechType, index) => (
<div key={index} className='flex'>
<div className='flex flex-grow items-center gap-2'>
<CustomAvatar src={team.avatar} size={38} />
<div className='flex flex-grow flex-col'>
<Typography className='font-medium' color='text.primary'>
{team.title}
</Typography>
<Typography variant='body2'>{team.members} Members</Typography>
</div>
</div>
<Chip color={team.ChipColor} label={team.chipText} size='small' variant='tonal' />
</div>
))}
</CardContent>
<CardActions className='flex justify-center'>
<Typography component={Link} color='primary.main'>
View all teams
</Typography>
</CardActions>
</Card>
</Grid>
</>
)
}
export default ConnectionsTeams
@@ -1,289 +0,0 @@
'use client'
// React Imports
import { useEffect, useMemo, useState } from 'react'
// MUI Imports
import AvatarGroup from '@mui/material/AvatarGroup'
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import Checkbox from '@mui/material/Checkbox'
import LinearProgress from '@mui/material/LinearProgress'
import type { TextFieldProps } from '@mui/material/TextField'
import Typography from '@mui/material/Typography'
// Third-party Imports
import type { RankingInfo } from '@tanstack/match-sorter-utils'
import { rankItem } from '@tanstack/match-sorter-utils'
import type { ColumnDef, FilterFn } from '@tanstack/react-table'
import {
createColumnHelper,
flexRender,
getCoreRowModel,
getFacetedMinMaxValues,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from '@tanstack/react-table'
import classnames from 'classnames'
// Type Imports
import type { ProjectTableRowType } from '@/types/pages/profileTypes'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import CustomTextField from '@core/components/mui/TextField'
import OptionMenu from '@core/components/option-menu'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
declare module '@tanstack/table-core' {
interface FilterFns {
fuzzy: FilterFn<unknown>
}
interface FilterMeta {
itemRank: RankingInfo
}
}
const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
// Rank the item
const itemRank = rankItem(row.getValue(columnId), value)
// Store the itemRank info
addMeta({
itemRank
})
// Return if the item should be filtered in/out
return itemRank.passed
}
const DebouncedInput = ({
value: initialValue,
onChange,
debounce = 500,
...props
}: {
value: string | number
onChange: (value: string | number) => void
debounce?: number
} & Omit<TextFieldProps, 'onChange'>) => {
// States
const [value, setValue] = useState(initialValue)
useEffect(() => {
setValue(initialValue)
}, [initialValue])
useEffect(() => {
const timeout = setTimeout(() => {
onChange(value)
}, debounce)
return () => clearTimeout(timeout)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value])
return <CustomTextField {...props} value={value} onChange={e => setValue(e.target.value)} />
}
// Column Definitions
const columnHelper = createColumnHelper<ProjectTableRowType>()
const ProjectTables = ({ projectTable }: { projectTable?: ProjectTableRowType[] }) => {
// States
const [rowSelection, setRowSelection] = useState({})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [data, setData] = useState(...[projectTable])
const [globalFilter, setGlobalFilter] = useState('')
// Hooks
const columns = useMemo<ColumnDef<ProjectTableRowType, any>[]>(
() => [
{
id: 'select',
header: ({ table }) => (
<Checkbox
{...{
checked: table.getIsAllRowsSelected(),
indeterminate: table.getIsSomeRowsSelected(),
onChange: table.getToggleAllRowsSelectedHandler()
}}
/>
),
cell: ({ row }) => (
<Checkbox
{...{
checked: row.getIsSelected(),
disabled: !row.getCanSelect(),
indeterminate: row.getIsSomeSelected(),
onChange: row.getToggleSelectedHandler()
}}
/>
)
},
columnHelper.accessor('title', {
header: 'Project',
cell: ({ row }) => (
<div className='flex items-center gap-3'>
<CustomAvatar src={row.original.avatar} size={34} />
<div className='flex flex-col'>
<Typography className='font-medium' color='text.primary'>
{row.original.title}
</Typography>
<Typography variant='body2'>{row.original.subtitle}</Typography>
</div>
</div>
)
}),
columnHelper.accessor('leader', {
header: 'Leader',
cell: ({ row }) => <Typography color='text.primary'>{row.original.leader}</Typography>
}),
columnHelper.accessor('avatarGroup', {
header: 'Team',
cell: ({ row }) => (
<AvatarGroup max={4} className='flex items-center pull-up'>
{row.original.avatarGroup.map((avatar, index) => (
<CustomAvatar key={index} src={avatar} size={26} />
))}
</AvatarGroup>
),
enableSorting: false
}),
columnHelper.accessor('status', {
header: 'Progress',
cell: ({ row }) => (
<div className='flex items-center gap-3'>
<LinearProgress color='primary' value={row.original.status} variant='determinate' className='is-20' />
<Typography color='text.primary'>{`${row.original.status}%`}</Typography>
</div>
)
}),
columnHelper.accessor('actions', {
header: 'Actions',
cell: () => (
<OptionMenu
iconButtonProps={{ size: 'medium' }}
iconClassName='text-textSecondary'
options={[
'Details',
'Archive',
{ divider: true },
{ text: 'Delete', menuItemProps: { className: 'text-error' } }
]}
/>
),
enableSorting: false
})
],
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
)
const table = useReactTable({
data: data as ProjectTableRowType[],
columns,
filterFns: {
fuzzy: fuzzyFilter
},
state: {
rowSelection,
globalFilter
},
initialState: {
pagination: {
pageSize: 7
}
},
enableRowSelection: true, //enable row selection for all rows
// enableRowSelection: row => row.original.age > 18, // or enable row selection conditionally per row
globalFilterFn: fuzzyFilter,
onRowSelectionChange: setRowSelection,
getCoreRowModel: getCoreRowModel(),
onGlobalFilterChange: setGlobalFilter,
getFilteredRowModel: getFilteredRowModel(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
getFacetedMinMaxValues: getFacetedMinMaxValues()
})
return (
<Card>
<CardHeader
className='flex-wrap gap-x-4 gap-y-2'
title='Project List'
action={
<DebouncedInput
value={globalFilter ?? ''}
onChange={value => setGlobalFilter(String(value))}
placeholder='Search Project'
/>
}
/>
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id}>
{headerGroup.headers.map(header => (
<th key={header.id}>
{header.isPlaceholder ? null : (
<div
className={classnames({
'flex items-center': header.column.getIsSorted(),
'cursor-pointer select-none': header.column.getCanSort()
})}
onClick={header.column.getToggleSortingHandler()}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: <i className='tabler-chevron-up text-xl' />,
desc: <i className='tabler-chevron-down text-xl' />
}[header.column.getIsSorted() as 'asc' | 'desc'] ?? null}
</div>
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table
.getRowModel()
.rows.slice(0, table.getState().pagination.pageSize)
.map(row => {
return (
<tr key={row.id} className={classnames({ selected: row.getIsSelected() })}>
{row.getVisibleCells().map(cell => (
<td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
))}
</tr>
)
})}
</tbody>
</table>
</div>
{/* <TablePagination
component={() => <TablePaginationComponent table={table} />}
count={table.getFilteredRowModel().rows.length}
rowsPerPage={table.getState().pagination.pageSize}
page={table.getState().pagination.pageIndex}
onPageChange={(_, page) => {
table.setPageIndex(page)
}}
onRowsPerPageChange={e => table.setPageSize(Number(e.target.value))}
/> */}
</Card>
)
}
export default ProjectTables
@@ -1,34 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Type Imports
import type { ProfileTabType } from '@/types/pages/profileTypes'
// Component Imports
import AboutOverview from './AboutOverview'
import ActivityTimeline from './ActivityTimeline'
import ConnectionsTeams from './ConnectionsTeams'
import ProjectsTable from './ProjectsTables'
const ProfileTab = ({ data }: { data?: ProfileTabType }) => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12, md: 5, lg: 4 }}>
<AboutOverview data={data} />
</Grid>
<Grid size={{ xs: 12, md: 7, lg: 8 }}>
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<ActivityTimeline />
</Grid>
<ConnectionsTeams connections={data?.connections} teamsTech={data?.teamsTech} />
<Grid size={{ xs: 12 }}>
<ProjectsTable projectTable={data?.projectTable} />
</Grid>
</Grid>
</Grid>
</Grid>
)
}
export default ProfileTab
@@ -1,141 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Chip from '@mui/material/Chip'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Divider from '@mui/material/Divider'
import LinearProgress from '@mui/material/LinearProgress'
import AvatarGroup from '@mui/material/AvatarGroup'
import Tooltip from '@mui/material/Tooltip'
// Type Imports
import type { ProjectsTabType } from '@/types/pages/profileTypes'
// Component Imports
import OptionMenu from '@core/components/option-menu'
import CustomAvatar from '@core/components/mui/Avatar'
import Link from '@components/Link'
const Projects = ({ data }: { data?: ProjectsTabType[] }) => {
return (
<Grid container spacing={6}>
{data &&
data.map((item, index) => {
return (
<Grid size={{ xs: 12, md: 6, lg: 4 }} key={index}>
<Card>
<CardContent className='flex flex-col gap-4'>
<div className='flex items-center justify-between'>
<div className='flex items-center gap-4'>
<CustomAvatar src={item.avatar} size={38} />
<div>
<Typography variant='h5' component={Link} className='hover:text-primary'>
{item.title}
</Typography>
<Typography>
<span className='font-medium'>Client: </span>
{item.client}
</Typography>
</div>
</div>
<OptionMenu
iconClassName='text-textDisabled'
options={[
'Rename Project',
'View Details',
'Add to Favorite',
{ divider: true },
{
text: 'Leave Project',
menuItemProps: { className: 'text-error hover:bg-[var(--mui-palette-error-lightOpacity)]' }
}
]}
/>
</div>
<div className='flex items-center justify-between flex-wrap gap-4'>
<div className='rounded bg-actionHover plb-2 pli-3'>
<div className='flex'>
<Typography className='font-medium' color='text.primary'>
{item.budgetSpent}
</Typography>
<Typography>{`/${item.budget}`}</Typography>
</div>
<Typography>Total Budget</Typography>
</div>
<div className='flex flex-col'>
<div className='flex'>
<Typography className='font-medium' color='text.primary'>
Start Date:
</Typography>
<Typography>{item.startDate}</Typography>
</div>
<div className='flex'>
<Typography className='font-medium' color='text.primary'>
Deadline:
</Typography>
<Typography>{item.deadline}</Typography>
</div>
</div>
</div>
<Typography>{item.description}</Typography>
</CardContent>
<Divider />
<CardContent className='flex flex-col gap-4'>
<div className='flex items-center justify-between '>
<div className='flex'>
<Typography className='font-medium' color='text.primary'>
All Hours:
</Typography>
<Typography>{item.hours}</Typography>
</div>
<Chip variant='tonal' size='small' color={item.chipColor} label={`${item.daysLeft} days left`} />
</div>
<div>
<div className='flex items-center justify-between mbe-2'>
<Typography
variant='caption'
className='text-textSecondary'
>{`Tasks: ${item.completedTask}/${item.totalTask}`}</Typography>
<Typography
variant='caption'
className='text-textSecondary'
>{`${Math.round((item.completedTask / item.totalTask) * 100)}% Completed`}</Typography>
</div>
<LinearProgress
color='primary'
variant='determinate'
value={Math.round((item.completedTask / item.totalTask) * 100)}
className='bs-2'
/>
</div>
<div className='flex items-center justify-between'>
<div className='flex items-center flex-grow gap-3'>
<AvatarGroup className='items-center pull-up'>
{item.avatarGroup.map((person, index) => {
return (
<Tooltip key={index} title={person.name}>
<CustomAvatar src={person.avatar} alt={person.name} size={32} />
</Tooltip>
)
})}
</AvatarGroup>
<Typography variant='body2' className='flex-grow'>
{item.members}
</Typography>
</div>
<div className='flex items-center gap-1'>
<i className='tabler-message-dots' />
<Typography>{item.comments}</Typography>
</div>
</div>
</CardContent>
</Card>
</Grid>
)
})}
</Grid>
)
}
export default Projects
@@ -1,85 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Avatar from '@mui/material/Avatar'
import Typography from '@mui/material/Typography'
import IconButton from '@mui/material/IconButton'
import AvatarGroup from '@mui/material/AvatarGroup'
import Tooltip from '@mui/material/Tooltip'
import Chip from '@mui/material/Chip'
// Type Imports
import type { TeamsTabType } from '@/types/pages/profileTypes'
// Component Imports
import OptionMenu from '@core/components/option-menu'
import Link from '@components/Link'
const Teams = ({ data }: { data?: TeamsTabType[] }) => {
return (
<Grid container spacing={6}>
{data &&
data.map((item, index) => {
return (
<Grid size={{ xs: 12, md: 6, lg: 4 }} key={index}>
<Card>
<CardContent className='flex flex-col gap-4'>
<div className='flex items-center justify-between gap-2'>
<div className='flex items-center gap-2'>
<Avatar src={item.avatar} className='bs-[38px] is-[38px]' />
<Typography variant='h5'>{item.title}</Typography>
</div>
<div className='flex items-center'>
<IconButton>
<i className='tabler-star text-textDisabled' />
</IconButton>
<OptionMenu
iconButtonProps={{ size: 'medium' }}
iconClassName='text-textDisabled'
options={[
'Rename Team',
'View Details',
'Add to Favorite',
{ divider: true },
{
text: 'Delete Team',
menuItemProps: { className: 'text-error hover:bg-[var(--mui-palette-error-lightOpacity)]' }
}
]}
/>
</div>
</div>
<Typography>{item.description}</Typography>
<div className='flex items-center justify-between flex-wrap gap-4'>
<AvatarGroup
total={item.extraMembers ? item.extraMembers + 3 : 3}
sx={{ '& .MuiAvatar-root': { width: '2rem', height: '2rem', fontSize: '1rem' } }}
className='items-center pull-up'
>
{item.avatarGroup.map((person, index) => {
return (
<Tooltip key={index} title={person.name}>
<Avatar src={person.avatar} alt={person.name} />
</Tooltip>
)
})}
</AvatarGroup>
<div className='flex items-center gap-2'>
{item.chips.map((chip, index) => (
<Link key={index}>
<Chip variant='tonal' size='small' label={chip.title} color={chip.color} />
</Link>
))}
</div>
</div>
</CardContent>
</Card>
</Grid>
)
})}
</Grid>
)
}
export default Teams
@@ -15,7 +15,6 @@ import OptionMenu from '@core/components/option-menu'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
import styles from '@views/apps/logistics/dashboard/styles.module.css'
type dataTypes = {
icon: string
@@ -76,9 +75,9 @@ const VehicleOverview = () => {
{data.map((item, index) => (
<div
key={index}
className={classnames(item.widthClass, styles.linearRound, 'flex flex-col gap-[38px] relative')}
className={classnames(item.widthClass, 'flex flex-col gap-[38px] relative')}
>
<Typography className={classnames(styles.header, 'relative max-sm:hidden')}>{item.heading}</Typography>
<Typography className={classnames('relative max-sm:hidden')}>{item.heading}</Typography>
<LinearProgress
variant='determinate'
value={-1}