feat: analytic

This commit is contained in:
ferdiansyah783
2025-08-08 17:59:39 +07:00
parent 7beee4c3a1
commit 67b747f0ff
34 changed files with 1227 additions and 2834 deletions
@@ -1,123 +1,56 @@
'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'
import classnames from 'classnames'
import CustomAvatar, { CustomAvatarProps } from '../../../@core/components/mui/Avatar'
import { ThemeColor } from '../../../@core/types'
import { Skeleton, Typography } from '@mui/material'
import { formatShortCurrency } from '../../../utils/transform'
// Styled Component Imports
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
type Props = {
title: string
value: number
isLoading: boolean
avatarIcon: string
avatarSkin?: CustomAvatarProps['skin']
avatarSize?: number
avatarColor?: ThemeColor
}
// Vars
const series = [{ data: [77, 55, 23, 43, 77, 55, 89] }]
const DistributedBarChartOrder = ({
title,
value,
isLoading,
avatarIcon,
avatarSkin,
avatarColor
}: Props) => {
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%' }
}
}
}
]
if (isLoading) {
return <Skeleton sx={{ bgcolor: 'grey.100' }} variant='rectangular' width={300} height={118} />
}
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>
<CardContent>
<div className='flex items-start justify-between'>
<div className='flex-1'>
<Typography variant='h6' color='text.disabled'>
{title}
</Typography>
<Typography color='text.primary' variant='h4'>
{formatShortCurrency(value)}
</Typography>
</div>
<CustomAvatar variant='rounded' skin={avatarSkin} size={52} color={avatarColor}>
<i className={classnames(avatarIcon, 'text-[28px]')} />
</CustomAvatar>
</div>
</CardContent>
</Card>
@@ -1,31 +1,33 @@
'use client'
// React Imports
import { useState } from 'react'
import type { SyntheticEvent } from 'react'
import { useState } 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 TabContext from '@mui/lab/TabContext'
import TabList from '@mui/lab/TabList'
import TabPanel from '@mui/lab/TabPanel'
import TabContext from '@mui/lab/TabContext'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import CardHeader from '@mui/material/CardHeader'
import Tab from '@mui/material/Tab'
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'
import classnames from 'classnames'
// Components Imports
import OptionMenu from '@core/components/option-menu'
import CustomAvatar from '@core/components/mui/Avatar'
import OptionMenu from '@core/components/option-menu'
import Loading from '../../../components/layout/shared/Loading'
import { formatShortCurrency } from '../../../utils/transform'
// Styled Component Imports
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
@@ -33,39 +35,14 @@ const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexChart
type ApexChartSeries = NonNullable<ApexOptions['series']>
type ApexChartSeriesData = Exclude<ApexChartSeries[0], number>
type TabCategory = 'orders' | 'sales' | 'profit' | 'income'
type TabType = {
type: TabCategory
type: string
avatarIcon: string
date: any
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) => {
const renderTabs = (tabData: TabType[], value: string) => {
return tabData.map((item, index) => (
<Tab
key={index}
@@ -90,7 +67,7 @@ const renderTabs = (value: TabCategory) => {
))
}
const renderTabPanels = (value: TabCategory, theme: Theme, options: ApexOptions, colors: string[]) => {
const renderTabPanels = (tabData: TabType[], 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)
@@ -101,7 +78,7 @@ const renderTabPanels = (value: TabCategory, theme: Theme, options: ApexOptions,
<TabPanel key={index} value={item.type} className='!p-0'>
<AppReactApexCharts
type='bar'
height={233}
height={360}
width='100%'
options={{ ...options, colors: finalColors }}
series={item.series}
@@ -111,9 +88,9 @@ const renderTabPanels = (value: TabCategory, theme: Theme, options: ApexOptions,
})
}
const EarningReportsWithTabs = () => {
const EarningReportsWithTabs = ({ data }: { data: TabType[] }) => {
// States
const [value, setValue] = useState<TabCategory>('orders')
const [value, setValue] = useState(data[0].type)
// Hooks
const theme = useTheme()
@@ -121,7 +98,7 @@ const EarningReportsWithTabs = () => {
// Vars
const disabledText = 'var(--mui-palette-text-disabled)'
const handleChange = (event: SyntheticEvent, newValue: TabCategory) => {
const handleChange = (event: SyntheticEvent, newValue: string) => {
setValue(newValue)
}
@@ -145,7 +122,7 @@ const EarningReportsWithTabs = () => {
tooltip: { enabled: false },
dataLabels: {
offsetY: -11,
formatter: val => `${val}k`,
formatter: val => formatShortCurrency(Number(val)),
style: {
fontWeight: 500,
colors: ['var(--mui-palette-text-primary)'],
@@ -173,7 +150,7 @@ const EarningReportsWithTabs = () => {
xaxis: {
axisTicks: { show: false },
axisBorder: { color: 'var(--mui-palette-divider)' },
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
categories: data.find(item => item.type === value)?.date,
labels: {
style: {
colors: disabledText,
@@ -185,7 +162,7 @@ const EarningReportsWithTabs = () => {
yaxis: {
labels: {
offsetX: -18,
formatter: val => `$${val}k`,
formatter: val => `${formatShortCurrency(Number(val))}`,
style: {
colors: disabledText,
fontFamily: theme.typography.fontFamily,
@@ -235,31 +212,33 @@ const EarningReportsWithTabs = () => {
/>
<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)}
{data.length > 1 && (
<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(data, 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(data, theme, options, colors)}
</TabContext>
</CardContent>
</Card>
+2 -2
View File
@@ -88,12 +88,12 @@ const statusObj: StatusObj = {
verified: { text: 'Verified', color: 'success' }
}
const LastTransaction = ({ serverMode }: { serverMode: SystemMode }) => {
const LastTransaction = () => {
// Hooks
const { mode } = useColorScheme()
// Vars
const _mode = (mode === 'system' ? serverMode : mode) || serverMode
const _mode = mode as SystemMode
return (
<Card>