diff --git a/app/analyze/page.tsx b/app/analyze/page.tsx
index 0944c645..7ddf8d54 100644
--- a/app/analyze/page.tsx
+++ b/app/analyze/page.tsx
@@ -33,7 +33,7 @@ import { CompositionStats } from '@/ui/stats/composition-stats';
import { FactionDistribution } from '@/ui/stats/faction-distribution';
import { FactionPerformance } from '@/ui/stats/faction-performance';
import { FactionVictories } from '@/ui/stats/faction-victories';
-import { Filter } from '@/ui/stats/filter';
+import { StatsFilter } from '@/ui/stats/stats-filter';
import { PilotCostDistribution } from '@/ui/stats/pilot-cost-distribution';
import { PilotSkillDistribution } from '@/ui/stats/pilot-skill-distribution';
import { PilotStats } from '@/ui/stats/pilot-stats';
@@ -171,7 +171,7 @@ const AnalyzePage = async ({ searchParams }: AnalyzePageProps) => {
-
diff --git a/lib/stats/details/composition.ts b/lib/stats/details/composition.ts
index fd9ec21a..9288e6d6 100644
--- a/lib/stats/details/composition.ts
+++ b/lib/stats/details/composition.ts
@@ -7,13 +7,7 @@ import type {
XWSUpgrades,
} from '@/lib/types';
import { fromDate, toMonth } from '@/lib/utils/date.utils';
-import {
- average,
- deviation,
- percentile,
- round,
- winrate,
-} from '@/lib/utils/math.utils';
+import { average, deviation, round, winrate } from '@/lib/utils/math.utils';
// Types
// ---------------
diff --git a/lib/utils/index.ts b/lib/utils/index.ts
index 97b5cf2c..32ba6306 100644
--- a/lib/utils/index.ts
+++ b/lib/utils/index.ts
@@ -4,3 +4,4 @@ export * from './fetch.utils';
export * from './math.utils';
export * from './react.utils';
export * from './string.utils';
+export * from './url.utils';
diff --git a/lib/utils/url.utils.ts b/lib/utils/url.utils.ts
new file mode 100644
index 00000000..bb9e7e93
--- /dev/null
+++ b/lib/utils/url.utils.ts
@@ -0,0 +1,9 @@
+import qs from 'query-string';
+
+/**
+ * Used to parse a dynamic route segment and use it as query params.
+ *
+ * This is done because using `searchParams` (the real query params) will cause
+ * pages to switch to dynamic mode.
+ */
+export const pq = (query: string = '') => qs.parse(decodeURIComponent(query));
diff --git a/package.json b/package.json
index 1d55dda2..1938bb61 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"mysql2": "3.6.2",
"next": "13.5.4",
"p-limit": "4.0.0",
+ "query-string": "^8.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-is": "18.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 94af6dd9..edde9c4e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -59,6 +59,9 @@ dependencies:
p-limit:
specifier: 4.0.0
version: 4.0.0
+ query-string:
+ specifier: ^8.1.0
+ version: 8.1.0
react:
specifier: 18.2.0
version: 18.2.0
@@ -3019,6 +3022,11 @@ packages:
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
dev: true
+ /decode-uri-component@0.4.1:
+ resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==}
+ engines: {node: '>=14.16'}
+ dev: false
+
/dedent@1.5.1:
resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==}
peerDependencies:
@@ -3786,6 +3794,11 @@ packages:
dependencies:
to-regex-range: 5.0.1
+ /filter-obj@5.1.0:
+ resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==}
+ engines: {node: '>=14.16'}
+ dev: false
+
/find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
@@ -5787,6 +5800,15 @@ packages:
resolution: {integrity: sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==}
dev: true
+ /query-string@8.1.0:
+ resolution: {integrity: sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw==}
+ engines: {node: '>=14.16'}
+ dependencies:
+ decode-uri-component: 0.4.1
+ filter-obj: 5.1.0
+ split-on-first: 3.0.0
+ dev: false
+
/querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
dev: true
@@ -6194,6 +6216,11 @@ packages:
deprecated: Please use @jridgewell/sourcemap-codec instead
dev: false
+ /split-on-first@3.0.0:
+ resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==}
+ engines: {node: '>=12'}
+ dev: false
+
/split@0.3.3:
resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==}
dependencies:
diff --git a/ui/filter/query-filter.tsx b/ui/filter/query-filter.tsx
new file mode 100644
index 00000000..6c6dda2a
--- /dev/null
+++ b/ui/filter/query-filter.tsx
@@ -0,0 +1,19 @@
+'use client';
+
+import { useTransition } from 'react';
+import type { ReactNode } from 'react';
+import { usePathname, useRouter } from 'next/navigation';
+
+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}>;
+};
diff --git a/ui/stats/filter.tsx b/ui/stats/stats-filter.tsx
similarity index 94%
rename from ui/stats/filter.tsx
rename to ui/stats/stats-filter.tsx
index 1bc1773d..619e4d8b 100644
--- a/ui/stats/filter.tsx
+++ b/ui/stats/stats-filter.tsx
@@ -15,7 +15,11 @@ export interface FilterProps {
// Component
// ---------------
-export const Filter = ({ children, dateRange, smallSamples }: FilterProps) => {
+export const StatsFilter = ({
+ children,
+ dateRange,
+ smallSamples,
+}: FilterProps) => {
const { replace } = useRouter();
const pathname = usePathname();
const [pending, startTransition] = useTransition();