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
5 changes: 4 additions & 1 deletion 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 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
59 changes: 22 additions & 37 deletions frontend/src/main-page/grants/filter-bar/FilterBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
//import { Link } from "react-router-dom";
import {
Status,
stringToStatus,
Expand All @@ -8,8 +8,9 @@ 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";

interface FilterBarProps {
name: string;
Expand Down Expand Up @@ -44,40 +45,24 @@ const FilterBar: React.FC = observer(() => {
}

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 className="flex items-center gap-2 border-2 border-grey-400 rounded-full px-5 py-2 bg-white text-grey-900 text-base whitespace-nowrap shadow-xl">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These buttons should all use the reusable button component and probably map over a dictionary with name and icon. Instead of ascii characters, they should be react icons. See other uses of button in the codebase to see how to do the icon button param for the reusable component

My Grants
</button>
<button className="flex items-center gap-2 border border-grey-400 rounded-full px-5 py-2 bg-white text-grey-900 text-base whitespace-nowrap">
BCAN Eligible
</button>
<button className="flex items-center gap-2 border border-grey-400 rounded-full px-5 py-2 bg-white text-grey-900 text-base whitespace-nowrap">
⇅ Alphabetical
</button>
<button className="flex items-center gap-2 border border-grey-400 rounded-full px-5 py-2 bg-white text-grey-900 text-base whitespace-nowrap">
⇅ Due Date
</button>
<button className="flex items-center gap-2 border border-grey-400 rounded-full px-5 py-2 bg-white text-grey-900 text-base whitespace-nowrap">
⇅ Grant Amount
</button>
<StatusDropdown />
</div>
);
});

Expand Down
72 changes: 72 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,72 @@

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";

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
className="flex items-center gap-2 border border-grey-400 rounded-full px-5 py-2 bg-white text-grey-900 text-base whitespace-nowrap"
onClick={() => setIsOpen(!isOpen)}
>
Status {isOpen ? "∧" : "∨"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same not from above - Button should use the reusable button component and probably map over a dictionary with name and icon. Instead of ascii characters, they should be react icons. See other uses of button in the codebase to see how to do the icon button param for the reusable component

</button>

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would double check that setting a hardcoded min width with pixels is responsive enough on small screens. typically I would say this should at least be rem

<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