Skip to content
Merged
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
6 changes: 3 additions & 3 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import js from "@eslint/js";
import globals from "globals";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import react from "eslint-plugin-react";
import globals from "globals";
import tseslint from "typescript-eslint";

export default tseslint.config(
Expand Down Expand Up @@ -46,7 +46,7 @@ export default tseslint.config(
},
settings: {
react: {
version: "17.0",
version: "18.2",
},
},
}
Expand Down
28 changes: 13 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,42 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@hookform/error-message": "^2.0.1",
"@react-oauth/google": "^0.12.1",
"@reduxjs/toolkit": "^1.8.0",
"@types/lodash": "^4.14.182",
"@types/react-datepicker": "^4.4.1",
"@types/react-dom": "^18.0.4",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.25",
"@reduxjs/toolkit": "^2.3.0",
"bootstrap": "^5.2.1",
"dayjs": "^1.11.0",
"lodash": "^4.17.21",
"query-string": "^7.1.1",
"react": "^17.0.2",
"react-bootstrap": "^2.7.0",
"react-datepicker": "^4.7.0",
"react-dom": "^17.0.2",
"react-dom": "^18.2.0",
"react-hook-form": "^7.52.0",
"react-redux": "^7.2.6",
"react-router-dom": "^5.3.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.9.1",
"react-select": "^5.3.0",
"react": "^18.2.0",
"styled-components": "^5.3.3"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.35.0",
"@types/lodash": "^4.14.182",
"@types/node": "^24.4.0",
"@types/react": "^18.0.9",
"@types/react-datepicker": "^4.4.1",
"@types/react-dom": "^18.0.4",
"@types/react-modal": "^3.16.3",
"@types/react-redux": "^7.1.7",
"@types/react": "^18.0.9",
"@types/styled-components": "^5.1.25",
"@vitejs/plugin-react": "^5.0.2",
"eslint": "^9.35.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"eslint-plugin-react": "^7.37.5",
"eslint": "^9.35.0",
"globals": "^16.4.0",
"prettier": "^3.1.1",
"typescript": "^5.9.2",
"typescript-eslint": "^8.44.0",
"typescript": "^5.9.2",
"vite": "^7.1.5"
},
"scripts": {
Expand Down
168 changes: 85 additions & 83 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useEffect } from "react";
import {
BrowserRouter as Router,
Redirect,
Navigate,
Route,
Switch,
Routes,
} from "react-router-dom";
import { useLoadCurrentUser, usePermissions } from "src/redux/auth";

import { refreshCsrfToken } from "src/apiClient/client";
import BaseLayout from "src/components/BaseLayout";
Expand All @@ -17,6 +16,7 @@ import { MyOfficeHoursHistory } from "src/pages/OfficeHours/MyOfficeHoursHistory
import { OfficeHoursHistory } from "src/pages/OfficeHours/OfficeHoursHistory";
import { RequestDeskCreditPage } from "src/pages/OfficeHours/RequestDeskCreditPage";
import { ChangePassword } from "src/pages/People/PersonProfile/PersonChangePassword";
import { useLoadCurrentUser, usePermissions } from "src/redux/auth";

