| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import {
- Card,
- CardContent,
- CardDescription,
- CardHeader,
- CardTitle,
- } from '@/components/ui/card'
- import { AnalyticsChart } from './analytics-chart'
- export function Analytics() {
- return (
- <div className='space-y-4'>
- <Card>
- <CardHeader>
- <CardTitle>Traffic Overview</CardTitle>
- <CardDescription>Weekly clicks and unique visitors</CardDescription>
- </CardHeader>
- <CardContent className='px-6'>
- <AnalyticsChart />
- </CardContent>
- </Card>
- <div className='grid gap-4 sm:grid-cols-2 lg:grid-cols-4'>
- <Card>
- <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>
- <CardTitle className='text-sm font-medium'>Total Clicks</CardTitle>
- <svg
- xmlns='http://www.w3.org/2000/svg'
- viewBox='0 0 24 24'
- fill='none'
- stroke='currentColor'
- strokeLinecap='round'
- strokeLinejoin='round'
- strokeWidth='2'
- className='text-muted-foreground h-4 w-4'
- >
- <path d='M3 3v18h18' />
- <path d='M7 15l4-4 4 4 4-6' />
- </svg>
- </CardHeader>
- <CardContent>
- <div className='text-2xl font-bold'>1,248</div>
- <p className='text-muted-foreground text-xs'>+12.4% vs last week</p>
- </CardContent>
- </Card>
- <Card>
- <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>
- <CardTitle className='text-sm font-medium'>
- Unique Visitors
- </CardTitle>
- <svg
- xmlns='http://www.w3.org/2000/svg'
- viewBox='0 0 24 24'
- fill='none'
- stroke='currentColor'
- strokeLinecap='round'
- strokeLinejoin='round'
- strokeWidth='2'
- className='text-muted-foreground h-4 w-4'
- >
- <circle cx='12' cy='7' r='4' />
- <path d='M6 21v-2a6 6 0 0 1 12 0v2' />
- </svg>
- </CardHeader>
- <CardContent>
- <div className='text-2xl font-bold'>832</div>
- <p className='text-muted-foreground text-xs'>+5.8% vs last week</p>
- </CardContent>
- </Card>
- <Card>
- <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>
- <CardTitle className='text-sm font-medium'>Bounce Rate</CardTitle>
- <svg
- xmlns='http://www.w3.org/2000/svg'
- viewBox='0 0 24 24'
- fill='none'
- stroke='currentColor'
- strokeLinecap='round'
- strokeLinejoin='round'
- strokeWidth='2'
- className='text-muted-foreground h-4 w-4'
- >
- <path d='M3 12h6l3 6 3-6h6' />
- </svg>
- </CardHeader>
- <CardContent>
- <div className='text-2xl font-bold'>42%</div>
- <p className='text-muted-foreground text-xs'>-3.2% vs last week</p>
- </CardContent>
- </Card>
- <Card>
- <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>
- <CardTitle className='text-sm font-medium'>Avg. Session</CardTitle>
- <svg
- xmlns='http://www.w3.org/2000/svg'
- viewBox='0 0 24 24'
- fill='none'
- stroke='currentColor'
- strokeLinecap='round'
- strokeLinejoin='round'
- strokeWidth='2'
- className='text-muted-foreground h-4 w-4'
- >
- <circle cx='12' cy='12' r='10' />
- <path d='M12 6v6l4 2' />
- </svg>
- </CardHeader>
- <CardContent>
- <div className='text-2xl font-bold'>3m 24s</div>
- <p className='text-muted-foreground text-xs'>+18s vs last week</p>
- </CardContent>
- </Card>
- </div>
- <div className='grid grid-cols-1 gap-4 lg:grid-cols-7'>
- <Card className='col-span-1 lg:col-span-4'>
- <CardHeader>
- <CardTitle>Referrers</CardTitle>
- <CardDescription>Top sources driving traffic</CardDescription>
- </CardHeader>
- <CardContent>
- <SimpleBarList
- items={[
- { name: 'Direct', value: 512 },
- { name: 'Product Hunt', value: 238 },
- { name: 'Twitter', value: 174 },
- { name: 'Blog', value: 104 },
- ]}
- barClass='bg-primary'
- valueFormatter={(n) => `${n}`}
- />
- </CardContent>
- </Card>
- <Card className='col-span-1 lg:col-span-3'>
- <CardHeader>
- <CardTitle>Devices</CardTitle>
- <CardDescription>How users access your app</CardDescription>
- </CardHeader>
- <CardContent>
- <SimpleBarList
- items={[
- { name: 'Desktop', value: 74 },
- { name: 'Mobile', value: 22 },
- { name: 'Tablet', value: 4 },
- ]}
- barClass='bg-muted-foreground'
- valueFormatter={(n) => `${n}%`}
- />
- </CardContent>
- </Card>
- </div>
- </div>
- )
- }
- function SimpleBarList({
- items,
- valueFormatter,
- barClass,
- }: {
- items: { name: string; value: number }[]
- valueFormatter: (n: number) => string
- barClass: string
- }) {
- const max = Math.max(...items.map((i) => i.value), 1)
- return (
- <ul className='space-y-3'>
- {items.map((i) => {
- const width = `${Math.round((i.value / max) * 100)}%`
- return (
- <li key={i.name} className='flex items-center justify-between gap-3'>
- <div className='min-w-0 flex-1'>
- <div className='text-muted-foreground mb-1 truncate text-xs'>
- {i.name}
- </div>
- <div className='bg-muted h-2.5 w-full rounded-full'>
- <div
- className={`h-2.5 rounded-full ${barClass}`}
- style={{ width }}
- />
- </div>
- </div>
- <div className='ps-2 text-xs font-medium tabular-nums'>
- {valueFormatter(i.value)}
- </div>
- </li>
- )
- })}
- </ul>
- )
- }
|