diff --git a/frontend/src/main-page/grants/GrantPage.tsx b/frontend/src/main-page/grants/GrantPage.tsx
index 9033560..e90fd20 100644
--- a/frontend/src/main-page/grants/GrantPage.tsx
+++ b/frontend/src/main-page/grants/GrantPage.tsx
@@ -4,10 +4,22 @@ import FilterBar from "./filter-bar/FilterBar.tsx";
import GrantItem from "./grant-view/GrantView.tsx";
import { observer } from "mobx-react-lite";
import { ProcessGrantData } from "./filter-bar/processGrantData.ts";
+import {
+ amountRangeFilter,
+ dateRangeFilter,
+ eligibleFilter,
+ filterGrants,
+ searchFilter,
+ statusFilter,
+ userEmailFilter,
+ yearFilterer,
+} from "./filter-bar/grantFilters.ts";
import GrantCard from "./grant-view/components/GrantCard.tsx";
import Button from "../../components/Button.tsx";
import EditGrant from "./edit-grant/EditGrant.tsx";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
+import { clearAllFilters } from "../../external/bcanSatchel/actions.ts";
+import { getAppStore } from "../../external/bcanSatchel/store.ts";
function GrantPage() {
const [showEditGrant, setShowEditGrant] = useState(false);
@@ -21,11 +33,55 @@ function GrantPage() {
grants[0] ??
null;
- // When the first grant in the list changes (sort/filter/initial load), show it
- const firstGrantId = grants[0]?.grantId ?? null;
+ const handleGrantCreated = (grantId: number) => {
+ setCurId(grantId);
+
+ const {
+ allGrants,
+ filterStatus,
+ startDateFilter,
+ endDateFilter,
+ yearFilter,
+ searchQuery,
+ emailFilter,
+ eligibleOnly,
+ amountMinFilter,
+ amountMaxFilter,
+ user,
+ } = getAppStore();
+
+ const createdGrant = allGrants.find((grant) => grant.grantId === grantId);
+
+ if (createdGrant) {
+ const grantIsVisible =
+ filterGrants([createdGrant], [
+ statusFilter(filterStatus),
+ eligibleFilter(eligibleOnly),
+ dateRangeFilter(startDateFilter, endDateFilter),
+ amountRangeFilter(amountMinFilter, amountMaxFilter),
+ yearFilterer(yearFilter),
+ searchFilter(searchQuery),
+ userEmailFilter(emailFilter, user),
+ ]).length > 0;
+
+ if (!grantIsVisible) {
+ clearAllFilters();
+ }
+ }
+ };
+
+ // Preserve current selection when still visible; otherwise show the first visible grant.
useEffect(() => {
- setCurId(grants.length > 0 ? grants[0].grantId : null);
- }, [firstGrantId]);
+ if (grants.length === 0) {
+ setCurId(null);
+ return;
+ }
+
+ const currentSelectionStillVisible = grants.some((grant) => grant.grantId === curId);
+ if (!currentSelectionStillVisible) {
+ setCurId(grants[0].grantId);
+ }
+ }, [curId, grants]);
return (
@@ -64,6 +120,7 @@ function GrantPage() {
{showEditGrant && (
{
setShowEditGrant(false);
}}
diff --git a/frontend/src/main-page/grants/edit-grant/EditGrant.tsx b/frontend/src/main-page/grants/edit-grant/EditGrant.tsx
index 43f7592..8a0dfc0 100644
--- a/frontend/src/main-page/grants/edit-grant/EditGrant.tsx
+++ b/frontend/src/main-page/grants/edit-grant/EditGrant.tsx
@@ -42,7 +42,8 @@ export interface GrantFormState {
const EditGrant: React.FC<{
grantToEdit: Grant | null;
onClose: () => void;
-}> = observer(({ grantToEdit, onClose }) => {
+ onGrantCreated?: (grantId: number) => void;
+}> = observer(({ grantToEdit, onClose, onGrantCreated }) => {
// State to track if form was submitted successfully
const [saving, setSaving] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
@@ -144,6 +145,9 @@ const EditGrant: React.FC<{
: await createNewGrant(grantData);
if (result.success) {
+ if (!grantToEdit && result.grantId != null) {
+ onGrantCreated?.(result.grantId);
+ }
setSaving(false);
onClose();
} else {
diff --git a/frontend/src/main-page/grants/edit-grant/processGrantDataEditSave.ts b/frontend/src/main-page/grants/edit-grant/processGrantDataEditSave.ts
index 81b956b..1a57637 100644
--- a/frontend/src/main-page/grants/edit-grant/processGrantDataEditSave.ts
+++ b/frontend/src/main-page/grants/edit-grant/processGrantDataEditSave.ts
@@ -4,8 +4,14 @@ import { api } from "../../../api.ts";
import { GrantFormState } from "./EditGrant.tsx";
import { fetchGrants } from "../filter-bar/processGrantData.ts";
+export type GrantMutationResult =
+ | { success: true; grantId?: number }
+ | { success: false; error: string };
+
// save a new grant
-export const createNewGrant = async (newGrant: Grant) => {
+export const createNewGrant = async (
+ newGrant: Grant
+): Promise => {
try {
const response = await api("/grant/new-grant", {
method: "POST",
@@ -14,8 +20,9 @@ export const createNewGrant = async (newGrant: Grant) => {
});
if (response.ok) {
+ const createdGrantId = (await response.json()) as number;
await fetchGrants();
- return { success: true };
+ return { success: true, grantId: createdGrantId };
} else {
const errorData = await response.json();
throw new Error(errorData.message || "Failed to create grant");
@@ -34,7 +41,9 @@ export const createNewGrant = async (newGrant: Grant) => {
}
};
-export const saveGrantEdits = async (updatedGrant: Grant) => {
+export const saveGrantEdits = async (
+ updatedGrant: Grant
+): Promise => {
try {
const response = await api("/grant/save", {
method: "PUT",
diff --git a/frontend/src/main-page/grants/filter-bar/FilterBar.tsx b/frontend/src/main-page/grants/filter-bar/FilterBar.tsx
index 8a9c6c6..1858c97 100644
--- a/frontend/src/main-page/grants/filter-bar/FilterBar.tsx
+++ b/frontend/src/main-page/grants/filter-bar/FilterBar.tsx
@@ -25,6 +25,7 @@ const FilterBar: React.FC = observer(() => {
emailFilter,
eligibleOnly,
sort,
+ filterStatus,
startDateFilter,
endDateFilter,
amountMinFilter,
@@ -34,7 +35,6 @@ const FilterBar: React.FC = observer(() => {
const [showDueDateCard, setShowDueDateCard] = useState(false);
const [showAmountCard, setShowAmountCard] = useState(false);
const [showStatusDropdown, setShowStatusDropdown] = useState(false);
- const [selectedStatus, setSelectedStatus] = useState(null);
const dueDateDropdownRef = useRef(null);
const amountDropdownRef = useRef(null);
const statusDropdownRef = useRef(null);
@@ -82,8 +82,7 @@ const FilterBar: React.FC = observer(() => {
};
const handleStatusSelect = (status: Status) => {
- const newSelected = selectedStatus === status ? null : status;
- setSelectedStatus(newSelected);
+ const newSelected = filterStatus === status ? null : status;
updateFilter(newSelected);
};
@@ -279,11 +278,11 @@ const FilterBar: React.FC = observer(() => {
logo={showStatusDropdown ? faChevronUp : faChevronDown}
logoPosition="right"
className={`bg-white text-sm lg:text-base whitespace-nowrap ${
- showStatusDropdown || selectedStatus ? activeButtonClass : inactiveButtonClass
+ showStatusDropdown || filterStatus ? activeButtonClass : inactiveButtonClass
}`}
/>
{showStatusDropdown && (
-
+
)}