feat(FE-438): Add UniformityBarChartSkeleton and use it

This commit is contained in:
rstubryan
2025-12-26 09:49:18 +07:00
parent 8c21883aa9
commit f5f154883b
2 changed files with 184 additions and 62 deletions
@@ -2,6 +2,7 @@ import React from 'react';
import Card from '@/components/Card';
import UniformityBarChart from '@/components/pages/uniformity/chart/UniformityBarChart';
import UniformityGaugeChart from '@/components/pages/uniformity/chart/UniformityGaugeChart';
import UniformityBarChartSkeleton from './skeleton/UniformityBarChartSkeleton';
interface BarChartData {
name: string;
@@ -20,50 +21,50 @@ interface GaugeChartData {
const UniformityChart = () => {
// TODO: Replace with actual API call
const barChartData: BarChartData[] = [
{
name: '48-52',
uv: 80,
},
{
name: '52-56',
uv: 120,
},
{
name: '56-60',
uv: 160,
},
{
name: '60-64',
uv: 200,
},
{
name: '64-68',
uv: 160,
},
{
name: '68-72',
uv: 120,
},
{
name: '72-76',
uv: 80,
},
{
name: '76-80',
uv: 120,
},
{
name: '84-88',
uv: 160,
},
{
name: '88-92',
uv: 200,
},
{
name: '92-96',
uv: 160,
},
// {
// name: '48-52',
// uv: 80,
// },
// {
// name: '52-56',
// uv: 120,
// },
// {
// name: '56-60',
// uv: 160,
// },
// {
// name: '60-64',
// uv: 200,
// },
// {
// name: '64-68',
// uv: 160,
// },
// {
// name: '68-72',
// uv: 120,
// },
// {
// name: '72-76',
// uv: 80,
// },
// {
// name: '76-80',
// uv: 120,
// },
// {
// name: '84-88',
// uv: 160,
// },
// {
// name: '88-92',
// uv: 200,
// },
// {
// name: '92-96',
// uv: 160,
// },
];
// TODO: Replace with actual API call
@@ -87,26 +88,43 @@ const UniformityChart = () => {
}}
>
<div className='w-full h-full flex items-center justify-center'>
<UniformityBarChart data={barChartData} />
{barChartData.length === 0 ? (
<UniformityBarChartSkeleton />
) : (
<UniformityBarChart data={barChartData} />
)}
</div>
</Card>
<Card
variant='bordered'
title='Weekly Performance ⓘ'
className={{
wrapper: 'xl:col-span-1 2xl:col-span-1 w-full',
body: 'p-4',
}}
>
<UniformityGaugeChart
value={gaugeChartData.value}
label={gaugeChartData.label}
kandang={gaugeChartData.kandang}
week={gaugeChartData.week}
currentValue={gaugeChartData.currentValue}
totalValue={gaugeChartData.totalValue}
/>
</Card>
{gaugeChartData.value === 0 ? (
<Card
variant='bordered'
title='Weekly Performance ⓘ'
className={{
wrapper: 'xl:col-span-1 2xl:col-span-1 w-full',
body: 'h-96',
}}
>
<UniformityBarChartSkeleton />
</Card>
) : (
<Card
variant='bordered'
title='Weekly Performance ⓘ'
className={{
wrapper: 'xl:col-span-1 2xl:col-span-1 w-full',
body: 'p-4',
}}
>
<UniformityGaugeChart
value={gaugeChartData.value}
label={gaugeChartData.label}
kandang={gaugeChartData.kandang}
week={gaugeChartData.week}
currentValue={gaugeChartData.currentValue}
totalValue={gaugeChartData.totalValue}
/>
</Card>
)}
</section>
);
};
@@ -0,0 +1,104 @@
import Button from '@/components/Button';
import { Icon } from '@iconify/react';
const LeftLegend = () => {
return (
<>
<div className='w-4 h-30 bg-gray-200 rounded animate-pulse flex items-center justify-center self-center'></div>
<div className='grid grid-cols-1 justify-center items-center'>
<div className='shrink-0 flex flex-col justify-center'>
<div className='h-4 w-8 bg-gray-200 rounded animate-pulse' />
</div>
<div className='shrink-0 flex flex-col justify-center'>
<div className='h-4 w-8 bg-gray-200 rounded animate-pulse' />
</div>
<div className='shrink-0 flex flex-col justify-center'>
<div className='h-4 w-8 bg-gray-200 rounded animate-pulse' />
</div>
<div className='shrink-0 flex flex-col justify-center'>
<div className='h-4 w-8 bg-gray-200 rounded animate-pulse' />
</div>
</div>
</>
);
};
const ChartArea = () => {
const ranges = [
'48-52',
'52-56',
'56-60',
'60-64',
'64-68',
'68-72',
'72-76',
];
return (
<>
<div className='flex-1 flex flex-col relative'>
<div className='flex-1 ml-6 flex flex-col'>
<div className='flex-1 relative flex flex-col justify-between py-4'>
{[...Array(5)].map((_, index) => (
<div
key={`grid-${index}`}
className='w-full border-b border-gray-200 absolute'
style={{ top: `${(index / 4) * 100}%` }}
/>
))}
</div>
<div className='flex justify-between gap-10 px-4 py-2'>
{ranges.map((range) => (
<div
key={range}
className='flex-1 h-3 bg-gray-200 rounded animate-pulse'
style={{ animationDelay: '0.5s' }}
/>
))}
</div>
<div className='flex justify-center pb-1'>
<div className='h-3 w-28 bg-gray-200 rounded animate-pulse' />
</div>
</div>
</div>
</>
);
};
const EmptyState = () => {
return (
<>
<div className='absolute inset-0 flex flex-col items-center justify-center z-10 gap-2'>
<div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center my-2'>
<Button className='rounded-2xl border border-sky-500 bg-[#0069E0] text-white'>
<Icon icon={'heroicons:funnel'} className='text-4xl text-whitd' />
</Button>
</div>
<span className='text-xl font-semibold text-[#18181B80] leading-5'>
No Filters Selected
</span>
<span className='text-xs font-light text-[#18181B80] leading-4 text-center max-w-xs px-4'>
Please choose filters to narrow down your results and make your search
easier.
</span>
</div>
</>
);
};
const UniformityBarChartSkeleton = () => {
return (
<div className='relative w-full h-full min-h-[300px] xl:min-h-[350px]'>
<div className='flex h-full gap-4'>
<LeftLegend />
<ChartArea />
</div>
<EmptyState />
</div>
);
};
export default UniformityBarChartSkeleton;