Skip to content

Commit

Permalink
sync some filters with URL
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgnlez committed Oct 24, 2024
1 parent d635fdf commit 3737abc
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 58 deletions.
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"mapbox-gl": "3.7.0",
"next": "14.2.10",
"next-auth": "4.24.8",
"nuqs": "2.0.4",
"react": "^18",
"react-dom": "^18",
"react-map-gl": "7.1.7",
Expand Down
14 changes: 14 additions & 0 deletions client/src/app/(projects)/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,17 @@ export const LAYOUT_TRANSITIONS = {
duration: 0.4,
ease: "easeInOut",
};

export const PROJECT_SIZE_VALUES = ["small", "medium", "large"] as const;
export const CARBON_PRICING_TYPE_VALUES = [
"market_price",
"opex_breakeven_price",
] as const;
export const COST_VALUES = ["total", "npv"] as const;

export const FILTER_KEYS = [
"keyword",
"projectSize",
"carbonPricingType",
"cost",
] as const;
14 changes: 0 additions & 14 deletions client/src/app/(projects)/store.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { atom } from "jotai";

import { PROJECT_PARAMETERS } from "@/containers/projects/header/parameters";

export const projectsUIState = atom<{
filtersOpen: boolean;
mapExpanded: "default" | "expanded" | "collapsed";
Expand All @@ -17,15 +15,3 @@ export const projectsMapState = atom<{
}>({
legendOpen: true,
});

export const projectsFiltersState = atom<{
keyword: string | undefined;
projectSize: (typeof PROJECT_PARAMETERS)[0]["options"][number]["value"];
carbonPricingType: (typeof PROJECT_PARAMETERS)[1]["options"][number]["value"];
cost: (typeof PROJECT_PARAMETERS)[2]["options"][number]["value"];
}>({
keyword: undefined,
projectSize: "medium",
carbonPricingType: "market_price",
cost: "npv",
});
37 changes: 37 additions & 0 deletions client/src/app/(projects)/url-store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { parseAsJson, parseAsStringLiteral, useQueryState } from "nuqs";
import { z } from "zod";

import {
PROJECT_SIZE_VALUES,
CARBON_PRICING_TYPE_VALUES,
COST_VALUES,
FILTER_KEYS,
} from "@/app/(projects)/constants";

import { TABLE_MODES } from "@/containers/projects/table-visualization/toolbar/table-selector";

export const filtersSchema = z.object({
[FILTER_KEYS[0]]: z.string().optional(),
[FILTER_KEYS[1]]: z.enum(PROJECT_SIZE_VALUES),
[FILTER_KEYS[2]]: z.enum(CARBON_PRICING_TYPE_VALUES),
[FILTER_KEYS[3]]: z.enum(COST_VALUES),
});

export function useGlobalFilters() {
return useQueryState(
"filters",
parseAsJson(filtersSchema.parse).withDefault({
keyword: "",
projectSize: "medium",
carbonPricingType: "market_price",
cost: "npv",
}),
);
}

export function useTableMode() {
return useQueryState(
"table",
parseAsStringLiteral(TABLE_MODES).withDefault("overview"),
);
}
17 changes: 10 additions & 7 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { PropsWithChildren } from "react";

import { Inter } from "next/font/google";

import type { Metadata } from "next";
import "@/app/globals.css";
import { getServerSession } from "next-auth";
import { NuqsAdapter } from "nuqs/adapters/next/app";

import { config } from "@/app/auth/api/[...nextauth]/config";

Expand All @@ -19,18 +22,18 @@ export const metadata: Metadata = {

export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
}: Readonly<PropsWithChildren>) {
const session = await getServerSession(config);

return (
<LayoutProviders session={session}>
<html lang="en">
<body className={inter.className}>
<main>{children}</main>
<Toaster />
</body>
<NuqsAdapter>
<body className={inter.className}>
<main>{children}</main>
<Toaster />
</body>
</NuqsAdapter>
</html>
</LayoutProviders>
);
Expand Down
48 changes: 24 additions & 24 deletions client/src/containers/projects/header/parameters/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { useAtom, ExtractAtomValue } from "jotai";
import { z } from "zod";

import { projectsFiltersState } from "@/app/(projects)/store";
import {
CARBON_PRICING_TYPE_VALUES,
COST_VALUES,
FILTER_KEYS,
PROJECT_SIZE_VALUES,
} from "@/app/(projects)/constants";
import { useGlobalFilters } from "@/app/(projects)/url-store";
import { filtersSchema } from "@/app/(projects)/url-store";

import { Label } from "@/components/ui/label";
import {
Expand All @@ -10,70 +17,63 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";

export const PROJECT_PARAMETERS = [
{
key: FILTER_KEYS[1],
label: "Project size",
key: "projectSize",
defaultValue: "medium",
options: [
{
label: "Small",
value: "small",
value: PROJECT_SIZE_VALUES[0],
},
{
label: "Medium",
value: "medium",
value: PROJECT_SIZE_VALUES[1],
},
{
label: "Large",
value: "large",
value: PROJECT_SIZE_VALUES[2],
},
],
},
{
key: FILTER_KEYS[2],
label: "Carbon pricing type",
key: "carbonPricingType",
defaultValue: "market_price",
options: [
{
label: "Market price",
value: "market_price",
value: CARBON_PRICING_TYPE_VALUES[0],
},
{
label: "OPEX Breakeven price",
value: "opex_breakeven_price",
value: CARBON_PRICING_TYPE_VALUES[1],
},
],
},
{
key: FILTER_KEYS[3],
label: "Cost",
key: "cost",
defaultValue: "npv",
options: [
{
label: "Total",
value: "total",
value: COST_VALUES[0],
},
{
label: "NPV",
value: "npv",
value: COST_VALUES[1],
},
],
},
] as const;

export default function ParametersProjects() {
const [, setFilters] = useAtom(projectsFiltersState);
const [filters, setFilters] = useGlobalFilters();

const handleParameters = (
const handleParameters = async (
v: string,
parameter: keyof Omit<
ExtractAtomValue<typeof projectsFiltersState>,
"keyword"
>,
parameter: keyof Omit<z.infer<typeof filtersSchema>, "keyword">,
) => {
setFilters((prev) => ({ ...prev, [parameter]: v }));
await setFilters((prev) => ({ ...prev, [parameter]: v }));
};

return (
Expand All @@ -83,7 +83,7 @@ export default function ParametersProjects() {
<Label htmlFor={parameter.label}>{parameter.label}</Label>
<Select
name={parameter.label}
defaultValue={parameter.defaultValue}
defaultValue={filters[parameter.key]}
onValueChange={(v) => {
handleParameters(v, parameter.key);
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { ComponentProps } from "react";

import { useSetAtom } from "jotai";

import { projectsFiltersState } from "@/app/(projects)/store";
import { useGlobalFilters } from "@/app/(projects)/url-store";

import Search from "@/components/ui/search";

export default function SearchProjectsTable() {
const setFilters = useSetAtom(projectsFiltersState);
const handleSearch = (
const [, setFilters] = useGlobalFilters();

const handleSearch = async (
v: Parameters<ComponentProps<typeof Search>["onChange"]>[0],
) => {
setFilters((prev) => ({ ...prev, keyword: v }));
await setFilters((prev) => ({ ...prev, keyword: v }));
};

return <Search placeholder="Search project" onChange={handleSearch} />;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
import { useTableMode } from "@/app/(projects)/url-store";

import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";

const TABS = [
export const TABLE_MODES = [
"overview",
"scorecard-prioritization",
"key-costs",
] as const;

export const TABLE_TABS = [
{
label: "Overview",
value: "overview",
value: TABLE_MODES[0],
},
{
label: "Scorecard Prioritization",
value: "scorecard-prioritization",
value: TABLE_MODES[1],
},
{
label: "Key costs",
value: "key-costs",
value: TABLE_MODES[2],
},
];
] as const;

export default function TabsProjectsTable() {
const [tableMode, setTableMode] = useTableMode();
return (
<Tabs defaultValue={TABS[0].value}>
<Tabs
defaultValue={tableMode}
onValueChange={async (v) => {
await setTableMode(v as typeof tableMode);
}}
>
<TabsList>
{TABS.map(({ label, value }) => (
{TABLE_TABS.map(({ label, value }) => (
<TabsTrigger key={value} value={value}>
{label}
</TabsTrigger>
Expand Down
31 changes: 31 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3737abc

Please sign in to comment.