feat: add bar and subscription chart components, update dashboard integration
This commit is contained in:
parent
bd92f9a09f
commit
6a00b9207e
@ -3,12 +3,29 @@ import {
|
|||||||
ArcElement,
|
ArcElement,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Legend,
|
Legend,
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
BarElement,
|
||||||
|
Title,
|
||||||
type ChartOptions,
|
type ChartOptions,
|
||||||
|
type ChartEvent,
|
||||||
|
type ActiveElement,
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { Pie } from 'react-chartjs-2'
|
import { useState } from 'react'
|
||||||
ChartJS.register(ArcElement, Tooltip, Legend)
|
import { Bar, Doughnut, Pie } from 'react-chartjs-2'
|
||||||
|
ChartJS.register(
|
||||||
|
ArcElement,
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
BarElement,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
Legend,
|
||||||
|
)
|
||||||
|
|
||||||
export const ChartPie = () => {
|
type HandleChartClick = (event: ChartEvent, elements: ActiveElement[]) => void
|
||||||
|
|
||||||
|
export const UiChartPie = () => {
|
||||||
const data = {
|
const data = {
|
||||||
labels: [
|
labels: [
|
||||||
'Pidana',
|
'Pidana',
|
||||||
@ -64,3 +81,147 @@ export const ChartPie = () => {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const UiChartBar = () => {
|
||||||
|
const yearlyData = {
|
||||||
|
labels: ['2022', '2023', '2024'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Total Sales',
|
||||||
|
data: [800, 950, 1200],
|
||||||
|
backgroundColor: '#1E3A8A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const monthlyData = {
|
||||||
|
labels: [
|
||||||
|
'Jan',
|
||||||
|
'Feb',
|
||||||
|
'Mar',
|
||||||
|
'Apr',
|
||||||
|
'May',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Aug',
|
||||||
|
'Sep',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Dec',
|
||||||
|
],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Monthly Sales',
|
||||||
|
data: [70, 90, 750, 80, 90, 95, 75, 85, 78, 88, 95, 0],
|
||||||
|
backgroundColor: '#2E2F7C',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const [view, setView] = useState('month') // Default tampil bulanan
|
||||||
|
const [selectedYear, setSelectedYear] = useState('')
|
||||||
|
|
||||||
|
const handleChartClick: HandleChartClick = (event, elements) => {
|
||||||
|
if (elements.length > 0 && view === 'year') {
|
||||||
|
const clickedIndex = elements[0].index
|
||||||
|
const year = yearlyData.labels[clickedIndex]
|
||||||
|
setSelectedYear(year)
|
||||||
|
setView('month')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBackToYear = () => {
|
||||||
|
setView('year')
|
||||||
|
setSelectedYear('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
onClick: handleChartClick,
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
max: selectedYear ? 100 : 1500,
|
||||||
|
ticks: {
|
||||||
|
stepSize: 25,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl bg-white p-6 shadow-lg">
|
||||||
|
<div className="mb-4 flex items-center justify-between">
|
||||||
|
<h2 className="text-xl font-bold">
|
||||||
|
{view === 'year'
|
||||||
|
? 'Penjualan Tahunan'
|
||||||
|
: `Penjualan Bulanan ${selectedYear || '2024'}`}
|
||||||
|
</h2>
|
||||||
|
{view === 'month' && (
|
||||||
|
<button
|
||||||
|
className="rounded-lg bg-gray-200 px-4 py-2"
|
||||||
|
onClick={handleBackToYear}
|
||||||
|
>
|
||||||
|
Tahun
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Bar
|
||||||
|
data={view === 'year' ? yearlyData : monthlyData}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChartSubscription = () => {
|
||||||
|
const data = {
|
||||||
|
labels: ['Selesai', 'Belum Selesai'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: [70, 30],
|
||||||
|
backgroundColor: ['#1e3a8a', '#e5e7eb'],
|
||||||
|
borderWidth: 0,
|
||||||
|
cutout: '70%',
|
||||||
|
circumference: 180,
|
||||||
|
rotation: 270,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: ChartOptions<'doughnut'> = {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
position: 'right',
|
||||||
|
labels: {
|
||||||
|
usePointStyle: true,
|
||||||
|
pointStyle: 'circle',
|
||||||
|
boxWidth: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl bg-white p-6 shadow-lg">
|
||||||
|
<h2 className="mb-4 text-[20px]">Subscription Selesai</h2>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div style={{ height: '200px', width: '100%' }}>
|
||||||
|
<Doughnut
|
||||||
|
data={data}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -1,10 +1,28 @@
|
|||||||
import { CardReport } from '~/components/ui/card-report'
|
import { CardReport } from '~/components/ui/card-report'
|
||||||
import { ChartPie } from '~/components/ui/chart'
|
import {
|
||||||
|
ChartSubscription,
|
||||||
|
UiChartBar,
|
||||||
|
UiChartPie,
|
||||||
|
} from '~/components/ui/chart'
|
||||||
|
|
||||||
import { HISTORY, REPORT } from './data'
|
import { HISTORY, REPORT } from './data'
|
||||||
export const DashboardPage = () => {
|
export const DashboardPage = () => {
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
<section className="mb-5 flex items-center justify-between">
|
||||||
|
<h1 className="text-xl font-bold">Dashboard</h1>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span>Tanggal:</span>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="rounded border p-2"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="rounded border p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<div className="mt-5 grid grid-cols-1 grid-rows-1 gap-6 sm:grid-cols-3">
|
<div className="mt-5 grid grid-cols-1 grid-rows-1 gap-6 sm:grid-cols-3">
|
||||||
{REPORT.map(({ title, amount, icon }, index) => (
|
{REPORT.map(({ title, amount, icon }, index) => (
|
||||||
<CardReport
|
<CardReport
|
||||||
@ -27,28 +45,22 @@ export const DashboardPage = () => {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<div className="max-h-[300px] sm:col-span-2 sm:col-start-2 sm:row-span-2 sm:row-start-1">
|
<div className="max-h-[300px] sm:col-span-2 sm:col-start-2 sm:row-span-2 sm:row-start-1">
|
||||||
<ChartPie />
|
<UiChartPie />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="my-5 grid grid-cols-1 grid-rows-2 gap-6 sm:grid-cols-5 sm:grid-rows-1">
|
<div className="mt-5 grid max-h-[280px] grid-cols-1 grid-rows-2 gap-6 sm:grid-cols-5 sm:grid-rows-1">
|
||||||
<div className="sm:col-span-3">
|
<div className="sm:col-span-3">
|
||||||
<div className="h-30 w-full">
|
<div className="h-30 w-full">
|
||||||
<div className="shadow-sm">
|
<div className="shadow-sm">
|
||||||
<img
|
<UiChartBar />
|
||||||
src="/images/dummy-chart-1.svg"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="sm:col-span-2 sm:col-start-4">
|
<div className="sm:col-span-2 sm:col-start-4">
|
||||||
<div className="h-30 w-full">
|
<div className="h-30 w-full">
|
||||||
<div className="shadow-sm">
|
<div className="shadow-sm">
|
||||||
<img
|
<ChartSubscription />
|
||||||
src="/images/dummy-chart-3.svg"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user