wip event list
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
useEventFilters,
|
||||
useEventQueryFilters,
|
||||
} from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
export function OverviewFiltersButtons() {
|
||||
const eventQueryFilters = useEventQueryFilters();
|
||||
const filters = Object.entries(eventQueryFilters).filter(
|
||||
([, filter]) => filter.get !== null
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className={cn('flex flex-wrap gap-2', filters.length > 0 && 'px-4 pb-4')}
|
||||
>
|
||||
{filters.map(([key, filter]) => (
|
||||
<Button
|
||||
key={key}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => filter.set(null)}
|
||||
>
|
||||
<span className="mr-1">{key} is</span>
|
||||
<strong>{filter.get}</strong>
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
'use client';
|
||||
|
||||
import { api } from '@/app/_trpc/client';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Combobox } from '@/components/ui/combobox';
|
||||
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { XIcon } from 'lucide-react';
|
||||
|
||||
interface OverviewFiltersProps {
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
export function OverviewFiltersDrawerContent({
|
||||
projectId,
|
||||
}: OverviewFiltersProps) {
|
||||
const eventQueryFilters = useEventQueryFilters();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-medium mb-8">Overview filters</h2>
|
||||
<Combobox
|
||||
className="w-full"
|
||||
onChange={(value) => {
|
||||
// @ts-expect-error
|
||||
eventQueryFilters[value].set('');
|
||||
}}
|
||||
value=""
|
||||
placeholder="Filter by..."
|
||||
label="What do you want to filter by?"
|
||||
items={Object.entries(eventQueryFilters)
|
||||
.filter(([, filter]) => filter.get === null)
|
||||
.map(([name]) => ({
|
||||
label: name,
|
||||
value: name,
|
||||
}))}
|
||||
searchable
|
||||
/>
|
||||
|
||||
<div className="flex flex-col gap-4 mt-8">
|
||||
{Object.entries(eventQueryFilters)
|
||||
.filter(([, filter]) => filter.get !== null)
|
||||
.map(([name, filter]) => (
|
||||
<FilterOption
|
||||
key={name}
|
||||
projectId={projectId}
|
||||
name={name}
|
||||
{...filter}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FilterOption({
|
||||
name,
|
||||
get,
|
||||
set,
|
||||
projectId,
|
||||
}: {
|
||||
name: string;
|
||||
get: string | null;
|
||||
set: (value: string | null) => void;
|
||||
projectId: string;
|
||||
}) {
|
||||
const { data } = api.chart.values.useQuery({
|
||||
projectId,
|
||||
event: name === 'path' ? 'screen_view' : 'session_start',
|
||||
property: name,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center">
|
||||
<div>{name}</div>
|
||||
<Combobox
|
||||
className="flex-1"
|
||||
onChange={(value) => set(value)}
|
||||
placeholder={'Select a value'}
|
||||
items={
|
||||
data?.values.filter(Boolean).map((value) => ({
|
||||
value,
|
||||
label: value,
|
||||
})) ?? []
|
||||
}
|
||||
value={get}
|
||||
/>
|
||||
<Button size="icon" variant="ghost" onClick={() => set(null)}>
|
||||
<XIcon />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
|
||||
import { FilterIcon } from 'lucide-react';
|
||||
|
||||
import { OverviewFiltersDrawerContent } from './overview-filters-drawer-content';
|
||||
|
||||
interface OverviewFiltersDrawerProps {
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
export function OverviewFiltersDrawer({
|
||||
projectId,
|
||||
}: OverviewFiltersDrawerProps) {
|
||||
return (
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="outline" responsive icon={FilterIcon}>
|
||||
Filters
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent className="!max-w-lg w-full" side="right">
|
||||
<OverviewFiltersDrawerContent projectId={projectId} />
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { cn } from '@/utils/cn';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
import { Button } from '../ui/button';
|
||||
import { useOverviewOptions } from './useOverviewOptions';
|
||||
|
||||
export function OverviewFiltersButtons() {
|
||||
const options = useOverviewOptions();
|
||||
const activeFilter = options.filters.length > 0;
|
||||
|
||||
return (
|
||||
<div className={cn('flex flex-wrap gap-2', activeFilter && 'px-4 pb-4')}>
|
||||
{options.referrer && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setReferrer(null)}
|
||||
>
|
||||
<span className="mr-1">Referrer is</span>
|
||||
<strong>{options.referrer}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.referrerName && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setReferrerName(null)}
|
||||
>
|
||||
<span className="mr-1">Referrer name is</span>
|
||||
<strong>{options.referrerName}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.referrerType && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setReferrerType(null)}
|
||||
>
|
||||
<span className="mr-1">Referrer type is</span>
|
||||
<strong>{options.referrerType}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.device && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setDevice(null)}
|
||||
>
|
||||
<span className="mr-1">Device is</span>
|
||||
<strong>{options.device}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.page && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setPage(null)}
|
||||
>
|
||||
<span className="mr-1">Page is</span>
|
||||
<strong>{options.page}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.utmSource && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setUtmSource(null)}
|
||||
>
|
||||
<span className="mr-1">Utm Source is</span>
|
||||
<strong>{options.utmSource}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.utmMedium && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setUtmMedium(null)}
|
||||
>
|
||||
<span className="mr-1">Utm Medium is</span>
|
||||
<strong>{options.utmMedium}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.utmCampaign && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setUtmCampaign(null)}
|
||||
>
|
||||
<span className="mr-1">Utm Campaign is</span>
|
||||
<strong>{options.utmCampaign}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.utmTerm && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setUtmTerm(null)}
|
||||
>
|
||||
<span className="mr-1">Utm Term is</span>
|
||||
<strong>{options.utmTerm}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.utmContent && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setUtmContent(null)}
|
||||
>
|
||||
<span className="mr-1">Utm Content is</span>
|
||||
<strong>{options.utmContent}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.country && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setCountry(null)}
|
||||
>
|
||||
<span className="mr-1">Country is</span>
|
||||
<strong>{options.country}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.region && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setRegion(null)}
|
||||
>
|
||||
<span className="mr-1">Region is</span>
|
||||
<strong>{options.region}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.city && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setCity(null)}
|
||||
>
|
||||
<span className="mr-1">City is</span>
|
||||
<strong>{options.city}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.browser && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setBrowser(null)}
|
||||
>
|
||||
<span className="mr-1">Browser is</span>
|
||||
<strong>{options.browser}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.browserVersion && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setBrowserVersion(null)}
|
||||
>
|
||||
<span className="mr-1">Browser Version is</span>
|
||||
<strong>{options.browserVersion}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.os && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setOS(null)}
|
||||
>
|
||||
<span className="mr-1">OS is</span>
|
||||
<strong>{options.os}</strong>
|
||||
</Button>
|
||||
)}
|
||||
{options.osVersion && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
icon={X}
|
||||
onClick={() => options.setOSVersion(null)}
|
||||
>
|
||||
<span className="mr-1">OS Version is</span>
|
||||
<strong>{options.osVersion}</strong>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { api } from '@/app/_trpc/client';
|
||||
import { useAppParams } from '@/hooks/useAppParams';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { Combobox } from '../ui/combobox';
|
||||
import { Label } from '../ui/label';
|
||||
import { useOverviewOptions } from './useOverviewOptions';
|
||||
|
||||
interface OverviewFiltersProps {
|
||||
projectId: string;
|
||||
}
|
||||
export function OverviewFilters({ projectId }: OverviewFiltersProps) {
|
||||
const options = useOverviewOptions();
|
||||
|
||||
const { data: referrers } = api.chart.values.useQuery({
|
||||
projectId,
|
||||
property: 'referrer',
|
||||
event: 'session_start',
|
||||
});
|
||||
|
||||
const { data: devices } = api.chart.values.useQuery({
|
||||
projectId,
|
||||
property: 'device',
|
||||
event: 'session_start',
|
||||
});
|
||||
|
||||
const { data: pages } = api.chart.values.useQuery({
|
||||
projectId,
|
||||
property: 'path',
|
||||
event: 'screen_view',
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-medium mb-8">Overview filters</h2>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<Label className="flex justify-between">
|
||||
Referrer
|
||||
<button
|
||||
className={cn(
|
||||
'text-slate-500 transition-opacity opacity-100',
|
||||
options.referrer === null && 'opacity-0'
|
||||
)}
|
||||
onClick={() => options.setReferrer(null)}
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</Label>
|
||||
<Combobox
|
||||
className="w-full"
|
||||
onChange={(value) => options.setReferrer(value)}
|
||||
label="Referrer"
|
||||
placeholder="Referrer"
|
||||
items={
|
||||
referrers?.values?.filter(Boolean)?.map((value) => ({
|
||||
value,
|
||||
label: value,
|
||||
})) ?? []
|
||||
}
|
||||
value={options.referrer}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="flex justify-between">
|
||||
Device
|
||||
<button
|
||||
className={cn(
|
||||
'opacity-100 text-slate-500 transition-opacity',
|
||||
options.device === null && 'opacity-0'
|
||||
)}
|
||||
onClick={() => options.setDevice(null)}
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</Label>
|
||||
<Combobox
|
||||
className="w-full"
|
||||
onChange={(value) => options.setDevice(value)}
|
||||
label="Device"
|
||||
placeholder="Device"
|
||||
items={
|
||||
devices?.values?.filter(Boolean)?.map((value) => ({
|
||||
value,
|
||||
label: value,
|
||||
})) ?? []
|
||||
}
|
||||
value={options.device}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="flex justify-between">
|
||||
Page
|
||||
<button
|
||||
className={cn(
|
||||
'opacity-100 text-slate-500 transition-opacity',
|
||||
options.page === null && 'opacity-0'
|
||||
)}
|
||||
onClick={() => options.setPage(null)}
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</Label>
|
||||
<Combobox
|
||||
className="w-full"
|
||||
onChange={(value) => options.setPage(value)}
|
||||
label="Page"
|
||||
placeholder="Page"
|
||||
items={
|
||||
pages?.values?.filter(Boolean)?.map((value) => ({
|
||||
value,
|
||||
label: value,
|
||||
})) ?? []
|
||||
}
|
||||
value={options.page}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import { Chart } from '@/components/report/chart';
|
||||
import {
|
||||
useEventFilters,
|
||||
useEventQueryFilters,
|
||||
} from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { Widget, WidgetBody } from '../Widget';
|
||||
@@ -14,17 +18,10 @@ interface OverviewTopDevicesProps {
|
||||
export default function OverviewTopDevices({
|
||||
projectId,
|
||||
}: OverviewTopDevicesProps) {
|
||||
const {
|
||||
filters,
|
||||
interval,
|
||||
range,
|
||||
previous,
|
||||
setBrowser,
|
||||
setBrowserVersion,
|
||||
setOS,
|
||||
setOSVersion,
|
||||
setDevice,
|
||||
} = useOverviewOptions();
|
||||
const { interval, range, previous } = useOverviewOptions();
|
||||
const filters = useEventFilters();
|
||||
const { device, browser, browserVersion, os, osVersion } =
|
||||
useEventQueryFilters();
|
||||
const [widget, setWidget, widgets] = useOverviewWidget('tech', {
|
||||
devices: {
|
||||
title: 'Top devices',
|
||||
@@ -193,21 +190,21 @@ export default function OverviewTopDevices({
|
||||
onClick={(item) => {
|
||||
switch (widget.key) {
|
||||
case 'devices':
|
||||
setDevice(item.name);
|
||||
device.set(item.name);
|
||||
break;
|
||||
case 'browser':
|
||||
setWidget('browser_version');
|
||||
setBrowser(item.name);
|
||||
browser.set(item.name);
|
||||
break;
|
||||
case 'browser_version':
|
||||
setBrowserVersion(item.name);
|
||||
browserVersion.set(item.name);
|
||||
break;
|
||||
case 'os':
|
||||
setWidget('os_version');
|
||||
setOS(item.name);
|
||||
os.set(item.name);
|
||||
break;
|
||||
case 'os_version':
|
||||
setOSVersion(item.name);
|
||||
osVersion.set(item.name);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { Suspense } from 'react';
|
||||
import { Chart } from '@/components/report/chart';
|
||||
import { ChartLoading } from '@/components/report/chart/ChartLoading';
|
||||
import { useEventFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { Widget, WidgetBody } from '../Widget';
|
||||
@@ -16,7 +15,8 @@ interface OverviewTopEventsProps {
|
||||
export default function OverviewTopEvents({
|
||||
projectId,
|
||||
}: OverviewTopEventsProps) {
|
||||
const { filters, interval, range, previous } = useOverviewOptions();
|
||||
const { interval, range, previous } = useOverviewOptions();
|
||||
const filters = useEventFilters();
|
||||
const [widget, setWidget, widgets] = useOverviewWidget('ev', {
|
||||
all: {
|
||||
title: 'Top events',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import { Suspense } from 'react';
|
||||
import { Chart } from '@/components/report/chart';
|
||||
import { ChartLoading } from '@/components/report/chart/ChartLoading';
|
||||
import {
|
||||
useEventFilters,
|
||||
useEventQueryFilters,
|
||||
} from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { Widget, WidgetBody } from '../Widget';
|
||||
@@ -14,8 +16,9 @@ interface OverviewTopGeoProps {
|
||||
projectId: string;
|
||||
}
|
||||
export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
const { filters, interval, range, previous, setCountry, setRegion, setCity } =
|
||||
useOverviewOptions();
|
||||
const { interval, range, previous } = useOverviewOptions();
|
||||
const filters = useEventFilters();
|
||||
const { region, country, city } = useEventQueryFilters();
|
||||
const [widget, setWidget, widgets] = useOverviewWidget('geo', {
|
||||
map: {
|
||||
title: 'Map',
|
||||
@@ -157,14 +160,14 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
switch (widget.key) {
|
||||
case 'countries':
|
||||
setWidget('regions');
|
||||
setCountry(item.name);
|
||||
country.set(item.name);
|
||||
break;
|
||||
case 'regions':
|
||||
setWidget('cities');
|
||||
setRegion(item.name);
|
||||
region.set(item.name);
|
||||
break;
|
||||
case 'cities':
|
||||
setCity(item.name);
|
||||
city.set(item.name);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import { Suspense } from 'react';
|
||||
import { Chart } from '@/components/report/chart';
|
||||
import { ChartLoading } from '@/components/report/chart/ChartLoading';
|
||||
import {
|
||||
useEventFilters,
|
||||
useEventQueryFilters,
|
||||
} from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { Widget, WidgetBody } from '../Widget';
|
||||
@@ -14,7 +16,9 @@ interface OverviewTopPagesProps {
|
||||
projectId: string;
|
||||
}
|
||||
export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
const { filters, interval, range, previous, setPage } = useOverviewOptions();
|
||||
const { interval, range, previous } = useOverviewOptions();
|
||||
const filters = useEventFilters();
|
||||
const { path } = useEventQueryFilters();
|
||||
const [widget, setWidget, widgets] = useOverviewWidget('pages', {
|
||||
top: {
|
||||
title: 'Top pages',
|
||||
@@ -125,7 +129,7 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
{...widget.chart}
|
||||
previous={false}
|
||||
onClick={(item) => {
|
||||
setPage(item.name);
|
||||
path.set(item.name);
|
||||
}}
|
||||
/>
|
||||
</WidgetBody>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import { Suspense } from 'react';
|
||||
import { Chart } from '@/components/report/chart';
|
||||
import { ChartLoading } from '@/components/report/chart/ChartLoading';
|
||||
import {
|
||||
useEventFilters,
|
||||
useEventQueryFilters,
|
||||
} from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { Widget, WidgetBody } from '../Widget';
|
||||
@@ -16,20 +18,18 @@ interface OverviewTopSourcesProps {
|
||||
export default function OverviewTopSources({
|
||||
projectId,
|
||||
}: OverviewTopSourcesProps) {
|
||||
const { interval, range, previous } = useOverviewOptions();
|
||||
const {
|
||||
filters,
|
||||
interval,
|
||||
range,
|
||||
previous,
|
||||
setReferrer,
|
||||
setUtmSource,
|
||||
setUtmMedium,
|
||||
setUtmCampaign,
|
||||
setUtmTerm,
|
||||
setUtmContent,
|
||||
setReferrerName,
|
||||
setReferrerType,
|
||||
} = useOverviewOptions();
|
||||
referrer,
|
||||
referrerName,
|
||||
referrerType,
|
||||
utmCampaign,
|
||||
utmContent,
|
||||
utmMedium,
|
||||
utmSource,
|
||||
utmTerm,
|
||||
} = useEventQueryFilters();
|
||||
const filters = useEventFilters();
|
||||
const [widget, setWidget, widgets] = useOverviewWidget('sources', {
|
||||
all: {
|
||||
title: 'Top sources',
|
||||
@@ -282,30 +282,30 @@ export default function OverviewTopSources({
|
||||
onClick={(item) => {
|
||||
switch (widget.key) {
|
||||
case 'all':
|
||||
setReferrerName(item.name);
|
||||
referrerName.set(item.name);
|
||||
setWidget('domain');
|
||||
break;
|
||||
case 'domain':
|
||||
setReferrer(item.name);
|
||||
referrer.set(item.name);
|
||||
break;
|
||||
case 'type':
|
||||
setReferrerType(item.name);
|
||||
referrerType.set(item.name);
|
||||
setWidget('domain');
|
||||
break;
|
||||
case 'utm_source':
|
||||
setUtmSource(item.name);
|
||||
utmSource.set(item.name);
|
||||
break;
|
||||
case 'utm_medium':
|
||||
setUtmMedium(item.name);
|
||||
utmMedium.set(item.name);
|
||||
break;
|
||||
case 'utm_campaign':
|
||||
setUtmCampaign(item.name);
|
||||
utmCampaign.set(item.name);
|
||||
break;
|
||||
case 'utm_term':
|
||||
setUtmTerm(item.name);
|
||||
utmTerm.set(item.name);
|
||||
break;
|
||||
case 'utm_content':
|
||||
setUtmContent(item.name);
|
||||
utmContent.set(item.name);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { IChartInput } from '@/types';
|
||||
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { getDefaultIntervalByRange, timeRanges } from '@/utils/constants';
|
||||
import { mapKeys } from '@/utils/validation';
|
||||
import {
|
||||
parseAsBoolean,
|
||||
parseAsInteger,
|
||||
parseAsString,
|
||||
parseAsStringEnum,
|
||||
useQueryState,
|
||||
} from 'nuqs';
|
||||
@@ -29,267 +27,12 @@ export function useOverviewOptions() {
|
||||
parseAsInteger.withDefault(0).withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
// Filters
|
||||
const [page, setPage] = useQueryState(
|
||||
'page',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
// Referrer
|
||||
const [referrer, setReferrer] = useQueryState(
|
||||
'referrer',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [referrerName, setReferrerName] = useQueryState(
|
||||
'referrer_name',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [referrerType, setReferrerType] = useQueryState(
|
||||
'referrer_type',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
// Sources
|
||||
const [utmSource, setUtmSource] = useQueryState(
|
||||
'utm_source',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [utmMedium, setUtmMedium] = useQueryState(
|
||||
'utm_medium',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [utmCampaign, setUtmCampaign] = useQueryState(
|
||||
'utm_campaign',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [utmContent, setUtmContent] = useQueryState(
|
||||
'utm_content',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [utmTerm, setUtmTerm] = useQueryState(
|
||||
'utm_term',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
// Geo
|
||||
const [country, setCountry] = useQueryState(
|
||||
'country',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [region, setRegion] = useQueryState(
|
||||
'region',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [city, setCity] = useQueryState(
|
||||
'city',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
//
|
||||
const [device, setDevice] = useQueryState(
|
||||
'device',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [browser, setBrowser] = useQueryState(
|
||||
'browser',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [browserVersion, setBrowserVersion] = useQueryState(
|
||||
'browser_version',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [os, setOS] = useQueryState(
|
||||
'os',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
const [osVersion, setOSVersion] = useQueryState(
|
||||
'os_version',
|
||||
parseAsString.withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
// Toggles
|
||||
const [liveHistogram, setLiveHistogram] = useQueryState(
|
||||
'live',
|
||||
parseAsBoolean.withDefault(false).withOptions(nuqsOptions)
|
||||
);
|
||||
|
||||
const filters = useMemo(() => {
|
||||
const filters: IChartInput['events'][number]['filters'] = [];
|
||||
|
||||
if (page) {
|
||||
filters.push({
|
||||
id: 'path',
|
||||
operator: 'is',
|
||||
name: 'path',
|
||||
value: [page],
|
||||
});
|
||||
}
|
||||
|
||||
if (device) {
|
||||
filters.push({
|
||||
id: 'device',
|
||||
operator: 'is',
|
||||
name: 'device',
|
||||
value: [device],
|
||||
});
|
||||
}
|
||||
|
||||
if (referrer) {
|
||||
filters.push({
|
||||
id: 'referrer',
|
||||
operator: 'is',
|
||||
name: 'referrer',
|
||||
value: [referrer],
|
||||
});
|
||||
}
|
||||
|
||||
if (referrerName) {
|
||||
filters.push({
|
||||
id: 'referrer_name',
|
||||
operator: 'is',
|
||||
name: 'referrer_name',
|
||||
value: [referrerName],
|
||||
});
|
||||
}
|
||||
|
||||
if (referrerType) {
|
||||
filters.push({
|
||||
id: 'referrer_type',
|
||||
operator: 'is',
|
||||
name: 'referrer_type',
|
||||
value: [referrerType],
|
||||
});
|
||||
}
|
||||
|
||||
if (utmSource) {
|
||||
filters.push({
|
||||
id: 'utm_source',
|
||||
operator: 'is',
|
||||
name: 'properties.query.utm_source',
|
||||
value: [utmSource],
|
||||
});
|
||||
}
|
||||
|
||||
if (utmMedium) {
|
||||
filters.push({
|
||||
id: 'utm_medium',
|
||||
operator: 'is',
|
||||
name: 'properties.query.utm_medium',
|
||||
value: [utmMedium],
|
||||
});
|
||||
}
|
||||
|
||||
if (utmCampaign) {
|
||||
filters.push({
|
||||
id: 'utm_campaign',
|
||||
operator: 'is',
|
||||
name: 'properties.query.utm_campaign',
|
||||
value: [utmCampaign],
|
||||
});
|
||||
}
|
||||
|
||||
if (utmContent) {
|
||||
filters.push({
|
||||
id: 'utm_content',
|
||||
operator: 'is',
|
||||
name: 'properties.query.utm_content',
|
||||
value: [utmContent],
|
||||
});
|
||||
}
|
||||
|
||||
if (utmTerm) {
|
||||
filters.push({
|
||||
id: 'utm_term',
|
||||
operator: 'is',
|
||||
name: 'properties.query.utm_term',
|
||||
value: [utmTerm],
|
||||
});
|
||||
}
|
||||
|
||||
if (country) {
|
||||
filters.push({
|
||||
id: 'country',
|
||||
operator: 'is',
|
||||
name: 'country',
|
||||
value: [country],
|
||||
});
|
||||
}
|
||||
|
||||
if (region) {
|
||||
filters.push({
|
||||
id: 'region',
|
||||
operator: 'is',
|
||||
name: 'region',
|
||||
value: [region],
|
||||
});
|
||||
}
|
||||
|
||||
if (city) {
|
||||
filters.push({
|
||||
id: 'city',
|
||||
operator: 'is',
|
||||
name: 'city',
|
||||
value: [city],
|
||||
});
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
filters.push({
|
||||
id: 'browser',
|
||||
operator: 'is',
|
||||
name: 'browser',
|
||||
value: [browser],
|
||||
});
|
||||
}
|
||||
|
||||
if (browserVersion) {
|
||||
filters.push({
|
||||
id: 'browser_version',
|
||||
operator: 'is',
|
||||
name: 'browser_version',
|
||||
value: [browserVersion],
|
||||
});
|
||||
}
|
||||
|
||||
if (os) {
|
||||
filters.push({
|
||||
id: 'os',
|
||||
operator: 'is',
|
||||
name: 'os',
|
||||
value: [os],
|
||||
});
|
||||
}
|
||||
|
||||
if (osVersion) {
|
||||
filters.push({
|
||||
id: 'os_version',
|
||||
operator: 'is',
|
||||
name: 'os_version',
|
||||
value: [osVersion],
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [
|
||||
page,
|
||||
device,
|
||||
referrer,
|
||||
referrerName,
|
||||
referrerType,
|
||||
utmSource,
|
||||
utmMedium,
|
||||
utmCampaign,
|
||||
utmContent,
|
||||
utmTerm,
|
||||
country,
|
||||
region,
|
||||
city,
|
||||
browser,
|
||||
browserVersion,
|
||||
os,
|
||||
osVersion,
|
||||
]);
|
||||
|
||||
return {
|
||||
previous,
|
||||
setPrevious,
|
||||
@@ -297,52 +40,9 @@ export function useOverviewOptions() {
|
||||
setRange,
|
||||
metric,
|
||||
setMetric,
|
||||
page,
|
||||
setPage,
|
||||
|
||||
// Computed
|
||||
interval,
|
||||
filters,
|
||||
|
||||
// Refs
|
||||
referrer,
|
||||
setReferrer,
|
||||
referrerName,
|
||||
setReferrerName,
|
||||
referrerType,
|
||||
setReferrerType,
|
||||
|
||||
// UTM
|
||||
utmSource,
|
||||
setUtmSource,
|
||||
utmMedium,
|
||||
setUtmMedium,
|
||||
utmCampaign,
|
||||
setUtmCampaign,
|
||||
utmContent,
|
||||
setUtmContent,
|
||||
utmTerm,
|
||||
setUtmTerm,
|
||||
|
||||
// GEO
|
||||
country,
|
||||
setCountry,
|
||||
region,
|
||||
setRegion,
|
||||
city,
|
||||
setCity,
|
||||
|
||||
// Tech
|
||||
device,
|
||||
setDevice,
|
||||
browser,
|
||||
setBrowser,
|
||||
browserVersion,
|
||||
setBrowserVersion,
|
||||
os,
|
||||
setOS,
|
||||
osVersion,
|
||||
setOSVersion,
|
||||
|
||||
// Toggles
|
||||
liveHistogram,
|
||||
|
||||
Reference in New Issue
Block a user