pos-dashboard-v2/src/views/dashboards/crm/EarningReportsWithTabs.tsx
2025-08-10 15:47:04 +07:00

249 lines
6.8 KiB
TypeScript

'use client'
// React Imports
import type { SyntheticEvent } from 'react'
import { useState } from 'react'
// Next Imports
import dynamic from 'next/dynamic'
// MUI Imports
import TabContext from '@mui/lab/TabContext'
import TabList from '@mui/lab/TabList'
import TabPanel from '@mui/lab/TabPanel'
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 type { ApexOptions } from 'apexcharts'
import classnames from 'classnames'
// Components Imports
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'))
type ApexChartSeries = NonNullable<ApexOptions['series']>
type ApexChartSeriesData = Exclude<ApexChartSeries[0], number>
type TabType = {
type: string
avatarIcon: string
date: any
series: ApexChartSeries
}
const renderTabs = (tabData: TabType[], value: string) => {
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 = (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)
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={360}
width='100%'
options={{ ...options, colors: finalColors }}
series={item.series}
/>
</TabPanel>
)
})
}
const EarningReportsWithTabs = ({ data }: { data: TabType[] }) => {
// States
const [value, setValue] = useState(data[0].type)
// Hooks
const theme = useTheme()
// Vars
const disabledText = 'var(--mui-palette-text-disabled)'
const handleChange = (event: SyntheticEvent, newValue: string) => {
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 => formatShortCurrency(Number(val)),
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: data.find(item => item.type === value)?.date,
labels: {
style: {
colors: disabledText,
fontFamily: theme.typography.fontFamily,
fontSize: theme.typography.body2.fontSize as string
}
}
},
yaxis: {
labels: {
offsetX: -18,
formatter: val => `${formatShortCurrency(Number(val))}`,
style: {
colors: disabledText,
fontFamily: theme.typography.fontFamily,
fontSize: theme.typography.body2.fontSize as string
}
}
},
responsive: [
{
breakpoint: 1450,
options: {
plotOptions: {
bar: { columnWidth: '35%' }
}
}
},
{
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='Product Reports'
subheader='Yearly Earnings Overview'
action={<OptionMenu options={['Last Week', 'Last Month', 'Last Year']} />}
/>
<CardContent>
<TabContext value={value}>
{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>
)
}
export default EarningReportsWithTabs