import { AllGearPage, GearItemPage } from "./pages/Gear";
import { AddNewGear } from "./pages/Gear/AddNewGear";
Expand All @@ -31,98 +31,100 @@ function App() {
const { loggedIn, isLoading } = useLoadCurrentUser();
const { pathname, search } = window.location;
const { isApprover } = usePermissions();

useEffect(() => {
if (loggedIn) {
// Pre-load CSRF token
refreshCsrfToken();
}
}, [loggedIn]);

if (isLoading) {
return null;
}

const publicRoutes = (
<>
<Route path="/login" element={<LoginPage />} />
<Route
path="/reset-password/request"
element={<RequestPasswordReset />}
/>
<Route
path="/reset-password/confirm"
element={<RequestPasswordConfirm />}
/>
</>
);

// If not logged in and not loading, redirect to login
if (!isLoading && !loggedIn) {
return (
<Router basename="/">
<BaseLayout>
<Routes>
{publicRoutes}
<Route
path="*"
element={
<Navigate
to={{
pathname: "/login",
search: `redirectTo=${encodeURIComponent(
pathname + search,
)}`,
}}
replace
/>
}
/>
</Routes>
</BaseLayout>
</Router>
);
}

return (
<Router basename="/">
<BaseLayout>
<Switch>
<Route path="/login">
<LoginPage />
</Route>
<Route exact path="/reset-password/request/">
<RequestPasswordReset />
</Route>
<Route exact path="/reset-password/confirm/">
<RequestPasswordConfirm />
</Route>
<Route exact path="/change-password/">
<ChangePassword />
</Route>
{!isLoading && !loggedIn && (
<Redirect
to={{
pathname: "/login",
search: `redirectTo=${encodeURIComponent(pathname + search)}`,
}}
/>
)}
<Route exact path="/people">
<PeoplePage />
</Route>
<Route path="/people/:personId">
<PersonPage />
</Route>
<Route exact path="/add-person">
<AddNewPerson />
</Route>
<Route exact path="/add-gear">
<AddNewGear />
</Route>
<Route exact path="/gear">
<AllGearPage />
</Route>
<Route path="/gear/:gearId">
<GearItemPage />
</Route>
<Route exact path="/office-hours">
<OfficeHoursPage />
</Route>
<Route exact path="/gear-inventory">
<GearInventoryPage />
</Route>
<Route exact path="/approvals">
<ApprovalsPage />
</Route>
<Routes>
{publicRoutes}

<Route path="/change-password" element={<ChangePassword />} />

<Route path="/people" element={<PeoplePage />} />
<Route path="/people/:personId" element={<PersonPage />} />
<Route path="/add-person" element={<AddNewPerson />} />

<Route path="/add-gear" element={<AddNewGear />} />
<Route path="/gear" element={<AllGearPage />} />
<Route path="/gear/:gearId" element={<GearItemPage />} />

<Route path="/office-hours" element={<OfficeHoursPage />} />
<Route path="/gear-inventory" element={<GearInventoryPage />} />
<Route path="/approvals" element={<ApprovalsPage />} />

{isApprover && (
<Route exact path="/add-approval">
<AddNewApproval />
</Route>
)}
{loggedIn && (
<Route exact path="/request-desk-credit">
<RequestDeskCreditPage />
</Route>
)}
{loggedIn && (
<Route exact path="/approve-desk-credit">
<ApproveDeskCreditPage />
</Route>
<Route path="/add-approval" element={<AddNewApproval />} />
)}
{loggedIn && (
<Route exact path="/office-hours-history">
<OfficeHoursHistory />
</Route>
)}
{loggedIn && (
<Route exact path="/volunteer-history">
<MyOfficeHoursHistory />
</Route>
)}
<Route exact path="/">
<Redirect to="/people" />
</Route>
{loggedIn && (
<Route path="*">
<Redirect to="/people" />
</Route>
)}
</Switch>

<Route
path="/request-desk-credit"
element={<RequestDeskCreditPage />}
/>
<Route
path="/approve-desk-credit"
element={<ApproveDeskCreditPage />}
/>
<Route
path="/office-hours-history"
element={<OfficeHoursHistory />}
/>
<Route path="/volunteer-history" element={<MyOfficeHoursHistory />} />

<Route path="/" element={<Navigate to="/people" replace />} />
<Route path="*" element={<Navigate to="/people" replace />} />
</Routes>
</BaseLayout>
</Router>
);
Expand Down
18 changes: 8 additions & 10 deletions src/components/BaseLayout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import { newApprovalUI } from "src/featureFlags";
import { useEffect } from "react";
import { Link, useHistory } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
import styled from "styled-components";

import { User } from "src/apiClient/types";
import { PersonLink } from "src/components/PersonLink";
import { newApprovalUI } from "src/featureFlags";
import { logOut, useCurrentUser, usePermissions } from "src/redux/auth";
import { useAppDispatch, useConfig } from "src/redux/hooks";

export function Header() {
const { user } = useCurrentUser();

const { listen } = useHistory();
const location = useLocation();

// Hack to close the menu when the user clicks navigates to a new page
useEffect(() => {
return listen(() => {
const menuToggle = document.querySelector(".navbar-collapse");
if (menuToggle) {
menuToggle.classList.remove("show");
}
});
}, [listen]);
const menuToggle = document.querySelector(".navbar-collapse");
if (menuToggle) {
menuToggle.classList.remove("show");
}
}, [location]);

return (
<StyledNavBar className="navbar navbar-expand-md navbar-dark bg-dark mb-3 ">
Expand Down
9 changes: 6 additions & 3 deletions src/hooks/useQueryParamFilters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useHistory, useLocation } from "react-router";
import { useLocation, useNavigate } from "react-router-dom";

type Args<Filters> = {
parse: (params: URLSearchParams) => Filters;
Expand All @@ -14,7 +14,7 @@ export function useQueryParamFilters<Filters extends Record<string, any>>({
parse,
serialize,
}: Args<Filters>): ReturnType<Filters> {
const history = useHistory();
const navigate = useNavigate();
const location = useLocation();

const getFilters = () => {
Expand All @@ -26,7 +26,10 @@ export function useQueryParamFilters<Filters extends Record<string, any>>({
const newFilters = updater(getFilters());
const serialized = serialize(newFilters);
const params = new URLSearchParams(serialized);
history.replace({ pathname: location.pathname, search: params.toString() });
navigate(
{ pathname: location.pathname, search: params.toString() },
{ replace: true },
);
};

return { filters: getFilters(), setFilters };
Expand Down
8 changes: 5 additions & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ import "bootstrap/js/dist/dropdown";
import "./index.css";

import React from "react";
import ReactDOM from "react-dom";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";

import App from "./App";
import { store } from "./redux/store";

ReactDOM.render(
const container = document.getElementById("root");
const root = createRoot(container!);

root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root"),
);
8 changes: 4 additions & 4 deletions src/pages/Approvals/AddNewApproval.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import { useHistory, useLocation } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";

import {
createNewApproval,
Expand All @@ -14,7 +14,7 @@ import { AddNewApprovalForm } from "./AddNewApprovalForm";

export function AddNewApproval() {
useSetPageTitle("Approve restricted gear rental");
const history = useHistory();
const navigate = useNavigate();
const location = useLocation();
const [error, setError] = useState<APIErrorType | undefined>();
const refetchAllApprovals = gearDbApi.useLazyGetApprovalsQuery()[0];
Expand All @@ -32,9 +32,9 @@ export function AddNewApproval() {
refetchAllApprovals({ past: undefined });
if (personId != null) {
refetchPersonApprovals({ personID: personId, past: false });
history.push(`/people/${personId}?tab=approvals`);
navigate(`/people/${personId}?tab=approvals`);
} else {
history.push("/approvals");
navigate("/approvals");
}
})
.catch((err) => {
Expand Down
Loading
Loading