Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 2 additions & 20 deletions backend/package-lock.json

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

7 changes: 5 additions & 2 deletions frontend/src/main-page/grants/GrantPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import GrantSearch from "./filter-bar/GrantSearch.tsx";
import NewGrantModal from "./new-grant/NewGrantModal.tsx";
import { useEffect, useState } from "react";
import { Grant } from "../../../../middle-layer/types/Grant.ts";
import FilterBar from "./filter-bar/FilterBar.tsx";
import GrantItem from "./grant-view/GrantView.tsx";
import { useAuthContext } from "../../context/auth/authContext";
import {
Expand All @@ -21,7 +22,7 @@ import { Navigate } from "react-router-dom";
import BellButton from "../navbar/Bell.tsx";
import GrantCard from "./grant-list/GrantCard.tsx";
import { api } from "../../api.ts";
import Button from "../../components/Button.tsx";
//import Button from "../../components/Button.tsx";

// still needed potentially?
interface GrantPageProps {
Expand Down Expand Up @@ -114,7 +115,9 @@ function GrantPage({}: GrantPageProps) {
</div>
<GrantSearch />
<div className="flex w-full justify-between py-2 gap-4">
<Button text="Filters Coming Soon" onClick={() => {}} className="border-2 border-grey-500 bg-white" />
<span className="text-lg font-semibold">
<FilterBar />
</span>
<AddGrantButton onClick={() => setShowNewGrantModal(true)} />
</div>

Expand Down
68 changes: 31 additions & 37 deletions frontend/src/main-page/grants/filter-bar/FilterBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import {
updateFilter,
} from "../../../external/bcanSatchel/actions.ts";
import { observer } from "mobx-react-lite";
import CalendarDropdown from "./CalendarDropdown.tsx";
import { FaChevronRight } from "react-icons/fa";
//import CalendarDropdown from "./CalendarDropdown.tsx";
//import { FaChevronRight } from "react-icons/fa";
import StatusDropdown from "./StatusDropdown";
import Button from "../../../components/Button";
import { faSort } from "@fortawesome/free-solid-svg-icons";

interface FilterBarProps {
name: string;
Expand All @@ -29,7 +32,7 @@ const linkList: FilterBarProps[] = [
/**
* SortBar provides the sorting options for grants in the side bar
*/
const FilterBar: React.FC = observer(() => {
const FilterBar: React.FC = observer(() => {
const [selected, setSelected] = useState("All Grants");
function categoryClicked(
e: React.MouseEvent,
Expand All @@ -43,41 +46,32 @@ const FilterBar: React.FC = observer(() => {
}
}

const sortButtons = ["Alphabetical", "Due Date", "Grant Amount"];

return (
<div className="sortbar flex flex-col gap-4 bg-grey-100 p-6 rounded-[1.2rem] border-[0.1rem] border-black">
<div>
<div className="flex pb-2">{"Filter by Date"}</div>
<CalendarDropdown />
</div>
<div>
<div className="flex pb-2">{"Filter by Status"}</div>
<ul className="flex flex-col gap-2">
{linkList.map((item, index) => (
<li key={index}>
<Link
onClick={(e) => categoryClicked(e, item.name, item.linkTo)}
to={item.linkTo ? item.linkTo : "#"}
>
<div
className={`border hover:bg-primary-800 ${
selected === item.name ? "bg-primary-900" : "bg-white"
}`}
>
<div
className={`flex w-full justify-between items-center ${
selected === item.name ? "text-white" : "text-black"
}`}
>
{item.name}
<FaChevronRight />
</div>
</div>
</Link>
</li>
))}
</ul>
</div>
</div>
<div className="flex items-center gap-2 flex-wrap">
<Button
text="My Grants"
onClick={() => {}}
className="border-grey-400 bg-white text-grey-900 text-base whitespace-nowrap shadow-xl"
/>
<Button
text="BCAN Eligible"
onClick={() => {}}
className="border-grey-400 bg-white text-grey-900 text-base border-2 whitespace-nowrap"
/>
{sortButtons.map((name) => (
<Button
key={name}
text={name}
onClick={() => {}}
logo={faSort}
logoPosition="left"
className="border-grey-400 bg-white text-grey-900 text-base whitespace-nowrap"
/>
))}
<StatusDropdown />
</div>
);
});

Expand Down
75 changes: 75 additions & 0 deletions frontend/src/main-page/grants/filter-bar/StatusDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

import React, { useState } from "react";
import {
Status,
getColorStatus,
} from "../../../../../middle-layer/types/Status.ts";
import { updateFilter } from "../../../external/bcanSatchel/actions.ts";
import { observer } from "mobx-react-lite";
import Button from "../../../components/Button";
import { faChevronDown, faChevronUp } from "@fortawesome/free-solid-svg-icons";

const StatusDropdown: React.FC = observer(() => {
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState<Status | null>(null);

const statuses = [
Status.Active,
Status.Pending,
Status.Potential,
Status.Rejected,
Status.Inactive,
];

function handleSelect(status: Status) {
const newSelected = selected === status ? null : status;
setSelected(newSelected);
updateFilter(newSelected);
}


return (
<div className="relative">
<Button
text="Status"
onClick={() => setIsOpen(!isOpen)}
logo={isOpen ? faChevronUp : faChevronDown}
logoPosition="right"
className="border-grey-400 bg-white text-grey-900 text-base whitespace-nowrap"
/>

{isOpen && (
<div className="absolute top-12 left-0 bg-white border border-primary-900 rounded-md p-4 z-50 shadow-lg min-w-[25rem] overflow-x-auto">

<div className="grid grid-cols-3 gap-2">
{statuses.map((status) => (
<div
key={status}
className="flex items-center gap-2 cursor-pointer"
onClick={() => handleSelect(status)}
>
<input
type="checkbox"
checked={selected === status}
onChange={() => handleSelect(status)}
className="cursor-pointer w-4 h-4 flex-shrink-0"
/>
<span
className="px-3 py-1 rounded-full text-sm font-medium"
style={{
backgroundColor: getColorStatus(status, "light"),
color: getColorStatus(status, "dark"),
}}
>
{status}
</span>
</div>
))}
</div>
</div>
)}
</div>
);
});

export default StatusDropdown;
Loading