diff --git a/app/components/FilterMenu.tsx b/app/components/FilterMenu.tsx
index 2425ed3..00a7cbd 100644
--- a/app/components/FilterMenu.tsx
+++ b/app/components/FilterMenu.tsx
@@ -5,7 +5,6 @@ import {
AccordionIcon,
AccordionItem,
AccordionPanel,
- Button,
Box,
} from "@nycplanning/streetscape";
@@ -37,9 +36,6 @@ export const FilterMenu = ({ children, defaultIndex }: FilterMenuProps) => (
{children}
-
diff --git a/app/components/GoToDistrictBtn/GoToCityCouncilDistrictBtn.test.tsx b/app/components/GoToDistrictBtn/GoToCityCouncilDistrictBtn.test.tsx
new file mode 100644
index 0000000..6a1624f
--- /dev/null
+++ b/app/components/GoToDistrictBtn/GoToCityCouncilDistrictBtn.test.tsx
@@ -0,0 +1,28 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { GoToCityCouncilDistrictBtn } from "./GoToCityCouncilDistrictBtn";
+
+describe("GoToCommunityDistrictBtn", () => {
+ it("should call 'goToDistrict' when all ids are provided", () => {
+ const goToDistrict = vi.fn();
+ render(
+ ,
+ );
+ fireEvent.click(screen.getByText(/Go to Selected District/));
+ expect(goToDistrict).toHaveBeenCalled();
+ });
+
+ it("should not call 'goToDistrict' when an id is null", () => {
+ const goToDistrict = vi.fn();
+ render(
+ ,
+ );
+ fireEvent.click(screen.getByText(/Go to Selected District/));
+ expect(goToDistrict).not.toHaveBeenCalled();
+ });
+});
diff --git a/app/components/GoToDistrictBtn/GoToCityCouncilDistrictBtn.tsx b/app/components/GoToDistrictBtn/GoToCityCouncilDistrictBtn.tsx
new file mode 100644
index 0000000..eca549b
--- /dev/null
+++ b/app/components/GoToDistrictBtn/GoToCityCouncilDistrictBtn.tsx
@@ -0,0 +1,22 @@
+import { GoToDistrictBtn, GoToDistrictBtnProps } from ".";
+
+export interface GoToCityCouncilDistrictBtnProps
+ extends Pick {
+ districtId: string | null;
+}
+
+export function GoToCityCouncilDistrictBtn({
+ districtId,
+ ...props
+}: GoToCityCouncilDistrictBtnProps) {
+ return (
+
+ );
+}
diff --git a/app/components/GoToDistrictBtn/GoToCommunityDistrictBtn.test.tsx b/app/components/GoToDistrictBtn/GoToCommunityDistrictBtn.test.tsx
new file mode 100644
index 0000000..d56f502
--- /dev/null
+++ b/app/components/GoToDistrictBtn/GoToCommunityDistrictBtn.test.tsx
@@ -0,0 +1,30 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { GoToCommunityDistrictBtn } from "./GoToCommunityDistrictBtn";
+
+describe("GoToCommunityDistrictBtn", () => {
+ it("should call 'goToDistrict' when all ids are provided", () => {
+ const goToDistrict = vi.fn();
+ render(
+ ,
+ );
+ fireEvent.click(screen.getByText(/Go to Selected District/));
+ expect(goToDistrict).toHaveBeenCalled();
+ });
+
+ it("should not call 'goToDistrict' when an id is null", () => {
+ const goToDistrict = vi.fn();
+ render(
+ ,
+ );
+ fireEvent.click(screen.getByText(/Go to Selected District/));
+ expect(goToDistrict).not.toHaveBeenCalled();
+ });
+});
diff --git a/app/components/GoToDistrictBtn/GoToCommunityDistrictBtn.tsx b/app/components/GoToDistrictBtn/GoToCommunityDistrictBtn.tsx
new file mode 100644
index 0000000..f4777ee
--- /dev/null
+++ b/app/components/GoToDistrictBtn/GoToCommunityDistrictBtn.tsx
@@ -0,0 +1,24 @@
+import { GoToDistrictBtn, GoToDistrictBtnProps } from ".";
+
+export interface GoToCommunityDistrictBtnProps
+ extends Pick {
+ boroughId: string | null;
+ districtId: string | null;
+}
+
+export function GoToCommunityDistrictBtn({
+ boroughId,
+ districtId,
+ ...props
+}: GoToCommunityDistrictBtnProps) {
+ return (
+
+ );
+}
diff --git a/app/components/GoToDistrictBtn/index.test.tsx b/app/components/GoToDistrictBtn/index.test.tsx
new file mode 100644
index 0000000..f40316d
--- /dev/null
+++ b/app/components/GoToDistrictBtn/index.test.tsx
@@ -0,0 +1,24 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { GoToDistrictBtn } from ".";
+
+describe("GoToDistrictBtn", () => {
+ it("should render with 'Go To' text", () => {
+ const goToDistrict = vi.fn();
+ render();
+ expect(screen.getByText(/Go to Selected District/)).toBeVisible();
+ });
+
+ it("should call 'goToDistrict' when path is a string", () => {
+ const goToDistrict = vi.fn();
+ render();
+ fireEvent.click(screen.getByText(/Go to Selected District/));
+ expect(goToDistrict).toHaveBeenCalled();
+ });
+
+ it("should not call 'goToDistrict' when path is null", () => {
+ const goToDistrict = vi.fn();
+ render();
+ fireEvent.click(screen.getByText(/Go to Selected District/));
+ expect(goToDistrict).not.toHaveBeenCalled();
+ });
+});
diff --git a/app/components/GoToDistrictBtn/index.tsx b/app/components/GoToDistrictBtn/index.tsx
new file mode 100644
index 0000000..af49267
--- /dev/null
+++ b/app/components/GoToDistrictBtn/index.tsx
@@ -0,0 +1,20 @@
+import { Button } from "@nycplanning/streetscape";
+
+export { GoToCityCouncilDistrictBtn } from "./GoToCityCouncilDistrictBtn";
+
+export interface GoToDistrictBtnProps {
+ goToDistrict: (path: string) => void;
+ path: string | null;
+}
+export function GoToDistrictBtn({ goToDistrict, path }: GoToDistrictBtnProps) {
+ return (
+
+ );
+}
diff --git a/app/root.tsx b/app/root.tsx
index 2f9355b..a50597d 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -15,6 +15,8 @@ import {
ScrollRestoration,
isRouteErrorResponse,
useLoaderData,
+ useLocation,
+ useNavigate,
useRouteError,
useSearchParams,
} from "@remix-run/react";
@@ -38,6 +40,11 @@ import {
CityCouncilDistrictDropdown,
} from "./components/AdminDropdown";
import { URLSearchParamsInit } from "react-router-dom";
+import {
+ GoToCityCouncilDistrictBtn,
+ GoToDistrictBtn,
+} from "./components/GoToDistrictBtn";
+import { GoToCommunityDistrictBtn } from "./components/GoToDistrictBtn/GoToCommunityDistrictBtn";
export type BoroughId = null | string;
export type DistrictType = null | "cd" | "ccd";
@@ -126,6 +133,8 @@ function Document({
}
export default function App() {
+ const navigate = useNavigate();
+ const { pathname } = useLocation();
const [searchParams, setSearchParams] = useSearchParams();
const districtType = searchParams.get("districtType") as DistrictType;
const boroughId = searchParams.get("boroughId") as BoroughId;
@@ -146,33 +155,62 @@ export default function App() {
| undefined,
) => setSearchParams(nextSearchParams, { replace: true });
- const AdminDropdowns = () => (
-
-
-
-
- {districtType !== "ccd" ? (
- (nextPath: string) => {
+ // Avoid adding the same path to the history stack multiple times
+ if (currentPath !== `/${nextPath}`)
+ navigate({
+ pathname: nextPath,
+ search: `?${searchParams.toString()}`,
+ });
+ };
+
+ const goToNextDistrict = goToDistrict(pathname);
+
+ const FilterMenuContent = () => (
+ <>
+
+
- ) : (
-
+
+ {districtType !== "ccd" ? (
+
+ ) : (
+
+ )}
+
+ {districtType === null && (
+
+ )}
+ {districtType === "ccd" && (
+
+ )}
+ {districtType === "cd" && (
+
)}
-
+ >
);
return (
@@ -185,12 +223,12 @@ export default function App() {
-
+
-
+