update dashboard metrics and move away from round corners

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-05-20 21:22:20 +02:00
parent 4350670bbc
commit 3ecdf54d5c
13 changed files with 125 additions and 137 deletions

View File

@@ -12,8 +12,6 @@ import { useQueryClient } from '@tanstack/react-query';
import dynamic from 'next/dynamic';
import { toast } from 'sonner';
import { useOverviewOptions } from '../useOverviewOptions';
export interface LiveCounterProps {
data: number;
projectId: string;
@@ -27,7 +25,6 @@ const AnimatedNumbers = dynamic(() => import('react-animated-numbers'), {
const FIFTEEN_SECONDS = 1000 * 15;
export default function LiveCounter({ data = 0, projectId }: LiveCounterProps) {
const { setLiveHistogram } = useOverviewOptions();
const client = useQueryClient();
const [counter, setCounter] = useState(data);
const lastRefresh = useRef(Date.now());
@@ -47,38 +44,33 @@ export default function LiveCounter({ data = 0, projectId }: LiveCounterProps) {
return (
<Tooltip>
<TooltipTrigger asChild>
<button
onClick={() => setLiveHistogram((p) => !p)}
className="flex h-8 items-center gap-2 rounded border border-border px-3 font-medium leading-none"
>
<div className="relative">
<div
className={cn(
'h-3 w-3 animate-ping rounded-full bg-emerald-500 opacity-100 transition-all',
counter === 0 && 'bg-destructive opacity-0'
)}
></div>
<div
className={cn(
'absolute left-0 top-0 h-3 w-3 rounded-full bg-emerald-500 transition-all',
counter === 0 && 'bg-destructive'
)}
></div>
</div>
<AnimatedNumbers
includeComma
transitions={(index) => ({
type: 'spring',
duration: index + 0.3,
damping: 10,
stiffness: 200,
})}
animateToNumber={counter}
locale="en"
<TooltipTrigger className="flex h-8 items-center gap-2 rounded border border-border px-3 font-medium leading-none">
<div className="relative">
<div
className={cn(
'h-3 w-3 animate-ping rounded-full bg-emerald-500 opacity-100 transition-all',
counter === 0 && 'bg-destructive opacity-0'
)}
/>
</button>
<div
className={cn(
'absolute left-0 top-0 h-3 w-3 rounded-full bg-emerald-500 transition-all',
counter === 0 && 'bg-destructive'
)}
/>
</div>
<AnimatedNumbers
includeComma
transitions={(index) => ({
type: 'spring',
duration: index + 0.3,
damping: 10,
stiffness: 200,
})}
animateToNumber={counter}
locale="en"
/>
</TooltipTrigger>
<TooltipContent side="bottom">
<p>{counter} unique visitors last 5 minutes</p>

View File

@@ -5,9 +5,7 @@ import { cn } from '@/utils/cn';
import type { IChartInput } from '@openpanel/validation';
import AnimateHeight from '../animate-height';
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
import { useOverviewOptions } from './useOverviewOptions';
interface OverviewLiveHistogramProps {
projectId: string;
@@ -16,7 +14,6 @@ interface OverviewLiveHistogramProps {
export function OverviewLiveHistogram({
projectId,
}: OverviewLiveHistogramProps) {
const { liveHistogram } = useOverviewOptions();
const report: IChartInput = {
projectId,
events: [
@@ -80,11 +77,11 @@ export function OverviewLiveHistogram({
];
return (
<Wrapper count={0} open={liveHistogram}>
<Wrapper count={0}>
{staticArray.map((percent, i) => (
<div
key={i}
className="flex-1 animate-pulse rounded-md bg-slate-200 dark:bg-slate-800"
className="flex-1 animate-pulse rounded bg-slate-200 dark:bg-slate-800"
style={{ height: `${percent}%` }}
/>
))}
@@ -97,14 +94,14 @@ export function OverviewLiveHistogram({
}
return (
<Wrapper open={liveHistogram} count={liveCount}>
<Wrapper count={liveCount}>
{minutes.map((minute) => {
return (
<Tooltip key={minute.date}>
<TooltipTrigger asChild>
<div
className={cn(
'flex-1 rounded-md transition-all ease-in-out hover:scale-110',
'flex-1 rounded transition-all ease-in-out hover:scale-110',
minute.count === 0 ? 'bg-slate-200' : 'bg-blue-600'
)}
style={{
@@ -127,22 +124,19 @@ export function OverviewLiveHistogram({
}
interface WrapperProps {
open: boolean;
children: React.ReactNode;
count: number;
}
function Wrapper({ open, children, count }: WrapperProps) {
function Wrapper({ children, count }: WrapperProps) {
return (
<AnimateHeight open={open}>
<div className="flex flex-col">
<div className="relative -top-2 text-center text-xs font-medium text-muted-foreground">
{count} unique vistors last 30 minutes
</div>
<div className="relative flex aspect-[6/1] max-h-[150px] w-full flex-1 items-end gap-0.5 md:aspect-[10/1] md:gap-2">
{children}
</div>
<div className="flex h-full flex-col">
<div className="relative mb-1 text-xs font-medium text-muted-foreground">
{count} unique vistors last 30 minutes
</div>
</AnimateHeight>
<div className="relative flex h-full w-full flex-1 items-end gap-1">
{children}
</div>
</div>
);
}

View File

@@ -1,14 +1,14 @@
'use client';
import { WidgetHead } from '@/components/overview/overview-widget';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { ChartSwitch } from '@/components/report/chart';
import { Widget, WidgetBody } from '@/components/widget';
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
import { cn } from '@/utils/cn';
import type { IChartInput } from '@openpanel/validation';
import { OverviewLiveHistogram } from './overview-live-histogram';
interface OverviewMetricsProps {
projectId: string;
}
@@ -191,30 +191,40 @@ export default function OverviewMetrics({ projectId }: OverviewMetricsProps) {
const selectedMetric = reports[metric]!;
return (
<div className="card col-span-6 p-4">
<div className="-mx-2 -mt-2 mb-2 grid grid-cols-6 gap-2">
{reports.map((report, index) => (
<button
key={index}
<>
<div className="relative -top-0.5 col-span-6 -m-4 mb-0 md:m-0">
<div className="card mb-2 grid grid-cols-4">
{reports.map((report, index) => (
<button
key={index}
className={cn(
'col-span-2 flex-1 p-4 shadow-[0_0_0_0.5px] shadow-border md:col-span-1',
index === metric && 'bg-slate-50'
)}
onClick={() => {
setMetric(index);
}}
>
<ChartSwitch hideID {...report} />
</button>
))}
<div
className={cn(
'col-span-3 rounded-lg border border-background p-2 transition-all max-md:flex-1 md:col-span-2 lg:col-span-1 [&_[role="heading"]]:text-xs',
index === metric && 'border-border'
'col-span-4 min-h-28 flex-1 p-4 shadow-[0_0_0_0.5px] shadow-border max-md:row-start-1 md:col-span-2'
)}
onClick={() => {
setMetric(index);
}}
>
<ChartSwitch hideID {...report} />
{/* add active border */}
</button>
))}
<OverviewLiveHistogram projectId={projectId} />
</div>
</div>
<div className="card col-span-6 p-4">
<ChartSwitch
key={selectedMetric.id}
hideID
{...selectedMetric}
chartType="linear"
/>
</div>
</div>
<ChartSwitch
key={selectedMetric.id}
hideID
{...selectedMetric}
chartType="linear"
/>
</div>
</>
);
}

View File

@@ -46,12 +46,6 @@ export function useOverviewOptions() {
parseAsInteger.withDefault(0).withOptions(nuqsOptions)
);
// Toggles
const [liveHistogram, setLiveHistogram] = useQueryState(
'live',
parseAsBoolean.withDefault(true).withOptions(nuqsOptions)
);
return {
previous,
setPrevious,
@@ -72,9 +66,5 @@ export function useOverviewOptions() {
// Computed
interval,
// Toggles
liveHistogram,
setLiveHistogram,
};
}