- {/* link to different pages */}
-
-
- } text="Resources" />
-
-
- } text="Services" />
-
-
- } text="Training Manuals" />
-
-
- {/* search bar */}
-
+
+
+
+ Good evening!
+
+
+
);
}
diff --git a/compass/components/resource/LandingSearchBar.tsx b/compass/components/resource/LandingSearchBar.tsx
index afce772..399a71d 100644
--- a/compass/components/resource/LandingSearchBar.tsx
+++ b/compass/components/resource/LandingSearchBar.tsx
@@ -1,17 +1,41 @@
+import { FunnelIcon as FunnelIconOutline } from "@heroicons/react/24/outline";
import {
+ ArchiveBoxIcon,
ChevronDownIcon,
+ FunnelIcon,
MagnifyingGlassIcon,
+ TagIcon,
XMarkIcon,
} from "@heroicons/react/24/solid";
-import React, { useState } from "react";
+import React, {
+ ReactNode,
+ SetStateAction,
+ useState,
+ useRef,
+ useEffect,
+} from "react";
import Image from "next/image";
-import { FilterBox } from "../FilterBox";
+import { SearchResult } from "./SearchResult";
+
+// TODO: Actually implement search.
+import sampleResults from "./sample_results.json";
export const LandingSearchBar: React.FC = () => {
const [searchTerm, setSearchTerm] = useState("");
+ const [showFilters, setShowFilters] = useState(false);
const [showFilterBox, setShowFilterBox] = useState(false);
const toggleFilterBox = () => setShowFilterBox((prev) => !prev);
+ const collections = ["Resources", "Services"];
+ const [selectedCollections, setSelectedCollections] = useState(
+ new Array(collections.length).fill(false)
+ );
+
+ const tags = ["Food Relief", "Period Poverty", "Nutrition Education"];
+ const [selectedTags, setSelectedTags] = useState(
+ new Array(tags.length).fill(false)
+ );
+
const handleSearchChange = (event: React.ChangeEvent
) => {
setSearchTerm(event.target.value);
};
@@ -21,53 +45,235 @@ export const LandingSearchBar: React.FC = () => {
};
return (
-
+
{/* searchbar */}
-
-
-
-
- {/* input */}
- {searchTerm && (
-
-
+
+ {/* Left side: magnifying glass icon and input */}
+
+
+
+
+ {/* Right side icons */}
+
+ {/* If search bar is not empty, include clear icon */}
+ {searchTerm && (
+
+
+
+ )}
+ {/* Filter button */}
+
setShowFilters(!showFilters)}
+ >
+ {!showFilters && (
+
+ )}
+ {showFilters && (
+
+ )}
- )}
-
-
-
-
- {showFilterBox && }
-
+
+ {/* Search filters */}
+
+
+
+
+
{/* search results, for now since it's empty this is the default screen */}
-
+
0 ? " hidden" : "")
+ }
+ >
-
- Need to find something? Use the links or the search bar
- above to get your results.
-
+
+ Need to find something? Use the search bar above to get your
+ results.
+
+
+
+
0 ? "" : " hidden")
+ }
+ >
+ {sampleResults.map((result, i) => (
+
+ ))}
+
+
+ );
+};
+
+// Closes the filter dropdown when the user clicks outside the dropdown.
+const useFilterPillDropdown = (
+ ref: React.RefObject
,
+ setShowDropdown: Function
+) => {
+ // Close on outside click
+ useEffect(() => {
+ const handleClickOutside = (event: MouseEvent) => {
+ if (ref.current && !ref.current.contains(event.target as Node)) {
+ if (setShowDropdown) setShowDropdown(false);
+ }
+ };
+
+ document.addEventListener("mousedown", handleClickOutside);
+ return () =>
+ // Unbind the event listener on cleanup.
+ document.removeEventListener("mousedown", handleClickOutside);
+ }, [ref, setShowDropdown]);
+};
+
+// Props for the filter pill...
+interface FilterPillProps {
+ icon: React.ForwardRefExoticComponent<
+ Omit, "ref">
+ >;
+ name: string;
+ searchBar?: boolean;
+ options: string[];
+ selectedOptions: boolean[];
+ setSelectedOptions: React.Dispatch>;
+}
+
+// The filter pill (visible when filter button active, contains dropdown)
+const FilterPill: React.FC = ({
+ icon,
+ name,
+ options,
+ selectedOptions,
+ setSelectedOptions,
+ searchBar = false,
+}) => {
+ const Icon = icon;
+ const [showDropdown, setShowDropdown] = useState(false);
+ const [isActive, setIsActive] = useState(false);
+ const dropdownRef = useRef(null);
+
+ const handleCheck = (
+ e: React.ChangeEvent,
+ item: string
+ ) => {
+ const selected = selectedOptions.map((o, i) => {
+ if (i == options.indexOf(item)) {
+ return e.target.checked;
+ } else {
+ return o;
+ }
+ });
+
+ setSelectedOptions(selected);
+ setIsActive(selected.includes(true));
+ };
+
+ // Closes dropdown when clicked outside
+ useFilterPillDropdown(dropdownRef, setShowDropdown);
+
+ return (
+
);
diff --git a/compass/components/resource/SearchResult.tsx b/compass/components/resource/SearchResult.tsx
new file mode 100644
index 0000000..42b1b9e
--- /dev/null
+++ b/compass/components/resource/SearchResult.tsx
@@ -0,0 +1,44 @@
+import React from "react";
+import {
+ BookmarkIcon,
+ ClipboardIcon,
+ QuestionMarkCircleIcon,
+ ArrowUturnRightIcon,
+} from "@heroicons/react/24/solid";
+
+interface SearchResultProps {
+ type: "resource" | "service" | string;
+ name: string;
+ description: string;
+}
+
+export const SearchResult: React.FC = ({
+ type,
+ name,
+ description,
+}) => {
+ const Icon: React.ForwardRefExoticComponent<
+ Omit, "ref">
+ > =
+ type === "resource"
+ ? BookmarkIcon
+ : type === "service"
+ ? ClipboardIcon
+ : QuestionMarkCircleIcon; // Unknown type
+
+ return (
+
+ {/* Left side of the item */}
+
+
+
+ {name}
+
+
+ {description}
+
+
+
+
+ );
+};
diff --git a/compass/components/resource/sample_results.json b/compass/components/resource/sample_results.json
new file mode 100644
index 0000000..275250c
--- /dev/null
+++ b/compass/components/resource/sample_results.json
@@ -0,0 +1,32 @@
+[
+ {
+ "type": "resource",
+ "name": "example name",
+ "description": "example description"
+ },
+ {
+ "type": "service",
+ "name": "example name",
+ "description": "example description"
+ },
+ {
+ "type": "resource",
+ "name": "National Domestic Violence Hotline",
+ "description": "24/7 confidential support for victims of domestic violence"
+ },
+ {
+ "type": "resource",
+ "name": "Legal Aid Society",
+ "description": "Free legal assistance for low-income individuals"
+ },
+ {
+ "type": "service",
+ "name": "Crisis Hotline",
+ "description": "24/7 support for individuals in crisis"
+ },
+ {
+ "type": "unknown",
+ "name": "unknown thing with a really long name",
+ "description": "and let's also type out a really long description to see how it handles overflow and all that anyways"
+ }
+]