First commit
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// 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 LinearProgress from '@mui/material/LinearProgress'
|
||||
import Chip from '@mui/material/Chip'
|
||||
|
||||
// Third Party Imports
|
||||
import classnames from 'classnames'
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Types Imports
|
||||
import type { ThemeColor } from '@core/types'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
type DataType = {
|
||||
stats: string
|
||||
title: string
|
||||
progress: number
|
||||
avatarIcon: string
|
||||
avatarColor?: ThemeColor
|
||||
progressColor?: ThemeColor
|
||||
}
|
||||
|
||||
// Vars
|
||||
const series = [{ data: [37, 76, 65, 41, 99, 53, 70] }]
|
||||
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Earnings',
|
||||
progress: 64,
|
||||
stats: '$545.69',
|
||||
progressColor: 'primary',
|
||||
avatarColor: 'primary',
|
||||
avatarIcon: 'tabler-currency-dollar'
|
||||
},
|
||||
{
|
||||
title: 'Profit',
|
||||
progress: 59,
|
||||
stats: '$256.34',
|
||||
progressColor: 'info',
|
||||
avatarColor: 'info',
|
||||
avatarIcon: 'tabler-chart-pie-2'
|
||||
},
|
||||
{
|
||||
title: 'Expense',
|
||||
progress: 22,
|
||||
stats: '$74.19',
|
||||
progressColor: 'error',
|
||||
avatarColor: 'error',
|
||||
avatarIcon: 'tabler-brand-paypal'
|
||||
}
|
||||
]
|
||||
|
||||
const EarningReports = () => {
|
||||
// Vars
|
||||
const primaryColorWithOpacity = 'var(--mui-palette-primary-lightOpacity)'
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false }
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -31,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: -9
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 4,
|
||||
distributed: true,
|
||||
columnWidth: '42%'
|
||||
}
|
||||
},
|
||||
legend: { show: false },
|
||||
dataLabels: { enabled: false },
|
||||
colors: [
|
||||
primaryColorWithOpacity,
|
||||
primaryColorWithOpacity,
|
||||
primaryColorWithOpacity,
|
||||
primaryColorWithOpacity,
|
||||
'var(--mui-palette-primary-main)',
|
||||
primaryColorWithOpacity,
|
||||
primaryColorWithOpacity
|
||||
],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' }
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' }
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
colors: 'var(--mui-palette-text-disabled)'
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: { show: false }
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Earning Reports'
|
||||
subheader='Weekly Earnings Overview'
|
||||
action={<OptionMenu options={['Last Week', 'Last Month', 'Last Year']} />}
|
||||
className='pbe-0'
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-5 max-md:gap-5 max-[1015px]:gap-[62px] max-[1051px]:gap-10 max-[1200px]:gap-5 max-[1310px]:gap-10'>
|
||||
<div className='flex flex-col sm:flex-row items-center justify-between gap-8'>
|
||||
<div className='flex flex-col gap-3 is-full sm:is-[unset]'>
|
||||
<div className='flex items-center gap-2.5'>
|
||||
<Typography variant='h2'>$468</Typography>
|
||||
<Chip size='small' variant='tonal' color='success' label='+4.2%' />
|
||||
</div>
|
||||
<Typography variant='body2' className='text-balance'>
|
||||
You informed of this week compared to last week
|
||||
</Typography>
|
||||
</div>
|
||||
<AppReactApexCharts type='bar' height={163} width='100%' series={series} options={options} />
|
||||
</div>
|
||||
<div className='flex flex-col sm:flex-row gap-6 p-5 border rounded'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex flex-col gap-2 is-full'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<CustomAvatar skin='light' variant='rounded' color={item.avatarColor} size={26}>
|
||||
<i className={classnames(item.avatarIcon, 'text-lg')} />
|
||||
</CustomAvatar>
|
||||
<Typography variant='h6' className='leading-6 font-normal'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography variant='h4'>{item.stats}</Typography>
|
||||
<LinearProgress
|
||||
value={item.progress}
|
||||
variant='determinate'
|
||||
color={item.progressColor}
|
||||
className='max-bs-1'
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default EarningReports
|
||||
@@ -0,0 +1,94 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third-party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
const series = [{ data: [40, 20, 65, 50] }]
|
||||
|
||||
const LineAreaDailySalesChart = () => {
|
||||
// Hook
|
||||
const theme = useTheme()
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
sparkline: { enabled: true }
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 2,
|
||||
curve: 'smooth'
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
bottom: 20
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
opacityTo: 0,
|
||||
opacityFrom: 1,
|
||||
shadeIntensity: 1,
|
||||
stops: [0, 100],
|
||||
colorStops: [
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
opacity: 0.4,
|
||||
color: theme.palette.success.main
|
||||
},
|
||||
{
|
||||
opacity: 0,
|
||||
offset: 100,
|
||||
color: 'var(--mui-palette-background-paper)'
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
monochrome: {
|
||||
enabled: true,
|
||||
shadeTo: 'light',
|
||||
shadeIntensity: 1,
|
||||
color: theme.palette.success.main
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false }
|
||||
},
|
||||
yaxis: { show: false }
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className='pbe-6'>
|
||||
<CardHeader title='Average Daily Sales' className='pbe-3' />
|
||||
<CardContent>
|
||||
<Typography>Total Sales This Month</Typography>
|
||||
<Typography variant='h4'>$28,450</Typography>
|
||||
</CardContent>
|
||||
<AppReactApexCharts type='area' height={88} width='100%' series={series} options={options} />
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default LineAreaDailySalesChart
|
||||
@@ -0,0 +1,108 @@
|
||||
// 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'
|
||||
|
||||
// Third-party Imports
|
||||
import classnames from 'classnames'
|
||||
|
||||
import type { ThemeColor } from '@core/types'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
type DataType = {
|
||||
icon: string
|
||||
title: string
|
||||
amount: string
|
||||
avatarColor: ThemeColor
|
||||
trendNumber: string
|
||||
trend?: 'positive' | 'negative'
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Emails',
|
||||
amount: '12,346',
|
||||
trendNumber: '0.3%',
|
||||
avatarColor: 'success',
|
||||
icon: 'tabler-mail'
|
||||
},
|
||||
{
|
||||
title: 'Opened',
|
||||
amount: '8,734',
|
||||
trendNumber: '2.1%',
|
||||
avatarColor: 'info',
|
||||
icon: 'tabler-link'
|
||||
},
|
||||
{
|
||||
title: 'Clicked',
|
||||
amount: '967',
|
||||
trendNumber: '1.4%',
|
||||
trend: 'negative',
|
||||
avatarColor: 'warning',
|
||||
icon: 'tabler-mouse'
|
||||
},
|
||||
{
|
||||
title: 'Subscribe',
|
||||
amount: '345',
|
||||
trendNumber: '8.5%',
|
||||
avatarColor: 'primary',
|
||||
icon: 'tabler-users'
|
||||
},
|
||||
{
|
||||
title: 'Complaints',
|
||||
amount: '10',
|
||||
trendNumber: '1.5%',
|
||||
trend: 'negative',
|
||||
avatarColor: 'secondary',
|
||||
icon: 'tabler-alert-triangle'
|
||||
},
|
||||
{
|
||||
title: 'Unsubscribe',
|
||||
amount: '86',
|
||||
trendNumber: '0.8%',
|
||||
avatarColor: 'error',
|
||||
icon: 'tabler-ban'
|
||||
}
|
||||
]
|
||||
|
||||
const MonthlyCampaignState = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Monthly Campaign State'
|
||||
subheader='8.52k Social Visitors'
|
||||
action={<OptionMenu options={['Last Month', 'Last 6 Months', 'Last Year']} />}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-6 md:gap-[1.6875rem]'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<CustomAvatar skin='light' variant='rounded' color={item.avatarColor} size={34}>
|
||||
<i className={classnames(item.icon, 'text-[22px]')} />
|
||||
</CustomAvatar>
|
||||
<div className='flex flex-wrap justify-between items-center gap-x-4 gap-y-1 is-full'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<div className='flex items-center gap-4'>
|
||||
<Typography>{item.amount}</Typography>
|
||||
<Typography
|
||||
className='flex justify-end is-11'
|
||||
color={`${item.trend === 'negative' ? 'error' : 'success'}.main`}
|
||||
>
|
||||
{item.trendNumber}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default MonthlyCampaignState
|
||||
@@ -0,0 +1,295 @@
|
||||
'use client'
|
||||
|
||||
// React Imports
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
// MUI Imports
|
||||
import AvatarGroup from '@mui/material/AvatarGroup'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import LinearProgress from '@mui/material/LinearProgress'
|
||||
import Card from '@mui/material/Card'
|
||||
import Checkbox from '@mui/material/Checkbox'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import TablePagination from '@mui/material/TablePagination'
|
||||
import type { TextFieldProps } from '@mui/material/TextField'
|
||||
|
||||
// Third-party Imports
|
||||
import classnames from 'classnames'
|
||||
import { rankItem } from '@tanstack/match-sorter-utils'
|
||||
import {
|
||||
createColumnHelper,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
getFilteredRowModel,
|
||||
getFacetedRowModel,
|
||||
getFacetedUniqueValues,
|
||||
getFacetedMinMaxValues,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel
|
||||
} from '@tanstack/react-table'
|
||||
import type { ColumnDef, FilterFn } from '@tanstack/react-table'
|
||||
import type { RankingInfo } from '@tanstack/match-sorter-utils'
|
||||
|
||||
// Type Imports
|
||||
import type { ProjectTableRowType } from '@/types/pages/profileTypes'
|
||||
|
||||
// Component Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
import CustomTextField from '@core/components/mui/TextField'
|
||||
import TablePaginationComponent from '@/components/TablePaginationComponent'
|
||||
|
||||
// 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<ProjectTableRowType[]>(projectTable || [])
|
||||
const [globalFilter, setGlobalFilter] = useState('')
|
||||
|
||||
// Update data when projectTable changes
|
||||
useEffect(() => {
|
||||
setData(projectTable || [])
|
||||
}, [projectTable])
|
||||
|
||||
// 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: 'پروژه',
|
||||
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: 'تیم',
|
||||
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: 'پیشرفت',
|
||||
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: 'عملیات',
|
||||
cell: () => (
|
||||
<OptionMenu
|
||||
iconClassName='text-textSecondary'
|
||||
options={[
|
||||
'جزئیات',
|
||||
'Archive',
|
||||
{ divider: true },
|
||||
{ text: 'حذف', 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: 5
|
||||
}
|
||||
},
|
||||
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
|
||||
rowsPerPageOptions={[5, 7, 10]}
|
||||
component={() => <TablePaginationComponent table={table} />}
|
||||
count={table.getFilteredRowModel().rows.length}
|
||||
rowsPerPage={table.getState().pagination.pageSize}
|
||||
page={table.getState().pagination.pageIndex}
|
||||
onPageChange={(_, page) => {
|
||||
table.setPageIndex(page)
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectTables
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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'
|
||||
|
||||
// Third-party Imports
|
||||
import classnames from 'classnames'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
|
||||
type DataType = {
|
||||
title: string
|
||||
imgSrc: string
|
||||
subtitle: string
|
||||
trendNumber: number
|
||||
trend?: 'positive' | 'negative'
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: '$8.45k',
|
||||
subtitle: 'United States',
|
||||
trendNumber: 25.8,
|
||||
imgSrc: '/images/cards/us.png'
|
||||
},
|
||||
{
|
||||
title: '$7.78k',
|
||||
subtitle: 'Brazil',
|
||||
trendNumber: 16.2,
|
||||
trend: 'negative',
|
||||
imgSrc: '/images/cards/brazil.png'
|
||||
},
|
||||
{
|
||||
title: '$6.48k',
|
||||
subtitle: 'India',
|
||||
trendNumber: 12.3,
|
||||
imgSrc: '/images/cards/india.png'
|
||||
},
|
||||
{
|
||||
title: '$5.12k',
|
||||
subtitle: 'Australia',
|
||||
trendNumber: 11.9,
|
||||
trend: 'negative',
|
||||
imgSrc: '/images/cards/australia.png'
|
||||
},
|
||||
{
|
||||
title: '$4.45k',
|
||||
subtitle: 'France',
|
||||
trendNumber: 16.2,
|
||||
imgSrc: '/images/cards/france.png'
|
||||
},
|
||||
{
|
||||
title: '$3.90k',
|
||||
subtitle: 'China',
|
||||
trendNumber: 14.8,
|
||||
imgSrc: '/images/cards/china.png'
|
||||
}
|
||||
]
|
||||
|
||||
const SalesByCountries = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Sales by Countries'
|
||||
subheader='Monthly Sales Overview'
|
||||
action={<OptionMenu options={['Last Week', 'Last Month', 'Last Year']} />}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-[1.0875rem]'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<img src={item.imgSrc} alt={item.subtitle} width={34} />
|
||||
<div className='flex flex-wrap justify-between items-center gap-x-4 gap-y-1 is-full'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<Typography variant='body2'>{item.subtitle}</Typography>
|
||||
</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
<i
|
||||
className={classnames(
|
||||
item.trend === 'negative' ? 'tabler-chevron-down text-error' : 'tabler-chevron-up text-success',
|
||||
'text-xl'
|
||||
)}
|
||||
/>
|
||||
<Typography
|
||||
variant='h6'
|
||||
color={`${item.trend === 'negative' ? 'error' : 'success'}.main`}
|
||||
>{`${item.trendNumber}%`}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesByCountries
|
||||
@@ -0,0 +1,74 @@
|
||||
'use client'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import Divider from '@mui/material/Divider'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import MuiLinearProgress from '@mui/material/LinearProgress'
|
||||
import { styled } from '@mui/material/styles'
|
||||
|
||||
// Custom Components Imports
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
const LinearProgress = styled(MuiLinearProgress)(() => ({
|
||||
'&.MuiLinearProgress-colorInfo': { backgroundColor: 'var(--mui-palette-primary-main)' },
|
||||
'& .MuiLinearProgress-bar': {
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomRightRadius: 0
|
||||
}
|
||||
}))
|
||||
|
||||
const SalesOverview = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<div className='flex items-start justify-between gap-3'>
|
||||
<div>
|
||||
<Typography>Sales Overview</Typography>
|
||||
<Typography variant='h4'>$42.5k</Typography>
|
||||
</div>
|
||||
<Typography color='success.main' className='font-medium'>
|
||||
+18.2%
|
||||
</Typography>
|
||||
</div>
|
||||
<div className='flex items-center justify-between mlb-[1.4375rem]'>
|
||||
<div className='flex flex-col plb-2.25'>
|
||||
<div className='flex items-center mbe-2.5 gap-x-[6px]'>
|
||||
<CustomAvatar skin='light' color='info' variant='rounded' size={24}>
|
||||
<i className='tabler-shopping-cart text-lg' />
|
||||
</CustomAvatar>
|
||||
<Typography>Order</Typography>
|
||||
</div>
|
||||
<Typography variant='h5'>62.2%</Typography>
|
||||
<Typography variant='body2' color='text.disabled'>
|
||||
6,440
|
||||
</Typography>
|
||||
</div>
|
||||
<Divider flexItem orientation='vertical'>
|
||||
<CustomAvatar skin='light' size={24} className='text-xs text-textDisabled bg-actionHover'>
|
||||
VS
|
||||
</CustomAvatar>
|
||||
</Divider>
|
||||
<div className='flex items-end flex-col plb-2'>
|
||||
<div className='flex items-center mbe-2 gap-x-[6px]'>
|
||||
<Typography color='text.secondary' className='m'>
|
||||
Visits
|
||||
</Typography>
|
||||
<CustomAvatar skin='light' variant='rounded' color='primary' size={24}>
|
||||
<i className='tabler-link text-lg' />
|
||||
</CustomAvatar>
|
||||
</div>
|
||||
<Typography variant='h5'>25.5%</Typography>
|
||||
<Typography variant='body2' color='text.disabled'>
|
||||
12,749
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<LinearProgress value={65} color='info' variant='determinate' className='bs-2.5' />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesOverview
|
||||
@@ -0,0 +1,109 @@
|
||||
// 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'
|
||||
|
||||
// Third-party Imports
|
||||
import classnames from 'classnames'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
type DataType = {
|
||||
icon: string
|
||||
title: string
|
||||
amount: string
|
||||
subtitle: string
|
||||
trendNumber: number
|
||||
trend?: 'positive' | 'negative'
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Direct Source',
|
||||
subtitle: 'Direct link click',
|
||||
amount: '1.2k',
|
||||
trendNumber: 4.2,
|
||||
icon: 'tabler-shadow'
|
||||
},
|
||||
{
|
||||
title: 'Social Networks',
|
||||
subtitle: 'Social Channels',
|
||||
amount: '31.5k',
|
||||
trendNumber: 8.2,
|
||||
icon: 'tabler-globe'
|
||||
},
|
||||
{
|
||||
title: 'Email Newsletter',
|
||||
subtitle: 'Mail Campaigns',
|
||||
amount: '893',
|
||||
trendNumber: 2.4,
|
||||
icon: 'tabler-mail'
|
||||
},
|
||||
{
|
||||
title: 'Referrals',
|
||||
subtitle: 'Impact Radius Visits',
|
||||
amount: '342',
|
||||
trendNumber: 0.4,
|
||||
trend: 'negative',
|
||||
icon: 'tabler-external-link'
|
||||
},
|
||||
{
|
||||
title: 'ADVT',
|
||||
subtitle: 'Google ADVT',
|
||||
amount: '2.15k',
|
||||
trendNumber: 9.1,
|
||||
icon: 'tabler-ad'
|
||||
},
|
||||
{
|
||||
title: 'Other',
|
||||
subtitle: 'Many Sources',
|
||||
amount: '12.5k',
|
||||
trendNumber: 6.2,
|
||||
icon: 'tabler-star'
|
||||
}
|
||||
]
|
||||
|
||||
const SourceVisits = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Source Visits'
|
||||
subheader='38.4k Visitors'
|
||||
action={<OptionMenu options={['Last Week', 'Last Month', 'Last Year']} />}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-6 md:gap-[1.0875rem] lg:gap-[1.5875rem]'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<CustomAvatar skin='light' variant='rounded' size={34}>
|
||||
<i className={classnames(item.icon, 'text-[22px] text-textSecondary')} />
|
||||
</CustomAvatar>
|
||||
<div className='flex flex-wrap justify-between items-center gap-x-4 gap-y-1 is-full'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<Typography variant='body2'>{item.subtitle}</Typography>
|
||||
</div>
|
||||
<div className='flex items-center gap-4'>
|
||||
<Typography>{item.amount}</Typography>
|
||||
<Chip
|
||||
variant='tonal'
|
||||
size='small'
|
||||
color={item.trend === 'negative' ? 'error' : 'success'}
|
||||
label={`${item.trend === 'negative' ? '-' : '+'}${item.trendNumber}%`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default SourceVisits
|
||||
@@ -0,0 +1,215 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// 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 { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third Party Imports
|
||||
import classnames from 'classnames'
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Types Imports
|
||||
import type { ThemeColor } from '@core/types'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
type DataType = {
|
||||
title: string
|
||||
subtitle: string
|
||||
avatarIcon: string
|
||||
avatarColor?: ThemeColor
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'New Tickets',
|
||||
subtitle: '142',
|
||||
avatarColor: 'primary',
|
||||
avatarIcon: 'tabler-ticket'
|
||||
},
|
||||
{
|
||||
title: 'Open Tickets',
|
||||
subtitle: '28',
|
||||
avatarColor: 'info',
|
||||
avatarIcon: 'tabler-check'
|
||||
},
|
||||
{
|
||||
title: 'Response Time',
|
||||
subtitle: '1 Day',
|
||||
avatarColor: 'warning',
|
||||
avatarIcon: 'tabler-clock'
|
||||
}
|
||||
]
|
||||
|
||||
const SupportTracker = () => {
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const disabledText = 'var(--mui-palette-text-disabled)'
|
||||
|
||||
const options: ApexOptions = {
|
||||
stroke: { dashArray: 10 },
|
||||
labels: ['Completed Task'],
|
||||
colors: ['var(--mui-palette-primary-main)'],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' }
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' }
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shade: 'dark',
|
||||
opacityTo: 0.5,
|
||||
opacityFrom: 1,
|
||||
shadeIntensity: 0.5,
|
||||
stops: [30, 70, 100],
|
||||
inverseColors: false,
|
||||
gradientToColors: ['var(--mui-palette-primary-main)']
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
endAngle: 130,
|
||||
startAngle: -140,
|
||||
hollow: { size: '60%' },
|
||||
track: { background: 'transparent' },
|
||||
dataLabels: {
|
||||
name: {
|
||||
offsetY: -24,
|
||||
color: disabledText,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
fontSize: theme.typography.body2.fontSize as string
|
||||
},
|
||||
value: {
|
||||
offsetY: 8,
|
||||
fontWeight: 500,
|
||||
formatter: value => `${value}%`,
|
||||
color: 'var(--mui-palette-text-primary)',
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
fontSize: theme.typography.h2.fontSize as string
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
padding: {
|
||||
top: -18,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 14
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1380,
|
||||
options: {
|
||||
grid: {
|
||||
padding: {
|
||||
top: 8,
|
||||
left: 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1280,
|
||||
options: {
|
||||
chart: {
|
||||
height: 325
|
||||
},
|
||||
grid: {
|
||||
padding: {
|
||||
top: 12,
|
||||
left: 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1201,
|
||||
options: {
|
||||
chart: {
|
||||
height: 362
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1135,
|
||||
options: {
|
||||
chart: {
|
||||
height: 350
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 980,
|
||||
options: {
|
||||
chart: {
|
||||
height: 300
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 900,
|
||||
options: {
|
||||
chart: {
|
||||
height: 350
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Support Tracker'
|
||||
subheader='Last 7 Days'
|
||||
action={<OptionMenu options={['Refresh', 'Edit', 'Share']} />}
|
||||
/>
|
||||
<CardContent className='flex flex-col sm:flex-row items-center justify-between gap-7'>
|
||||
<div className='flex flex-col gap-6 is-full sm:is-[unset]'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography variant='h2'>164</Typography>
|
||||
<Typography>Total Tickets</Typography>
|
||||
</div>
|
||||
<div className='flex flex-col gap-4 is-full'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<CustomAvatar skin='light' variant='rounded' color={item.avatarColor} size={34}>
|
||||
<i className={classnames(item.avatarIcon, 'text-[22px]')} />
|
||||
</CustomAvatar>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<Typography variant='body2'>{item.subtitle}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<AppReactApexCharts type='radialBar' height={350} width='100%' series={[85]} options={options} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default SupportTracker
|
||||
@@ -0,0 +1,225 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// 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 { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third Party Imports
|
||||
import classnames from 'classnames'
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Types Imports
|
||||
import type { ThemeColor } from '@core/types'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
type DataType = {
|
||||
title: string
|
||||
amount: number
|
||||
subtitle: string
|
||||
avatarIcon: string
|
||||
avatarColor: ThemeColor
|
||||
amountDiff?: 'positive' | 'negative'
|
||||
}
|
||||
|
||||
// Vars
|
||||
const series = [
|
||||
{ name: 'Earning', data: [15, 10, 20, 8, 12, 18, 12, 5] },
|
||||
{ name: 'Expense', data: [-7, -10, -7, -12, -6, -9, -5, -8] }
|
||||
]
|
||||
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Total Revenue',
|
||||
subtitle: 'Client Payment',
|
||||
amount: 126,
|
||||
avatarColor: 'primary',
|
||||
avatarIcon: 'tabler-brand-paypal'
|
||||
},
|
||||
{
|
||||
title: 'Total Sales',
|
||||
subtitle: 'Refund',
|
||||
amount: 98,
|
||||
avatarColor: 'secondary',
|
||||
avatarIcon: 'tabler-currency-dollar'
|
||||
}
|
||||
]
|
||||
|
||||
const TotalEarning = () => {
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
stacked: true,
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 5,
|
||||
colors: ['var(--mui-palette-background-paper)']
|
||||
},
|
||||
colors: ['var(--mui-palette-primary-main)', 'var(--mui-palette-secondary-main)'],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' }
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' }
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 7,
|
||||
columnWidth: '40%',
|
||||
borderRadiusApplication: 'around',
|
||||
borderRadiusWhenStacked: 'all'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
borderColor: 'var(--mui-palette-divider)',
|
||||
yaxis: {
|
||||
lines: { show: false }
|
||||
},
|
||||
padding: {
|
||||
top: -56,
|
||||
left: -13,
|
||||
right: 0,
|
||||
bottom: -15
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
crosshairs: { opacity: 0 },
|
||||
axisBorder: { show: false }
|
||||
},
|
||||
yaxis: {
|
||||
labels: { show: false }
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.xl,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '50%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1380,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 5,
|
||||
columnWidth: '55%'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.lg,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 7,
|
||||
columnWidth: '40%'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.md,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '25%', borderRadius: 6 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 680,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '28%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.sm,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '38%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 450,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '55%' }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Total Earning'
|
||||
action={<OptionMenu options={['Refresh', 'Share', 'Update']} />}
|
||||
subheader={
|
||||
<div className='flex items-center gap-2'>
|
||||
<Typography variant='h2'>87%</Typography>
|
||||
<div className='flex items-center gap-1'>
|
||||
<i className='tabler-chevron-up text-xl text-success' />
|
||||
<Typography color='success.main'>25.8%</Typography>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-4'>
|
||||
<AppReactApexCharts type='bar' height={189} width='100%' series={series} options={options} />
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<CustomAvatar skin='light' variant='rounded' color={item.avatarColor} size={38}>
|
||||
<i className={classnames(item.avatarIcon, 'text-[22px]')} />
|
||||
</CustomAvatar>
|
||||
<div className='flex justify-between items-center is-full'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<Typography variant='body2'>{item.subtitle}</Typography>
|
||||
</div>
|
||||
<Typography
|
||||
className='font-medium'
|
||||
color={`${item.amountDiff === 'negative' ? 'error' : 'success'}.main`}
|
||||
>{`${item.amountDiff === 'negative' ? '-' : '+'}$${item.amount}`}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default TotalEarning
|
||||
@@ -0,0 +1,226 @@
|
||||
'use client'
|
||||
|
||||
// React Imports
|
||||
import { useState } from 'react'
|
||||
|
||||
// MUI Imports
|
||||
import Badge from '@mui/material/Badge'
|
||||
import Card from '@mui/material/Card'
|
||||
import Grid from '@mui/material/Grid2'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third-party Components
|
||||
import classnames from 'classnames'
|
||||
import { useKeenSlider } from 'keen-slider/react'
|
||||
import type { KeenSliderPlugin } from 'keen-slider/react'
|
||||
|
||||
// Components Imports
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
import AppKeenSlider from '@/libs/styles/AppKeenSlider'
|
||||
|
||||
type DataType = {
|
||||
img: string
|
||||
title: string
|
||||
details: { [key: string]: string }
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Traffic',
|
||||
img: '/images/cards/graphic-illustration-1.png',
|
||||
details: {
|
||||
Sessions: '28%',
|
||||
'Page Views': '3.1k',
|
||||
Leads: '1.2k',
|
||||
Conversions: '12%'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Spending',
|
||||
img: '/images/cards/graphic-illustration-2.png',
|
||||
details: {
|
||||
Spend: '12h',
|
||||
Orders: '18',
|
||||
Order: '127',
|
||||
Items: '2.3k'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Revenue Sources',
|
||||
img: '/images/cards/graphic-illustration-3.png',
|
||||
details: {
|
||||
Direct: '268',
|
||||
Organic: '890',
|
||||
Referral: '62',
|
||||
Campaign: '1.2k'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const Slides = () => {
|
||||
return (
|
||||
<>
|
||||
{data.map((slide: DataType, index: number) => {
|
||||
return (
|
||||
<div key={index} className={classnames('keen-slider__slide p-6 pbe-3 is-full')}>
|
||||
<Typography variant='h5' className='mbe-0.5 text-[var(--mui-palette-common-white)]'>
|
||||
Website Analytics
|
||||
</Typography>
|
||||
<Typography variant='subtitle2' className='mbe-3 text-[var(--mui-palette-common-white)]'>
|
||||
Total 28.5% Conversion Rate
|
||||
</Typography>
|
||||
<Grid container spacing={4} className='relative'>
|
||||
<Grid size={{ xs: 12, sm: 8 }} className='order-2 sm:order-1'>
|
||||
<div className='flex flex-col gap-4 sm:plb-6'>
|
||||
<Typography className='font-medium text-[var(--mui-palette-common-white)]'>{slide.title}</Typography>
|
||||
<Grid container spacing={4}>
|
||||
{Object.keys(slide.details).map((key: string, index: number) => {
|
||||
return (
|
||||
<Grid key={index} size={{ xs: 6 }}>
|
||||
<div className='flex items-center gap-0.5'>
|
||||
<CustomAvatar
|
||||
color='primary'
|
||||
variant='rounded'
|
||||
className='font-medium mie-2 text-white bg-[var(--mui-palette-primary-dark)] bs-[30px] is-12'
|
||||
>
|
||||
{slide.details[key]}
|
||||
</CustomAvatar>
|
||||
<Typography noWrap className='text-[var(--mui-palette-common-white)]'>
|
||||
{key}
|
||||
</Typography>
|
||||
</div>
|
||||
</Grid>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, sm: 4 }} className='flex justify-center order-1 sm:order-2'>
|
||||
<img
|
||||
src={slide.img}
|
||||
height={150}
|
||||
className='max-bs-[150px] lg:bs-[120px] xl:bs-[150px] drop-shadow-[0_4px_60px_rgba(0,0,0,0.5)] sm:absolute bottom-3 end-0'
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const WebsiteAnalyticsSlider = () => {
|
||||
// States
|
||||
const [loaded, setLoaded] = useState<boolean>(false)
|
||||
const [currentSlide, setCurrentSlide] = useState<number>(0)
|
||||
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
const ResizePlugin: KeenSliderPlugin = slider => {
|
||||
const observer = new ResizeObserver(function () {
|
||||
slider.update()
|
||||
})
|
||||
|
||||
slider.on('created', () => {
|
||||
observer.observe(slider.container)
|
||||
})
|
||||
slider.on('destroyed', () => {
|
||||
observer.unobserve(slider.container)
|
||||
})
|
||||
}
|
||||
|
||||
const [sliderRef, instanceRef] = useKeenSlider<HTMLDivElement>(
|
||||
{
|
||||
loop: true,
|
||||
initial: 0,
|
||||
rtl: theme.direction === 'rtl',
|
||||
slideChanged(slider) {
|
||||
setCurrentSlide(slider.track.details.rel)
|
||||
},
|
||||
created() {
|
||||
setLoaded(true)
|
||||
}
|
||||
},
|
||||
[
|
||||
ResizePlugin,
|
||||
slider => {
|
||||
let mouseOver = false
|
||||
let timeout: number | ReturnType<typeof setTimeout>
|
||||
|
||||
const clearNextTimeout = () => {
|
||||
clearTimeout(timeout as number)
|
||||
}
|
||||
|
||||
const nextTimeout = () => {
|
||||
clearTimeout(timeout as number)
|
||||
if (mouseOver) return
|
||||
timeout = setTimeout(() => {
|
||||
slider.next()
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
slider.on('created', () => {
|
||||
slider.container.addEventListener('mouseover', () => {
|
||||
mouseOver = true
|
||||
clearNextTimeout()
|
||||
})
|
||||
slider.container.addEventListener('mouseout', () => {
|
||||
mouseOver = false
|
||||
nextTimeout()
|
||||
})
|
||||
nextTimeout()
|
||||
})
|
||||
slider.on('dragStarted', clearNextTimeout)
|
||||
slider.on('animationEnded', nextTimeout)
|
||||
slider.on('updated', nextTimeout)
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
<AppKeenSlider>
|
||||
<Card className='bg-primary'>
|
||||
<div ref={sliderRef} className='keen-slider relative'>
|
||||
{loaded && instanceRef.current && (
|
||||
<div className='swiper-dots absolute top-1 inline-end-6'>
|
||||
{[...Array(instanceRef.current.track.details.slides.length).keys()].map(idx => {
|
||||
return (
|
||||
<Badge
|
||||
key={idx}
|
||||
variant='dot'
|
||||
component='div'
|
||||
className={classnames({
|
||||
active: currentSlide === idx
|
||||
})}
|
||||
onClick={() => {
|
||||
instanceRef.current?.moveToIdx(idx)
|
||||
}}
|
||||
sx={{
|
||||
'& .MuiBadge-dot': {
|
||||
width: '8px !important',
|
||||
height: '8px !important',
|
||||
backgroundColor: 'var(--mui-palette-common-white) !important',
|
||||
opacity: 0.4
|
||||
},
|
||||
'&.active .MuiBadge-dot': {
|
||||
opacity: 1
|
||||
}
|
||||
}}
|
||||
></Badge>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<Slides />
|
||||
</div>
|
||||
</Card>
|
||||
</AppKeenSlider>
|
||||
)
|
||||
}
|
||||
|
||||
export default WebsiteAnalyticsSlider
|
||||
@@ -0,0 +1,103 @@
|
||||
// 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 LinearProgress from '@mui/material/LinearProgress'
|
||||
|
||||
import type { ThemeColor } from '@core/types'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
|
||||
type DataType = {
|
||||
title: string
|
||||
imgSrc: string
|
||||
progress: number
|
||||
subtitle: string
|
||||
progressColor: ThemeColor
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Laravel',
|
||||
subtitle: 'eCommerce',
|
||||
progress: 54,
|
||||
progressColor: 'error',
|
||||
imgSrc: '/images/logos/laravel.png'
|
||||
},
|
||||
{
|
||||
title: 'Figma',
|
||||
subtitle: 'App UI Kit',
|
||||
progress: 85,
|
||||
progressColor: 'primary',
|
||||
imgSrc: '/images/logos/figma.png'
|
||||
},
|
||||
{
|
||||
title: 'VusJs',
|
||||
subtitle: 'Calendar App',
|
||||
progress: 64,
|
||||
progressColor: 'success',
|
||||
imgSrc: '/images/logos/vue.png'
|
||||
},
|
||||
{
|
||||
title: 'React',
|
||||
subtitle: 'Dashboard',
|
||||
progress: 40,
|
||||
progressColor: 'info',
|
||||
imgSrc: '/images/logos/react.png'
|
||||
},
|
||||
{
|
||||
title: 'Bootstrap',
|
||||
subtitle: 'Website',
|
||||
progress: 17,
|
||||
progressColor: 'primary',
|
||||
imgSrc: '/images/logos/bootstrap.png'
|
||||
},
|
||||
{
|
||||
title: 'Sketch',
|
||||
subtitle: 'Website Design',
|
||||
progress: 30,
|
||||
progressColor: 'warning',
|
||||
imgSrc: '/images/logos/sketch.png'
|
||||
}
|
||||
]
|
||||
|
||||
const ActiveProjects = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Active Projects'
|
||||
subheader='Average 72% completed'
|
||||
action={<OptionMenu options={['Refresh', 'Update', 'Share']} />}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-4'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<img src={item.imgSrc} alt={item.title} width={32} />
|
||||
<div className='flex flex-wrap justify-between items-center gap-x-4 gap-y-1 is-full'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<Typography variant='body2'>{item.subtitle}</Typography>
|
||||
</div>
|
||||
<div className='flex justify-between items-center is-32'>
|
||||
<LinearProgress
|
||||
value={item.progress}
|
||||
variant='determinate'
|
||||
color={item.progressColor}
|
||||
className='min-bs-2 is-20'
|
||||
/>
|
||||
<Typography color='text.disabled'>{`${item.progress}%`}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActiveProjects
|
||||
@@ -0,0 +1,117 @@
|
||||
'use client'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import { styled } from '@mui/material/styles'
|
||||
import Avatar from '@mui/material/Avatar'
|
||||
import AvatarGroup from '@mui/material/AvatarGroup'
|
||||
import MuiTimeline from '@mui/lab/Timeline'
|
||||
import TimelineDot from '@mui/lab/TimelineDot'
|
||||
import TimelineItem from '@mui/lab/TimelineItem'
|
||||
import TimelineContent from '@mui/lab/TimelineContent'
|
||||
import TimelineSeparator from '@mui/lab/TimelineSeparator'
|
||||
import TimelineConnector from '@mui/lab/TimelineConnector'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import type { TimelineProps } from '@mui/lab/Timeline'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
|
||||
// Styled Timeline component
|
||||
const Timeline = styled(MuiTimeline)<TimelineProps>({
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
'& .MuiTimelineItem-root': {
|
||||
width: '100%',
|
||||
'&:before': {
|
||||
display: 'none'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const ActivityTimeline = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
avatar={<i className='tabler-list-details text-xl' />}
|
||||
title='Activity Timeline'
|
||||
titleTypographyProps={{ variant: 'h5' }}
|
||||
action={<OptionMenu options={['Share timeline', 'Suggest edits', 'Report bug']} />}
|
||||
sx={{ '& .MuiCardHeader-avatar': { mr: 3 } }}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-6 pbe-5'>
|
||||
<Timeline>
|
||||
<TimelineItem>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color='primary' />
|
||||
<TimelineConnector />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>
|
||||
<div className='flex flex-wrap items-center justify-between gap-x-2 mbe-2.5'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
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 items-center gap-2.5 is-fit rounded bg-actionHover plb-[5px] pli-2.5'>
|
||||
<img height={20} alt='invoice.pdf' src='/images/icons/pdf-document.png' />
|
||||
<Typography className='font-medium'>invoices.pdf</Typography>
|
||||
</div>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
|
||||
<TimelineItem>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color='success' />
|
||||
<TimelineConnector />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>
|
||||
<div className='flex flex-wrap items-center justify-between gap-x-2 mbe-2.5'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
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'>
|
||||
<Avatar src='/images/avatars/1.png' className='is-8 bs-8' />
|
||||
<div className='flex flex-col flex-wrap'>
|
||||
<Typography variant='body2' className='font-medium'>
|
||||
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 flex-wrap items-center justify-between gap-x-2 mbe-2.5'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
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} className='pull-up'>
|
||||
<Avatar alt='Travis Howard' src='/images/avatars/1.png' />
|
||||
<Avatar alt='Agnes Walker' src='/images/avatars/4.png' />
|
||||
<Avatar alt='John Doe' src='/images/avatars/2.png' />
|
||||
</AvatarGroup>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
</Timeline>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActivityTimeline
|
||||
@@ -0,0 +1,136 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import Chip from '@mui/material/Chip'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third-party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
const series = [{ data: [32, 52, 72, 94, 116, 94, 72] }]
|
||||
|
||||
const BarChartRevenueGrowth = () => {
|
||||
// Hook
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const successColorWithOpacity = 'var(--mui-palette-success-lightOpacity)'
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false }
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 5,
|
||||
distributed: true,
|
||||
columnWidth: '55%'
|
||||
}
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
colors: [
|
||||
successColorWithOpacity,
|
||||
successColorWithOpacity,
|
||||
successColorWithOpacity,
|
||||
successColorWithOpacity,
|
||||
'var(--mui-palette-success-main)',
|
||||
successColorWithOpacity,
|
||||
successColorWithOpacity
|
||||
],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' }
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' }
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -15,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: -5
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
tickPlacement: 'on',
|
||||
labels: {
|
||||
style: {
|
||||
colors: 'var(--mui-palette-text-disabled)',
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
fontSize: theme.typography.body2.fontSize as string
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: { show: false },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1240,
|
||||
options: {
|
||||
chart: {
|
||||
width: 150
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1200,
|
||||
options: {
|
||||
plotOptions: { bar: { columnWidth: '65%' } },
|
||||
options: {
|
||||
chart: {
|
||||
width: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 410,
|
||||
options: {
|
||||
chart: {
|
||||
width: 150
|
||||
},
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '60%' }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardContent className='flex justify-between gap-2'>
|
||||
<div className='flex flex-col justify-between'>
|
||||
<div className='flex flex-col gap-y-2'>
|
||||
<Typography variant='h5'>Revenue Growth</Typography>
|
||||
<Typography>Weekly Report</Typography>
|
||||
</div>
|
||||
<div className='flex flex-col gap-y-2 items-start'>
|
||||
<Typography variant='h3'>$4,673</Typography>
|
||||
<Chip variant='tonal' size='small' color='success' label='+15.2%' />
|
||||
</div>
|
||||
</div>
|
||||
<AppReactApexCharts type='bar' width={170} height={172} series={series} options={options} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default BarChartRevenueGrowth
|
||||
@@ -0,0 +1,127 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third-party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
// Vars
|
||||
const series = [{ data: [77, 55, 23, 43, 77, 55, 89] }]
|
||||
|
||||
const DistributedBarChartOrder = () => {
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const actionSelectedColor = 'var(--mui-palette-action-selected)'
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
stacked: false,
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
sparkline: { enabled: true }
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
legend: { show: false },
|
||||
dataLabels: { enabled: false },
|
||||
colors: ['var(--mui-palette-primary-main)'],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' }
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' }
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 3,
|
||||
horizontal: false,
|
||||
columnWidth: '32%',
|
||||
colors: {
|
||||
backgroundBarRadius: 5,
|
||||
backgroundBarColors: [
|
||||
actionSelectedColor,
|
||||
actionSelectedColor,
|
||||
actionSelectedColor,
|
||||
actionSelectedColor,
|
||||
actionSelectedColor
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
left: -3,
|
||||
right: 5,
|
||||
top: 15,
|
||||
bottom: 18
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false }
|
||||
},
|
||||
yaxis: { show: false },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1350,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '45%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: theme.breakpoints.values.lg,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '20%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '15%' }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader title='Order' subheader='Last Week' className='pbe-0' />
|
||||
<CardContent className='flex flex-col'>
|
||||
<AppReactApexCharts type='bar' height={84} width='100%' options={options} series={series} />
|
||||
<div className='flex items-center justify-between flex-wrap gap-x-4 gap-y-0.5'>
|
||||
<Typography variant='h4' color='text.primary'>
|
||||
124k
|
||||
</Typography>
|
||||
<Typography variant='body2' color='success.main'>
|
||||
+12.6%
|
||||
</Typography>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default DistributedBarChartOrder
|
||||
@@ -0,0 +1,269 @@
|
||||
'use client'
|
||||
|
||||
// React Imports
|
||||
import { useState } from 'react'
|
||||
import type { SyntheticEvent } from 'react'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import Tab from '@mui/material/Tab'
|
||||
import TabList from '@mui/lab/TabList'
|
||||
import TabPanel from '@mui/lab/TabPanel'
|
||||
import TabContext from '@mui/lab/TabContext'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import type { Theme } from '@mui/material/styles'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third Party Imports
|
||||
import classnames from 'classnames'
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
type ApexChartSeries = NonNullable<ApexOptions['series']>
|
||||
type ApexChartSeriesData = Exclude<ApexChartSeries[0], number>
|
||||
|
||||
type TabCategory = 'orders' | 'sales' | 'profit' | 'income'
|
||||
|
||||
type TabType = {
|
||||
type: TabCategory
|
||||
avatarIcon: string
|
||||
series: ApexChartSeries
|
||||
}
|
||||
|
||||
// Vars
|
||||
const tabData: TabType[] = [
|
||||
{
|
||||
type: 'orders',
|
||||
avatarIcon: 'tabler-shopping-cart',
|
||||
series: [{ data: [28, 10, 46, 38, 15, 30, 35, 28, 8] }]
|
||||
},
|
||||
{
|
||||
type: 'sales',
|
||||
avatarIcon: 'tabler-chart-bar',
|
||||
series: [{ data: [35, 25, 15, 40, 42, 25, 48, 8, 30] }]
|
||||
},
|
||||
{
|
||||
type: 'profit',
|
||||
avatarIcon: 'tabler-currency-dollar',
|
||||
series: [{ data: [10, 22, 27, 33, 42, 32, 27, 22, 8] }]
|
||||
},
|
||||
{
|
||||
type: 'income',
|
||||
avatarIcon: 'tabler-chart-pie-2',
|
||||
series: [{ data: [5, 9, 12, 18, 20, 25, 30, 36, 48] }]
|
||||
}
|
||||
]
|
||||
|
||||
const renderTabs = (value: TabCategory) => {
|
||||
return tabData.map((item, index) => (
|
||||
<Tab
|
||||
key={index}
|
||||
value={item.type}
|
||||
className='mie-4'
|
||||
label={
|
||||
<div
|
||||
className={classnames(
|
||||
'flex flex-col items-center justify-center gap-2 is-[110px] bs-[100px] border rounded-xl',
|
||||
item.type === value ? 'border-solid border-[var(--mui-palette-primary-main)]' : 'border-dashed'
|
||||
)}
|
||||
>
|
||||
<CustomAvatar variant='rounded' skin='light' size={38} {...(item.type === value && { color: 'primary' })}>
|
||||
<i className={classnames('text-[22px]', { 'text-textSecondary': item.type !== value }, item.avatarIcon)} />
|
||||
</CustomAvatar>
|
||||
<Typography className='font-medium capitalize' color='text.primary'>
|
||||
{item.type}
|
||||
</Typography>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
const renderTabPanels = (value: TabCategory, theme: Theme, options: ApexOptions, colors: string[]) => {
|
||||
return tabData.map((item, index) => {
|
||||
const max = Math.max(...((item.series[0] as ApexChartSeriesData).data as number[]))
|
||||
const seriesIndex = ((item.series[0] as ApexChartSeriesData).data as number[]).indexOf(max)
|
||||
|
||||
const finalColors = colors.map((color, i) => (seriesIndex === i ? 'var(--mui-palette-primary-main)' : color))
|
||||
|
||||
return (
|
||||
<TabPanel key={index} value={item.type} className='!p-0'>
|
||||
<AppReactApexCharts
|
||||
type='bar'
|
||||
height={233}
|
||||
width='100%'
|
||||
options={{ ...options, colors: finalColors }}
|
||||
series={item.series}
|
||||
/>
|
||||
</TabPanel>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const EarningReportsWithTabs = () => {
|
||||
// States
|
||||
const [value, setValue] = useState<TabCategory>('orders')
|
||||
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const disabledText = 'var(--mui-palette-text-disabled)'
|
||||
|
||||
const handleChange = (event: SyntheticEvent, newValue: TabCategory) => {
|
||||
setValue(newValue)
|
||||
}
|
||||
|
||||
const colors = Array(9).fill('var(--mui-palette-primary-lightOpacity)')
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false }
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 6,
|
||||
distributed: true,
|
||||
columnWidth: '33%',
|
||||
borderRadiusApplication: 'end',
|
||||
dataLabels: { position: 'top' }
|
||||
}
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: {
|
||||
offsetY: -11,
|
||||
formatter: val => `${val}k`,
|
||||
style: {
|
||||
fontWeight: 500,
|
||||
colors: ['var(--mui-palette-text-primary)'],
|
||||
fontSize: theme.typography.body1.fontSize as string
|
||||
}
|
||||
},
|
||||
colors,
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' }
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' }
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -19,
|
||||
left: -4,
|
||||
right: 0,
|
||||
bottom: -11
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { color: 'var(--mui-palette-divider)' },
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
|
||||
labels: {
|
||||
style: {
|
||||
colors: disabledText,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
fontSize: theme.typography.body2.fontSize as string
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
offsetX: -18,
|
||||
formatter: val => `$${val}k`,
|
||||
style: {
|
||||
colors: disabledText,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
fontSize: theme.typography.body2.fontSize as string
|
||||
}
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1450,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '45%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
dataLabels: {
|
||||
style: {
|
||||
fontSize: theme.typography.body2.fontSize as string
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '58%' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 500,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '70%' }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Earning Reports'
|
||||
subheader='Yearly Earnings Overview'
|
||||
action={<OptionMenu options={['Last Week', 'Last Month', 'Last Year']} />}
|
||||
/>
|
||||
<CardContent>
|
||||
<TabContext value={value}>
|
||||
<TabList
|
||||
variant='scrollable'
|
||||
scrollButtons='auto'
|
||||
onChange={handleChange}
|
||||
aria-label='earning report tabs'
|
||||
className='!border-0 mbe-10'
|
||||
sx={{
|
||||
'& .MuiTabs-indicator': { display: 'none !important' },
|
||||
'& .MuiTab-root': { padding: '0 !important', border: '0 !important' }
|
||||
}}
|
||||
>
|
||||
{renderTabs(value)}
|
||||
<Tab
|
||||
disabled
|
||||
value='add'
|
||||
label={
|
||||
<div className='flex flex-col items-center justify-center is-[110px] bs-[100px] border border-dashed rounded-xl'>
|
||||
<CustomAvatar variant='rounded' size={34}>
|
||||
<i className='tabler-plus text-textSecondary' />
|
||||
</CustomAvatar>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</TabList>
|
||||
{renderTabPanels(value, theme, options, colors)}
|
||||
</TabContext>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default EarningReportsWithTabs
|
||||
@@ -0,0 +1,164 @@
|
||||
'use client'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import Chip from '@mui/material/Chip'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Avatar from '@mui/material/Avatar'
|
||||
import { useColorScheme } from '@mui/material/styles'
|
||||
|
||||
// Third-party Imports
|
||||
import classnames from 'classnames'
|
||||
|
||||
// Types Imports
|
||||
import type { ThemeColor, SystemMode } from '@core/types'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
|
||||
// Style Imports
|
||||
import tableStyles from '@core/styles/table.module.css'
|
||||
|
||||
type DataType = {
|
||||
date: string
|
||||
trend: string
|
||||
imgName: string
|
||||
cardType: string
|
||||
cardNumber: string
|
||||
status: 'verified' | 'rejected' | 'pending' | 'on-hold'
|
||||
}
|
||||
|
||||
type StatusObj = Record<
|
||||
DataType['status'],
|
||||
{
|
||||
text: string
|
||||
color: ThemeColor
|
||||
}
|
||||
>
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
trend: '+$1,678',
|
||||
status: 'verified',
|
||||
cardType: 'Credit',
|
||||
cardNumber: '*4230',
|
||||
imgName: 'visa',
|
||||
date: `17 Mar ${new Date().getFullYear()}`
|
||||
},
|
||||
{
|
||||
trend: '-$839',
|
||||
status: 'rejected',
|
||||
cardType: 'Credit',
|
||||
cardNumber: '*5578',
|
||||
imgName: 'mastercard',
|
||||
date: `12 Feb ${new Date().getFullYear()}`
|
||||
},
|
||||
{
|
||||
trend: '+$435',
|
||||
cardType: 'ATM',
|
||||
status: 'verified',
|
||||
cardNumber: '*4567',
|
||||
imgName: 'american-express',
|
||||
date: `28 Feb ${new Date().getFullYear()}`
|
||||
},
|
||||
{
|
||||
trend: '+$2,345',
|
||||
status: 'pending',
|
||||
cardType: 'Credit',
|
||||
cardNumber: '*5699',
|
||||
imgName: 'visa',
|
||||
date: `08 Jan ${new Date().getFullYear()}`
|
||||
},
|
||||
{
|
||||
trend: '+$1,758',
|
||||
status: 'rejected',
|
||||
cardType: 'Credit',
|
||||
cardNumber: '*2451',
|
||||
imgName: 'visa',
|
||||
date: `19 Oct ${new Date().getFullYear()}`
|
||||
}
|
||||
]
|
||||
|
||||
const statusObj: StatusObj = {
|
||||
rejected: { text: 'Rejected', color: 'error' },
|
||||
pending: { text: 'Pending', color: 'secondary' },
|
||||
'on-hold': { text: 'On hold', color: 'warning' },
|
||||
verified: { text: 'Verified', color: 'success' }
|
||||
}
|
||||
|
||||
const LastTransaction = ({ serverMode }: { serverMode: SystemMode }) => {
|
||||
// Hooks
|
||||
const { mode } = useColorScheme()
|
||||
|
||||
// Vars
|
||||
const _mode = (mode === 'system' ? serverMode : mode) || serverMode
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Last Transaction'
|
||||
action={<OptionMenu options={['Show all entries', 'Refresh', 'Download']} />}
|
||||
/>
|
||||
<div className='overflow-x-auto'>
|
||||
<table className={tableStyles.table}>
|
||||
<thead className='uppercase'>
|
||||
<tr className='border-be'>
|
||||
<th className='leading-6 plb-4 pis-6 pli-2'>Card</th>
|
||||
<th className='leading-6 plb-4 pli-2'>Date</th>
|
||||
<th className='leading-6 plb-4 pli-2'>Status</th>
|
||||
<th className='leading-6 plb-4 pie-6 pli-2 text-right'>Trend</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((row, index) => (
|
||||
<tr key={index} className='border-0'>
|
||||
<td className='pis-6 pli-2 plb-3'>
|
||||
<div className='flex items-center gap-4'>
|
||||
<Avatar
|
||||
variant='rounded'
|
||||
className={classnames('is-[50px] bs-[30px]', {
|
||||
'bg-white': _mode === 'dark',
|
||||
'bg-actionHover': _mode === 'light'
|
||||
})}
|
||||
>
|
||||
<img width={30} alt={row.imgName} src={`/images/logos/${row.imgName}.png`} />
|
||||
</Avatar>
|
||||
<div className='flex flex-col'>
|
||||
<Typography color='text.primary'>{row.cardNumber}</Typography>
|
||||
<Typography variant='body2' color='text.disabled'>
|
||||
{row.cardType}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className='pli-2 plb-3'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography color='text.primary'>Sent</Typography>
|
||||
<Typography variant='body2' color='text.disabled'>
|
||||
{row.date}
|
||||
</Typography>
|
||||
</div>
|
||||
</td>
|
||||
<td className='pli-2 plb-3'>
|
||||
<Chip
|
||||
variant='tonal'
|
||||
size='small'
|
||||
label={statusObj[row.status].text}
|
||||
color={statusObj[row.status].color}
|
||||
/>
|
||||
</td>
|
||||
<td className='pli-2 plb-3 pie-6 text-right'>
|
||||
<Typography color='text.primary'>{row.trend}</Typography>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default LastTransaction
|
||||
@@ -0,0 +1,105 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third-party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
// Vars
|
||||
const series = [{ data: [40, 10, 65, 45] }]
|
||||
|
||||
const LineAreaYearlySalesChart = () => {
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const successColor = theme.palette.success.main
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
sparkline: { enabled: true }
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 2,
|
||||
curve: 'smooth'
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 10,
|
||||
bottom: 15
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
opacityTo: 0,
|
||||
opacityFrom: 1,
|
||||
shadeIntensity: 1,
|
||||
stops: [0, 100],
|
||||
colorStops: [
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
opacity: 0.4,
|
||||
color: successColor
|
||||
},
|
||||
{
|
||||
opacity: 0,
|
||||
offset: 100,
|
||||
color: 'var(--mui-palette-background-paper)'
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
monochrome: {
|
||||
enabled: true,
|
||||
shadeTo: 'light',
|
||||
shadeIntensity: 1,
|
||||
color: successColor
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false }
|
||||
},
|
||||
yaxis: { show: false }
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader title='Sales' subheader='Last Year' className='pbe-0' />
|
||||
<AppReactApexCharts type='area' height={84} width='100%' options={options} series={series} />
|
||||
<CardContent className='flex flex-col pbs-0'>
|
||||
<div className='flex items-center justify-between flex-wrap gap-x-4 gap-y-0.5'>
|
||||
<Typography variant='h4' color='text.primary'>
|
||||
175k
|
||||
</Typography>
|
||||
<Typography variant='body2' color='error.main'>
|
||||
-16.2%
|
||||
</Typography>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default LineAreaYearlySalesChart
|
||||
@@ -0,0 +1,159 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// 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 { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third Party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
import CustomAvatar from '@core/components/mui/Avatar'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
type DataType = {
|
||||
title: string
|
||||
amount: string
|
||||
trendDiff: number
|
||||
trend?: 'positive' | 'negative'
|
||||
}
|
||||
|
||||
// Vars
|
||||
const series = [
|
||||
{ data: [2000, 2000, 4000, 4000, 3050, 3050, 2050, 2050, 3050, 3050, 4700, 4700, 2750, 2750, 5700, 5700] }
|
||||
]
|
||||
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: 'Donates',
|
||||
trend: 'negative',
|
||||
amount: '$756.26',
|
||||
trendDiff: 139.34
|
||||
},
|
||||
{
|
||||
title: 'Podcasts',
|
||||
trendDiff: 576.24,
|
||||
amount: '$2,207.03'
|
||||
}
|
||||
]
|
||||
|
||||
const ProjectStatus = () => {
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const warningColor = theme.palette.warning.main
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 4,
|
||||
curve: 'straight'
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
opacityTo: 0,
|
||||
opacityFrom: 1,
|
||||
shadeIntensity: 1,
|
||||
stops: [0, 100],
|
||||
colorStops: [
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
opacity: 0.4,
|
||||
color: warningColor
|
||||
},
|
||||
{
|
||||
offset: 100,
|
||||
opacity: 0.1,
|
||||
color: 'var(--mui-palette-background-paper)'
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
monochrome: {
|
||||
enabled: true,
|
||||
shadeTo: 'light',
|
||||
shadeIntensity: 1,
|
||||
color: warningColor
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -40,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 32
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false }
|
||||
},
|
||||
yaxis: { show: false }
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader title='Project Status' action={<OptionMenu options={['Share', 'Refresh', 'Update']} />} />
|
||||
<CardContent className='flex flex-col gap-6'>
|
||||
<div className='flex items-center gap-4'>
|
||||
<CustomAvatar skin='light' variant='rounded' color='warning'>
|
||||
<i className='tabler-currency-dollar' />
|
||||
</CustomAvatar>
|
||||
<div className='flex justify-between items-center is-full'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
$4,3742
|
||||
</Typography>
|
||||
<Typography variant='body2'>Your Earnings</Typography>
|
||||
</div>
|
||||
<Typography className='font-medium' color='success.main'>
|
||||
+10.2%
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<AppReactApexCharts type='area' height={198} width='100%' series={series} options={options} />
|
||||
<div className='flex flex-col gap-4'>
|
||||
{data.map((item: DataType, index: number) => (
|
||||
<div key={index} className='flex items-center justify-between gap-4'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<div className='flex items-center gap-4'>
|
||||
<Typography>{item.amount}</Typography>
|
||||
<Typography color={`${item.trend === 'negative' ? 'error' : 'success'}.main`}>
|
||||
{`${item.trend === 'negative' ? '-' : '+'}${item.trendDiff}`}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectStatus
|
||||
@@ -0,0 +1,98 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// Third Party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
// Vars
|
||||
const series = [
|
||||
{ name: 'Sales', data: [32, 27, 27, 30, 25, 25] },
|
||||
{ name: 'Visits', data: [25, 35, 20, 20, 20, 20] }
|
||||
]
|
||||
|
||||
const RadarSalesChart = () => {
|
||||
// Hooks
|
||||
const theme = useTheme()
|
||||
|
||||
// Vars
|
||||
const textDisabled = 'var(--mui-palette-text-disabled)'
|
||||
const divider = 'var(--mui-palette-divider)'
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false }
|
||||
},
|
||||
colors: ['var(--mui-palette-primary-main)', 'var(--mui-palette-info-main)'],
|
||||
plotOptions: {
|
||||
radar: {
|
||||
polygons: {
|
||||
connectorColors: divider,
|
||||
strokeColors: divider
|
||||
}
|
||||
}
|
||||
},
|
||||
stroke: { width: 0 },
|
||||
fill: {
|
||||
opacity: [1, 0.85]
|
||||
},
|
||||
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
|
||||
markers: { size: 0 },
|
||||
legend: {
|
||||
fontSize: '13px',
|
||||
labels: { colors: 'var(--mui-palette-text-secondary)' },
|
||||
markers: { offsetY: -1, offsetX: theme.direction === 'rtl' ? 7 : -4 },
|
||||
itemMargin: { horizontal: 9 }
|
||||
},
|
||||
grid: { show: false },
|
||||
xaxis: {
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
colors: [textDisabled, textDisabled, textDisabled, textDisabled, textDisabled, textDisabled]
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: { show: false },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1200,
|
||||
options: {
|
||||
chart: {
|
||||
height: 332
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Sales'
|
||||
subheader='Last 6 Months'
|
||||
action={<OptionMenu options={['Last Month', 'Last 6 months', 'Last Year']} />}
|
||||
/>
|
||||
<CardContent>
|
||||
<AppReactApexCharts type='radar' height={373} width='100%' series={series} options={options} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default RadarSalesChart
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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'
|
||||
|
||||
// Third-party Imports
|
||||
import classnames from 'classnames'
|
||||
|
||||
// Components Imports
|
||||
import OptionMenu from '@core/components/option-menu'
|
||||
|
||||
type DataType = {
|
||||
title: string
|
||||
imgSrc: string
|
||||
subtitle: string
|
||||
trendNumber: number
|
||||
trend?: 'positive' | 'negative'
|
||||
}
|
||||
|
||||
// Vars
|
||||
const data: DataType[] = [
|
||||
{
|
||||
title: '$8.45k',
|
||||
subtitle: 'United States',
|
||||
trendNumber: 25.8,
|
||||
imgSrc: '/images/cards/us.png'
|
||||
},
|
||||
{
|
||||
title: '$7.78k',
|
||||
subtitle: 'Brazil',
|
||||
trendNumber: 16.2,
|
||||
trend: 'negative',
|
||||
imgSrc: '/images/cards/brazil.png'
|
||||
},
|
||||
{
|
||||
title: '$6.48k',
|
||||
subtitle: 'India',
|
||||
trendNumber: 12.3,
|
||||
imgSrc: '/images/cards/india.png'
|
||||
},
|
||||
{
|
||||
title: '$5.12k',
|
||||
subtitle: 'Australia',
|
||||
trendNumber: 11.9,
|
||||
trend: 'negative',
|
||||
imgSrc: '/images/cards/australia.png'
|
||||
},
|
||||
{
|
||||
title: '$4.45k',
|
||||
subtitle: 'France',
|
||||
trendNumber: 16.2,
|
||||
imgSrc: '/images/cards/france.png'
|
||||
},
|
||||
{
|
||||
title: '$3.90k',
|
||||
subtitle: 'China',
|
||||
trendNumber: 14.8,
|
||||
imgSrc: '/images/cards/china.png'
|
||||
}
|
||||
]
|
||||
|
||||
const SalesByCountries = () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title='Sales by Countries'
|
||||
subheader='Monthly Sales Overview'
|
||||
action={<OptionMenu options={['Last Week', 'Last Month', 'Last Year']} />}
|
||||
/>
|
||||
<CardContent className='flex flex-col gap-4'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className='flex items-center gap-4'>
|
||||
<img src={item.imgSrc} alt={item.subtitle} width={34} />
|
||||
<div className='flex flex-wrap justify-between items-center gap-x-4 gap-y-1 is-full'>
|
||||
<div className='flex flex-col'>
|
||||
<Typography className='font-medium' color='text.primary'>
|
||||
{item.title}
|
||||
</Typography>
|
||||
<Typography variant='body2'>{item.subtitle}</Typography>
|
||||
</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
<i
|
||||
className={classnames(
|
||||
item.trend === 'negative' ? 'tabler-chevron-down text-error' : 'tabler-chevron-up text-success',
|
||||
'text-xl'
|
||||
)}
|
||||
/>
|
||||
<Typography
|
||||
variant='h6'
|
||||
color={`${item.trend === 'negative' ? 'error' : 'success'}.main`}
|
||||
>{`${item.trendNumber}%`}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesByCountries
|
||||
Reference in New Issue
Block a user