minor visual tweaks
This commit is contained in:
@@ -62,7 +62,7 @@ export function ListReports({ reports }: ListReportsProps) {
|
|||||||
<span className="sm:hidden">Report</span>
|
<span className="sm:hidden">Report</span>
|
||||||
</Button>
|
</Button>
|
||||||
</StickyBelowHeader>
|
</StickyBelowHeader>
|
||||||
<div className="grid grid-cols-1 gap-4 p-4 sm:grid-cols-2">
|
<div className="mx-auto flex max-w-3xl flex-col gap-8 p-4 md:p-8">
|
||||||
{reports.map((report) => {
|
{reports.map((report) => {
|
||||||
const chartRange = report.range; // timeRanges[report.range];
|
const chartRange = report.range; // timeRanges[report.range];
|
||||||
return (
|
return (
|
||||||
@@ -122,12 +122,7 @@ export function ListReports({ reports }: ListReportsProps) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<div
|
<div className={cn('p-4')}>
|
||||||
className={cn(
|
|
||||||
'p-4',
|
|
||||||
report.chartType === 'bar' && 'max-h-[300px] overflow-auto'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<LazyChart
|
<LazyChart
|
||||||
{...report}
|
{...report}
|
||||||
range={range ?? report.range}
|
range={range ?? report.range}
|
||||||
|
|||||||
@@ -21,54 +21,45 @@ export default async function ProfileLastSeenServer({ projectId }: Props) {
|
|||||||
// Days since last event from users
|
// Days since last event from users
|
||||||
// group by days
|
// group by days
|
||||||
const res = await chQuery<Row>(
|
const res = await chQuery<Row>(
|
||||||
`SELECT age('days',created_at, now()) as days, count(distinct profile_id) as count FROM events where project_id = ${escape(projectId)} group by days order by days ASC`
|
`SELECT age('days',created_at, now()) as days, count(distinct profile_id) as count FROM events where project_id = ${escape(projectId)} group by days order by days ASC LIMIT 51`
|
||||||
|
);
|
||||||
|
|
||||||
|
const maxValue = Math.max(...res.map((x) => x.count));
|
||||||
|
const minValue = Math.min(...res.map((x) => x.count));
|
||||||
|
const calculateRatio = (currentValue: number) =>
|
||||||
|
Math.max(
|
||||||
|
0.1,
|
||||||
|
Math.min(1, (currentValue - minValue) / (maxValue - minValue))
|
||||||
);
|
);
|
||||||
|
|
||||||
const take = 18;
|
|
||||||
const split = take / 2;
|
|
||||||
const max = Math.max(...res.map((item) => item.count));
|
|
||||||
const renderItem = (item: Row) => (
|
const renderItem = (item: Row) => (
|
||||||
<div
|
<div className="flex w-1/12 flex-col items-center p-1">
|
||||||
key={item.days}
|
|
||||||
className="flex h-full flex-1 shrink-0 flex-col items-center"
|
|
||||||
>
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<div className="flex w-full flex-1 flex-col justify-end rounded bg-slate-200">
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn('aspect-square w-full shrink-0 rounded bg-blue-600')}
|
||||||
'w-full rounded',
|
|
||||||
item.days < split ? 'bg-blue-600' : 'bg-blue-400'
|
|
||||||
)}
|
|
||||||
style={{
|
style={{
|
||||||
height: `${(item.count / max) * 100}%`,
|
opacity: calculateRatio(item.count),
|
||||||
}}
|
}}
|
||||||
/>
|
></div>
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
{item.count} profiles last seen{' '}
|
{item.count} profiles last seen{' '}
|
||||||
{item.days === 0 ? 'today' : `${item.days} days ago`}
|
{item.days === 0 ? 'today' : `${item.days} days ago`}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<div className="mt-1 text-xs">{item.days}</div>
|
<div className="mt-1 text-[10px]">{item.days}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget className="w-full">
|
<Widget className="w-full">
|
||||||
<WidgetHead>
|
<WidgetHead>
|
||||||
<div className="title">Last seen</div>
|
<div className="title">Last seen</div>
|
||||||
</WidgetHead>
|
</WidgetHead>
|
||||||
<WidgetBody>
|
<WidgetBody>
|
||||||
<div className="flex aspect-[3/1] w-full items-end gap-1">
|
<div className="flex w-full flex-wrap items-start justify-start">
|
||||||
{res.length >= 18 ? (
|
{res.map(renderItem)}
|
||||||
<>
|
|
||||||
{res.slice(0, split).map(renderItem)}
|
|
||||||
{res.slice(-split).map(renderItem)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
res.map(renderItem)
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center text-xs text-muted-foreground">DAYS</div>
|
<div className="text-center text-xs text-muted-foreground">DAYS</div>
|
||||||
</WidgetBody>
|
</WidgetBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user