Skip to content

Commit

Permalink
connects more filters
Browse files Browse the repository at this point in the history
  • Loading branch information
agnlez committed Nov 4, 2024
1 parent 9c453eb commit b462c98
Show file tree
Hide file tree
Showing 12 changed files with 554 additions and 48 deletions.
2 changes: 2 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
"@hookform/resolvers": "3.9.0",
"@lukemorales/query-key-factory": "1.3.4",
"@radix-ui/react-alert-dialog": "1.1.2",
"@radix-ui/react-checkbox": "1.1.2",
"@radix-ui/react-dialog": "1.1.2",
"@radix-ui/react-icons": "1.3.0",
"@radix-ui/react-label": "2.1.0",
"@radix-ui/react-select": "2.1.2",
"@radix-ui/react-separator": "1.1.0",
"@radix-ui/react-slider": "1.2.1",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-tabs": "1.1.1",
"@radix-ui/react-toast": "1.2.2",
Expand Down
6 changes: 6 additions & 0 deletions client/src/app/(projects)/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ export const FILTER_KEYS = [
"projectSizeFilter",
"priceType",
"totalCost",
"countryCode",
"ecosystem",
"activity",
"activitySubtype",
"cost",
"abatementPotential",
] as const;
17 changes: 12 additions & 5 deletions client/src/app/(projects)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import { useMap } from "react-map-gl";
import { motion } from "framer-motion";
import { useAtomValue } from "jotai";

import { cn } from "@/lib/utils";

import { LAYOUT_TRANSITIONS } from "@/app/(projects)/constants";
import { projectsUIState } from "@/app/(projects)/store";

import ProjectsFilters from "@/containers/projects/filters";
import ProjectsFilters, {
FILTERS_SIDEBAR_WIDTH,
} from "@/containers/projects/filters";
import ProjectsHeader from "@/containers/projects/header";
import ProjectsMap from "@/containers/projects/map";

Expand All @@ -21,6 +25,7 @@ import { useSidebar } from "@/components/ui/sidebar";
import ProjectsTable from "src/containers/projects/table";

const PANEL_MIN_SIZE = 25;
const PANEL_DEFAULT_SIZE = 50;

export default function Projects() {
const { filtersOpen } = useAtomValue(projectsUIState);
Expand All @@ -37,7 +42,9 @@ export default function Projects() {
<motion.div
layout
layoutDependency={navOpen}
className="mx-3 flex flex-1"
className={cn("flex flex-1", {
"mx-3": !filtersOpen,
})}
transition={LAYOUT_TRANSITIONS}
>
<motion.aside
Expand All @@ -46,7 +53,7 @@ export default function Projects() {
animate={filtersOpen ? "open" : "closed"}
variants={{
open: {
width: 450,
width: FILTERS_SIDEBAR_WIDTH,
},
closed: {
width: 0,
Expand All @@ -67,15 +74,15 @@ export default function Projects() {
className="flex flex-1 flex-col"
minSize={PANEL_MIN_SIZE}
onResize={onResizeMapPanel}
defaultSize={100}
defaultSize={PANEL_DEFAULT_SIZE}
>
<ProjectsMap />
</ResizablePanel>
<ResizableHandle withHandle className="my-3" />
<ResizablePanel
className="flex flex-1 flex-col"
minSize={PANEL_MIN_SIZE}
defaultSize={100}
defaultSize={PANEL_DEFAULT_SIZE}
>
<ProjectsTable />
</ResizablePanel>
Expand Down
41 changes: 25 additions & 16 deletions client/src/app/(projects)/url-store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import {
parseAsJson,
parseAsString,
parseAsStringLiteral,
useQueryState,
} from "nuqs";
import { ACTIVITY, RESTORATION_ACTIVITY } from "@shared/entities/activity.enum";
import { ECOSYSTEM } from "@shared/entities/ecosystem.enum";
import { parseAsJson, parseAsStringLiteral, useQueryState } from "nuqs";
import { z } from "zod";

import {
Expand All @@ -15,29 +12,41 @@ import {

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

const SUB_ACTIVITIES = RESTORATION_ACTIVITY;

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),
[FILTER_KEYS[4]]: z.string().optional(),
[FILTER_KEYS[5]]: z.array(z.nativeEnum(ECOSYSTEM)),
[FILTER_KEYS[6]]: z.array(z.nativeEnum(ACTIVITY)),
[FILTER_KEYS[7]]: z.array(z.nativeEnum(SUB_ACTIVITIES)),
[FILTER_KEYS[8]]: z.array(z.number()).length(2),
[FILTER_KEYS[9]]: z.array(z.number()).length(2),
});

export const INITIAL_FILTERS_STATE: z.infer<typeof filtersSchema> = {
keyword: "",
projectSizeFilter: "medium",
priceType: "market_price",
totalCost: "npv",
countryCode: "",
ecosystem: [],
activity: [],
activitySubtype: [],
cost: [0, 0],
abatementPotential: [0, 0],
};

export function useGlobalFilters() {
return useQueryState(
"filters",
parseAsJson(filtersSchema.parse).withDefault({
keyword: "",
projectSizeFilter: "medium",
priceType: "market_price",
totalCost: "npv",
}),
parseAsJson(filtersSchema.parse).withDefault(INITIAL_FILTERS_STATE),
);
}

export function useSyncCountry() {
return useQueryState("country", parseAsString.withDefault(""));
}

export function useTableView() {
return useQueryState(
"table",
Expand Down
31 changes: 31 additions & 0 deletions client/src/components/ui/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use client";

import * as React from "react";

import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { CheckIcon } from "@radix-ui/react-icons";

import { cn } from "@/lib/utils";

const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<CheckIcon className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;

export { Checkbox };
68 changes: 68 additions & 0 deletions client/src/components/ui/slider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use client";

import * as React from "react";

import * as SliderPrimitive from "@radix-ui/react-slider";

import { cn } from "@/lib/utils";

const Thumb = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Thumb>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Thumb>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Thumb
ref={ref}
className={cn(
"block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
className,
)}
{...props}
/>
));

Thumb.displayName = SliderPrimitive.Thumb.displayName;

const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<Thumb />
</SliderPrimitive.Root>
));

Slider.displayName = SliderPrimitive.Root.displayName;

const RangeSlider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<Thumb />
<Thumb />
</SliderPrimitive.Root>
));

RangeSlider.displayName = SliderPrimitive.Root.displayName;

export { Slider, RangeSlider };
Loading

0 comments on commit b462c98

Please sign in to comment.