chrts + revensure chart
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
import { ArrowUp, DocumentDownload } from 'iconsax-react'
|
||||
import { type FC, useState } from 'react'
|
||||
import {
|
||||
Area,
|
||||
AreaChart,
|
||||
CartesianGrid,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
YAxis
|
||||
} from 'recharts'
|
||||
import DatePicker from '@/components/DatePicker'
|
||||
import Button from '@/components/Button'
|
||||
|
||||
interface RevenueChartProps {
|
||||
data?: Array<{ month: string; online: number; cash: number }>
|
||||
}
|
||||
|
||||
const RevenueChart: FC<RevenueChartProps> = ({ data }) => {
|
||||
const [selectedTab, setSelectedTab] = useState<
|
||||
'daily' | 'monthly' | 'yearly'
|
||||
>('monthly')
|
||||
|
||||
const defaultData = [
|
||||
{ month: 'فروردین', online: 10000000, cash: 8000000 },
|
||||
{ month: 'اردیبهشت', online: 15000000, cash: 11000000 },
|
||||
{ month: 'خرداد', online: 12000000, cash: 9000000 },
|
||||
{ month: 'تیر', online: 18000000, cash: 13000000 },
|
||||
{ month: 'مرداد', online: 16000000, cash: 12000000 },
|
||||
{ month: 'شهریور', online: 22000000, cash: 15000000 },
|
||||
{ month: 'مهر', online: 20000000, cash: 14000000 },
|
||||
{ month: 'آبان', online: 17000000, cash: 13000000 },
|
||||
{ month: 'آذر', online: 14000000, cash: 11000000 },
|
||||
{ month: 'دی', online: 12000000, cash: 10000000 },
|
||||
{ month: 'بهمن', online: 18000000, cash: 13000000 },
|
||||
{ month: 'اسفند', online: 16000000, cash: 12000000 }
|
||||
]
|
||||
|
||||
const chartData = data || defaultData
|
||||
|
||||
const formatYAxis = (value: number) => {
|
||||
if (value === 0) return '۰'
|
||||
if (value >= 1000000) {
|
||||
const millions = value / 1000000
|
||||
const formatted = millions
|
||||
.toFixed(1)
|
||||
.replace(/\d/g, (d) => '۰۱۲۳۴۵۶۷۸۹'[parseInt(d)])
|
||||
return `${formatted} میلیون`
|
||||
}
|
||||
return value.toLocaleString('fa-IR')
|
||||
}
|
||||
|
||||
const formatTooltip = (value: number | undefined) => {
|
||||
if (value === undefined) return ''
|
||||
return value.toLocaleString('fa-IR') + ' تومان'
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='bg-white rounded-3xl p-6 shadow-sm h-full overflow-visible'>
|
||||
{/* Header */}
|
||||
<div className='flex items-start justify-between mb-5'>
|
||||
<h3 className='text-base font-bold'>مجموع درآمد</h3>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div className='flex items-end gap-2'>
|
||||
<DatePicker
|
||||
label='تاریخ شروع'
|
||||
placeholder='mm/dd/yyyy'
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<DatePicker
|
||||
label='تاریخ پایان'
|
||||
placeholder='mm/dd/yyyy'
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<Button className=''>
|
||||
<div className='flex gap-3'>
|
||||
<DocumentDownload
|
||||
size={18}
|
||||
color='#fff'
|
||||
/>
|
||||
<span>گرفتن گزارش</span>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className='flex items-center gap-2 mt-5 mb-5'>
|
||||
<button
|
||||
onClick={() => setSelectedTab('yearly')}
|
||||
className={`px-4 py-1.5 rounded-full text-xs transition-all border ${selectedTab === 'yearly'
|
||||
? 'bg-black text-white border-black'
|
||||
: 'bg-white text-gray-600 border-gray-200'
|
||||
}`}
|
||||
>
|
||||
سالانه
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedTab('monthly')}
|
||||
className={`px-4 py-1.5 rounded-full text-xs transition-all border ${selectedTab === 'monthly'
|
||||
? 'bg-black text-white border-black'
|
||||
: 'bg-white text-gray-600 border-gray-200'
|
||||
}`}
|
||||
>
|
||||
ماهانه
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedTab('daily')}
|
||||
className={`px-4 py-1.5 rounded-full text-xs transition-all border ${selectedTab === 'daily'
|
||||
? 'bg-black text-white border-black'
|
||||
: 'bg-white text-gray-600 border-gray-200'
|
||||
}`}
|
||||
>
|
||||
روزانه
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* مبلغ و درصد */}
|
||||
|
||||
<div>
|
||||
<span className='text-sm text-gray-500'>مجموع درآمد</span>
|
||||
|
||||
</div>
|
||||
<div className='flex items-center justify-between mb-5'>
|
||||
<div className='flex items-center gap-3'>
|
||||
|
||||
<p className='text-2xl font-bold'>۲۰,۰۰۰,۰۰۰ تومان</p>
|
||||
<div className='flex items-center gap-1 px-2 py-0.5 bg-green-50 rounded-full'>
|
||||
<ArrowUp
|
||||
size={12}
|
||||
color='#10b981'
|
||||
/>
|
||||
<span className='text-xs font-medium text-green-600'>
|
||||
2,5%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex items-center gap-3'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='w-2 h-2 rounded-full bg-[#6B7FED]' />
|
||||
<span className='text-xs text-gray-500'>
|
||||
پرداخت آنلاین
|
||||
</span>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='w-2 h-2 rounded-full bg-[#B0BAC9]' />
|
||||
<span className='text-xs text-gray-500'>
|
||||
پرداخت نقدی
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* نمودار */}
|
||||
<div className='w-full h-[400px] min-h-[400px]'>
|
||||
<ResponsiveContainer width='100%' height='100%'>
|
||||
<AreaChart
|
||||
data={chartData}
|
||||
margin={{ top: 10, right: 10, left: 10, bottom: 40 }}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id='colorOnline'
|
||||
x1='0'
|
||||
y1='0'
|
||||
x2='0'
|
||||
y2='1'
|
||||
>
|
||||
<stop
|
||||
offset='5%'
|
||||
stopColor='#6B7FED'
|
||||
stopOpacity={0.3}
|
||||
/>
|
||||
<stop
|
||||
offset='95%'
|
||||
stopColor='#6B7FED'
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id='colorCash'
|
||||
x1='0'
|
||||
y1='0'
|
||||
x2='0'
|
||||
y2='1'
|
||||
>
|
||||
<stop
|
||||
offset='5%'
|
||||
stopColor='#B0BAC9'
|
||||
stopOpacity={0.2}
|
||||
/>
|
||||
<stop
|
||||
offset='95%'
|
||||
stopColor='#B0BAC9'
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<CartesianGrid
|
||||
strokeDasharray='0'
|
||||
stroke='#f0f0f0'
|
||||
vertical={false}
|
||||
/>
|
||||
<XAxis
|
||||
dataKey='month'
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fill: '#9CA3AF', fontSize: 11 }}
|
||||
reversed
|
||||
interval={0}
|
||||
angle={0}
|
||||
textAnchor='middle'
|
||||
height={40}
|
||||
/>
|
||||
<YAxis
|
||||
orientation='right'
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fill: '#9CA3AF', fontSize: 10 }}
|
||||
tickFormatter={formatYAxis}
|
||||
domain={[0, 'dataMax + 2000000']}
|
||||
tickMargin={50}
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={formatTooltip}
|
||||
contentStyle={{
|
||||
backgroundColor: 'white',
|
||||
border: '1px solid #e5e7eb',
|
||||
borderRadius: '12px',
|
||||
fontSize: '12px'
|
||||
}}
|
||||
/>
|
||||
<Area
|
||||
type='natural'
|
||||
dataKey='cash'
|
||||
stroke='#B0BAC9'
|
||||
strokeWidth={2}
|
||||
fillOpacity={1}
|
||||
fill='url(#colorCash)'
|
||||
/>
|
||||
<Area
|
||||
type='natural'
|
||||
dataKey='online'
|
||||
stroke='#6B7FED'
|
||||
strokeWidth={2}
|
||||
fillOpacity={1}
|
||||
fill='url(#colorOnline)'
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default RevenueChart
|
||||
Reference in New Issue
Block a user