Skip to content

Commit

Permalink
small sample size filter
Browse files Browse the repository at this point in the history
  • Loading branch information
sebald committed Oct 29, 2023
1 parent de68210 commit 80eb325
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 36 deletions.
30 changes: 30 additions & 0 deletions app/(stats)/compositions/[[...range]]/compositions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use client';

import { Card } from '@/ui';
import { useSmallSamplesFilter } from '@/ui/filter/small-samples-filter';
import { CompositionTable } from '@/ui/stats/composition-stats';
import type { CompositionData } from '@/lib/stats/module/composition';

export interface CompositionsProps {
data: CompositionData['composition'];
}

export const Compositions = ({ data }: CompositionsProps) => {
const [smallSamples] = useSmallSamplesFilter();

return (
<Card inset="headless">
<Card.Body>
<CompositionTable
value={data}
collapsible={false}
filter={
smallSamples === 'hide'
? ([, stat]) => stat.count >= 3 && stat.score >= 5
: undefined
}
/>
</Card.Body>
</Card>
);
};
16 changes: 7 additions & 9 deletions app/(stats)/compositions/[[...range]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { toRange } from '@/lib/utils/url.utils';
import { Caption, Card, Inline, Title } from '@/ui';
import { Calendar, Rocket, Trophy } from '@/ui/icons';

import { useQueryFilter } from '@/ui/filter/useQueryFilter';
import {
CompositionFilter,
CompositionFilterProvider,
Expand All @@ -20,6 +19,9 @@ import { StatsFilter } from '@/ui/stats/stats-filter';
import { StatsHint } from '@/ui/stats/stats-hint';
import { setup } from '@/lib/stats';
import { CompositionData, composition } from '@/lib/stats/module';
import { SmallSamplesFilter } from '@/ui/filter/small-samples-filter';
import { Suspense } from 'react';
import { Compositions } from './compositions';

// Config
// ---------------
Expand Down Expand Up @@ -102,20 +104,16 @@ const CompositionsPage = async ({ params }: PageProps) => {
</Inline>
</Caption>
</div>
<Inline align="end">
<SmallSamplesFilter />
</Inline>
<CompositionFilterProvider>
<StatsFilter smallSamples={false} dateRange={toDate(from, to)}>
<CompositionFilter />
</StatsFilter>
<div className="grid grid-cols-1 gap-4 md:grid-cols-12">
<div className="col-span-full">
<Card inset="headless">
<Card.Body>
<CompositionTable
value={stats.composition}
collapsible={false}
/>
</Card.Body>
</Card>
<Compositions data={stats.composition} />
</div>
<div className="col-span-full pt-8 lg:col-start-2 lg:col-end-12">
<StatsHint />
Expand Down
35 changes: 35 additions & 0 deletions ui/filter/small-samples-filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use client';

import { Switch } from '@/ui/switch';
import { useQueryFilter } from './useQueryFilter';

// Hook
// ---------------
export const useSmallSamplesFilter = () => {
const [filter, setFilter] = useQueryFilter(['small-samples']);

const setSmallSamples = (val: boolean) =>
setFilter({
['small-samples']: val ? 'show' : null,
});

return [
filter['small-samples'] === 'show' ? 'show' : 'hide',
setSmallSamples,
] as const;
};

// Component
// ---------------
export const SmallSamplesFilter = () => {
const [smallSamples, setSmallSamples] = useSmallSamplesFilter();

return (
<Switch
size="small"
label="Hide small Samples"
defaultChecked={smallSamples === 'hide'}
onCheckedChange={checked => setSmallSamples(!checked)}
/>
);
};
27 changes: 10 additions & 17 deletions ui/filter/useQueryFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,22 @@ export const useQueryFilter = <Params extends string>(keys: Params[]) => {
filter[key] = searchParams.get(key) || null;
});

const setFilter = (key: string, value: string) => {
const setFilter = (values: { [key: string]: string | null }) => {
const filterParams = new URLSearchParams(searchParams.toString());
filterParams.set(key, value);

Object.entries(values).forEach(([key, value]) => {
if (value) {
filterParams.set(key, value);
} else {
filterParams.delete(key);
}
});

const ps = filterParams.toString();
const queryString = `${ps.length ? '?' : ''}${ps}`;

router.replace(`${pathname}${queryString}`, { scroll: false });
};

return { filter, setFilter };
return [filter, setFilter] as const;
};

// export interface QueryFilterProps {
// children?: ReactNode;
// }

// export const QueryFilter = ({ children }: QueryFilterProps) => {
// const { replace } = useRouter();
// const pathname = usePathname();
// const [pending, startTransition] = useTransition();

// console.log(pathname);

// return <>{children}</>;
// };
11 changes: 9 additions & 2 deletions ui/inline.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { cn } from '@/lib/utils';

export interface InlineProps {
align?: 'start' | 'end';
className?: string;
children: React.ReactNode;
}

export const Inline = ({ className, children }: InlineProps) => (
<div className={cn('flex flex-wrap items-center gap-1', className)}>
export const Inline = ({ align, className, children }: InlineProps) => (
<div
className={cn(
'flex flex-wrap items-center gap-1',
align === 'end' && 'justify-end',
className
)}
>
{children}
</div>
);
16 changes: 9 additions & 7 deletions ui/stats/composition-stats/composition-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,25 @@ import type { CompositionStatsType } from './types';
export interface CompositionTableProps {
value: { [id: string]: CompositionStatsType };
collapsible?: boolean;
filter?: (entry: [string, CompositionStatsType]) => boolean;
}

// Components
// ---------------
export const CompositionTable = ({
value,
collapsible = true,
filter,
}: CompositionTableProps) => {
const { faction = 'all', sort = 'percentile' } = useCompositionFilter();
let data = Object.entries(value);

const data =
faction === 'all'
? (Object.entries(value) as [string, CompositionStatsType][])
: Object.entries(value).filter(
([_, stat]: [string, CompositionStatsType]) =>
stat.faction === faction
);
if (faction !== 'all' || filter) {
data = data.filter(entry => {
let result = faction === 'all' || entry[1].faction === faction;
return result && filter ? filter(entry) : result;
});
}

data.sort(([, a], [, b]) => {
const result = (b[sort] || 0) - (a[sort] || 0);
Expand Down
6 changes: 5 additions & 1 deletion ui/switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@ export const Switch = forwardRef<
return (
<div className="flex cursor-pointer items-center gap-2">
{label && (
<Label htmlFor={id} size={size} className="m-0 select-none font-normal">
<Label
htmlFor={id}
size={size}
className="m-0 cursor-pointer select-none font-normal"
>
{label}
</Label>
)}
Expand Down

0 comments on commit 80eb325

Please sign in to comment.