From 6d8ce5dc061d08357857724a7eb81e944bbba2f2 Mon Sep 17 00:00:00 2001 From: Jane Kamata Date: Tue, 24 Feb 2026 17:12:56 -0500 Subject: [PATCH 1/5] Matching styling and moving around files to be more organized --- backend/package-lock.json | 22 +-- frontend/src/{main-page => }/Footer.tsx | 2 +- frontend/src/Login.tsx | 157 ------------------ frontend/src/components/BrandingPanel.tsx | 17 ++ frontend/src/components/Button.tsx | 6 +- frontend/src/components/InputField.tsx | 7 +- frontend/src/images/logo.png | Bin 12764 -> 0 bytes frontend/src/{ => login}/ForgotPassword.tsx | 39 +---- frontend/src/login/Login.tsx | 118 +++++++++++++ frontend/src/main-page/MainPage.tsx | 2 +- .../grants/grant-view/CostBenefitAnalysis.tsx | 1 + frontend/src/routes/AppRoutes.tsx | 8 +- frontend/src/sign-up/BrandingPanel.tsx | 17 -- frontend/src/sign-up/LoginPrompt.tsx | 2 +- frontend/src/sign-up/PasswordField.tsx | 4 +- frontend/src/{ => sign-up}/Register.tsx | 9 +- .../src/{ => sign-up}/RegisterLanding.tsx | 18 +- frontend/src/sign-up/SignUpButton.tsx | 6 +- frontend/src/sign-up/SignUpForm.tsx | 13 +- frontend/src/sign-up/index.ts | 2 +- 20 files changed, 185 insertions(+), 265 deletions(-) rename frontend/src/{main-page => }/Footer.tsx (93%) delete mode 100644 frontend/src/Login.tsx create mode 100644 frontend/src/components/BrandingPanel.tsx delete mode 100644 frontend/src/images/logo.png rename frontend/src/{ => login}/ForgotPassword.tsx (59%) create mode 100644 frontend/src/login/Login.tsx delete mode 100644 frontend/src/sign-up/BrandingPanel.tsx rename frontend/src/{ => sign-up}/Register.tsx (91%) rename frontend/src/{ => sign-up}/RegisterLanding.tsx (74%) diff --git a/backend/package-lock.json b/backend/package-lock.json index 4a48a510..c41c3e99 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -206,7 +206,6 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -2306,7 +2305,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.12.tgz", "integrity": "sha512-v6U3O01YohHO+IE3EIFXuRuu3VJILWzyMmSYZXpyBbnp0hk0mFyHxK2w3dF4I5WnbwiRbWlEXdeXFvPQ7qaZzw==", "license": "MIT", - "peer": true, "dependencies": { "file-type": "21.3.0", "iterare": "1.2.1", @@ -2339,7 +2337,6 @@ "integrity": "sha512-97DzTYMf5RtGAVvX1cjwpKRiCUpkeQ9CCzSAenqkAhOmNVVFaApbhuw+xrDt13rsCa2hHVOYPrV4dBgOYMJjsA==", "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@nuxt/opencollective": "0.4.1", "fast-safe-stringify": "2.1.1", @@ -2423,7 +2420,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.12.tgz", "integrity": "sha512-GYK/vHI0SGz5m8mxr7v3Urx8b9t78Cf/dj5aJMZlGd9/1D9OI1hAl00BaphjEXINUJ/BQLxIlF2zUjrYsd6enQ==", "license": "MIT", - "peer": true, "dependencies": { "cors": "2.8.5", "express": "5.2.1", @@ -3197,7 +3193,6 @@ "integrity": "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", @@ -4016,7 +4011,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4043,7 +4037,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -4510,7 +4503,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -4731,7 +4723,6 @@ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -4779,15 +4770,13 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/class-validator": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", "license": "MIT", - "peer": true, "dependencies": { "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", @@ -6571,7 +6560,6 @@ "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.2.0", "@jest/types": "30.2.0", @@ -8154,7 +8142,6 @@ "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", "license": "MIT", - "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -8546,8 +8533,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/require-directory": { "version": "2.1.1", @@ -8752,7 +8738,6 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -9785,7 +9770,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10022,7 +10006,6 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -10246,7 +10229,6 @@ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", diff --git a/frontend/src/main-page/Footer.tsx b/frontend/src/Footer.tsx similarity index 93% rename from frontend/src/main-page/Footer.tsx rename to frontend/src/Footer.tsx index c3effd0a..ad2aa5d9 100644 --- a/frontend/src/main-page/Footer.tsx +++ b/frontend/src/Footer.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Group, Text, Link } from "@chakra-ui/react"; -import { FooterText } from "../translations/general"; +import { FooterText } from "./translations/general"; const Footer: React.FC = () => { return ( diff --git a/frontend/src/Login.tsx b/frontend/src/Login.tsx deleted file mode 100644 index 9fa1869f..00000000 --- a/frontend/src/Login.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import React, { useState } from "react"; -import { useAuthContext } from "./context/auth/authContext"; -import { observer } from "mobx-react-lite"; -import logo from "./images/logo.svg"; -import { useNavigate } from "react-router-dom"; -import "./external/bcanSatchel/mutators"; -import Button from "./components/Button"; - -/** - * Registered users can log in here - */ -const Login = observer(() => { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [rememberMe, setRememberMe] = useState(false); - const [showPassword, setShowPassword] = useState(false); - const [failure, setFailure] = useState(false); - const navigate = useNavigate(); - const { login } = useAuthContext(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - - const success = await login(email, password); - - if (success) { - navigate("/main/all-grants"); - } else { - setFailure(true); - } - }; - - return ( -
- {/*/ Left side: Registration form */} -
-
-

Log in

-
-
-
-
- -
- setEmail(e.target.value)} - placeholder="Enter your email address" - className="w-full rounded-xl border border-grey-600 bg-white py-3 px-4 text-base placeholder:text-grey-600 focus:outline-none focus:ring-2 focus:ring-primary-900 focus:border-transparent" - /> -
-
-
- -
- setPassword(e.target.value)} - placeholder="Enter your password" - className="w-full rounded-xl border border-grey-600 bg-white py-3 px-4 pr-12 text-base placeholder:text-grey-600 focus:outline-none focus:ring-2 focus:ring-primary-900 focus:border-transparent" - /> - -
-
-
- - {/* Remember Me & Forgot Password */} -
- - -
- - {/* Error Message */} -
- {failure && ( -
- Your password is incorrect or this account doesn't exist. -
- )} -
- -
- -
- - {/*/ Right side: logo */} -
-
- BCAN Logo -
-
- - ); -}); - -export default Login; diff --git a/frontend/src/components/BrandingPanel.tsx b/frontend/src/components/BrandingPanel.tsx new file mode 100644 index 00000000..83fff829 --- /dev/null +++ b/frontend/src/components/BrandingPanel.tsx @@ -0,0 +1,17 @@ +import logo from "../images/logo.svg"; + +/** + * Right-hand branding panel with orange background and BostonCAN logo. + * Uses Tailwind and primary-800 for panel background. + */ +export default function BrandingPanel() { + return ( +
+ BCAN Logo +
+ ); +} diff --git a/frontend/src/components/Button.tsx b/frontend/src/components/Button.tsx index f18332cc..edafeff1 100644 --- a/frontend/src/components/Button.tsx +++ b/frontend/src/components/Button.tsx @@ -20,8 +20,10 @@ export default function Button({ text, onClick, className, logo, logoPosition, d + @@ -84,14 +69,8 @@ const ForgotPassword = () => { {/* Right side: Logo */} -
-
- BCAN Logo -
+
+
); diff --git a/frontend/src/login/Login.tsx b/frontend/src/login/Login.tsx new file mode 100644 index 00000000..8b45648f --- /dev/null +++ b/frontend/src/login/Login.tsx @@ -0,0 +1,118 @@ +import React, { useState } from "react"; +import { useAuthContext } from "../context/auth/authContext"; +import { observer } from "mobx-react-lite"; +import { useNavigate } from "react-router-dom"; +import "../external/bcanSatchel/mutators"; +import Button from "../components/Button"; +import { BrandingPanel, InputField, PasswordField } from "../sign-up"; + +/** + * Registered users can log in here + */ +const Login = observer(() => { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [rememberMe, setRememberMe] = useState(false); + const [failure, setFailure] = useState(false); + const navigate = useNavigate(); + const { login } = useAuthContext(); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + const success = await login(email, password); + + if (success) { + navigate("/main/all-grants"); + } else { + setFailure(true); + } + }; + + return ( +
+ {/*/ Left side: Registration form */} +
+
+

Log in

+
+ +
+
+
+ setEmail(e.target.value)} error={failure} /> +
+
+
+
+ setPassword(e.target.value)} + error={failure} + /> +
+
+
+ + {/* Remember Me & Forgot Password */} +
+ + +
+ + {/* Error Message */} +
+ {failure && ( +
+ Your password is incorrect or this account doesn't exist. +
+ )} +
+ +
+ +
+ + {/*/ Right side: logo */} +
+ +
+ + ); +}); + +export default Login; diff --git a/frontend/src/main-page/MainPage.tsx b/frontend/src/main-page/MainPage.tsx index 6e050116..642d5357 100644 --- a/frontend/src/main-page/MainPage.tsx +++ b/frontend/src/main-page/MainPage.tsx @@ -6,7 +6,7 @@ import Users from "./users/Users"; import RestrictedPage from "./restricted/RestrictedPage"; import CashFlowPage from "./cash-flow/CashFlowPage"; import Settings from "./settings/Settings"; -import Footer from "./Footer"; +import Footer from "../Footer"; function MainPage() { return ( diff --git a/frontend/src/main-page/grants/grant-view/CostBenefitAnalysis.tsx b/frontend/src/main-page/grants/grant-view/CostBenefitAnalysis.tsx index 450294f5..4320a1b6 100644 --- a/frontend/src/main-page/grants/grant-view/CostBenefitAnalysis.tsx +++ b/frontend/src/main-page/grants/grant-view/CostBenefitAnalysis.tsx @@ -107,6 +107,7 @@ export const CostBenefitAnalysis: React.FC = ({ + /> diff --git a/frontend/src/sign-up/SignUpButton.tsx b/frontend/src/sign-up/SignUpButton.tsx index 0ea53f20..2307fa46 100644 --- a/frontend/src/sign-up/SignUpButton.tsx +++ b/frontend/src/sign-up/SignUpButton.tsx @@ -16,10 +16,6 @@ export default function SignUpButton({ disabled }: SignUpButtonProps) { type="submit" disabled={disabled} onClick={() => {}} - className={`mt-8 w-full text-base font-bold text-white transition-opacity ${ - disabled - ? "cursor-not-allowed bg-primary-700 opacity-70" - : "bg-primary-900 hover:opacity-95" - }`}/> + className={`mt-6 w-full text-base font-bold text-white`}/> ); } diff --git a/frontend/src/sign-up/SignUpForm.tsx b/frontend/src/sign-up/SignUpForm.tsx index 78d343fc..ae8aa7d5 100644 --- a/frontend/src/sign-up/SignUpForm.tsx +++ b/frontend/src/sign-up/SignUpForm.tsx @@ -45,7 +45,7 @@ export default function SignUpForm({ return (
-

Sign Up

+

Sign Up

@@ -69,11 +69,10 @@ export default function SignUpForm({ />
-
+
-
+
-
+
- + {!hasError && ()} {hasError && error?.message && ( -
+
{error.message}
)} diff --git a/frontend/src/sign-up/index.ts b/frontend/src/sign-up/index.ts index 39dca3d0..c6a92ab6 100644 --- a/frontend/src/sign-up/index.ts +++ b/frontend/src/sign-up/index.ts @@ -1,4 +1,4 @@ -export { default as BrandingPanel } from "./BrandingPanel"; +export { default as BrandingPanel } from "../components/BrandingPanel"; export { default as InputField } from "../components/InputField"; export { default as LoginPrompt } from "./LoginPrompt"; export { default as PasswordField } from "./PasswordField"; From fe693beea8271714e9ff2bb069625428c4307da8 Mon Sep 17 00:00:00 2001 From: Jane Kamata Date: Tue, 24 Feb 2026 17:23:18 -0500 Subject: [PATCH 2/5] Updating landing page --- frontend/src/routes/AppRoutes.tsx | 2 +- frontend/src/sign-up/RegisterLanding.tsx | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/frontend/src/routes/AppRoutes.tsx b/frontend/src/routes/AppRoutes.tsx index e86f61ca..72ce35cd 100644 --- a/frontend/src/routes/AppRoutes.tsx +++ b/frontend/src/routes/AppRoutes.tsx @@ -9,7 +9,7 @@ import ForgotPassword from "../login/ForgotPassword"; import RegisterLanding from "../sign-up/RegisterLanding"; import { getAppStore } from "../external/bcanSatchel/store"; import RestrictedPage from "../main-page/restricted/RestrictedPage"; -import Footer from "../main-page/Footer"; +import Footer from "../Footer"; /** * AppRoutes: diff --git a/frontend/src/sign-up/RegisterLanding.tsx b/frontend/src/sign-up/RegisterLanding.tsx index 62fb4aac..5595d793 100644 --- a/frontend/src/sign-up/RegisterLanding.tsx +++ b/frontend/src/sign-up/RegisterLanding.tsx @@ -1,7 +1,7 @@ import { Link } from "react-router-dom"; -import logo from "../images/logo.svg"; import { useAuthContext } from "../context/auth/authContext"; import Button from "../components/Button"; +import BrandingPanel from "../components/BrandingPanel"; /** * Registered user landing page after signing up @@ -9,18 +9,9 @@ import Button from "../components/Button"; const RegisterLanding = () => { const {logout} = useAuthContext(); return ( -
-
-
- BCAN Logo -
-
-
-
+
+
+

Account registration successful!

@@ -40,6 +31,9 @@ const RegisterLanding = () => {
+
+ +
); }; From 6f6ea11555b3548438e96b58d204de5c235eb192 Mon Sep 17 00:00:00 2001 From: Jane Kamata Date: Tue, 24 Feb 2026 17:24:45 -0500 Subject: [PATCH 3/5] Removing unused import --- frontend/src/login/ForgotPassword.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/login/ForgotPassword.tsx b/frontend/src/login/ForgotPassword.tsx index 1f5a40bd..983d36a4 100644 --- a/frontend/src/login/ForgotPassword.tsx +++ b/frontend/src/login/ForgotPassword.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; -import logo from "./images/logo.svg"; import { BrandingPanel, InputField } from "../sign-up"; import Button from "../components/Button"; From 3b7c0875efa0cff88d9a390785c7d53759d715cc Mon Sep 17 00:00:00 2001 From: Jane Kamata Date: Wed, 25 Feb 2026 00:46:44 -0500 Subject: [PATCH 4/5] Fixing password not matching issue --- frontend/src/sign-up/SignUpForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/sign-up/SignUpForm.tsx b/frontend/src/sign-up/SignUpForm.tsx index ae8aa7d5..8f5266fc 100644 --- a/frontend/src/sign-up/SignUpForm.tsx +++ b/frontend/src/sign-up/SignUpForm.tsx @@ -101,7 +101,7 @@ export default function SignUpForm({ placeholder="Re-enter your password" value={values.passwordRe} onChange={(e) => onChange("passwordRe", e.target.value)} - error={errorItem === "password"} + error={errorItem === "password" || passwordsMatch === false} />
From 6f37a8e2045bcbebe4f3bf5452be7a33ca496968 Mon Sep 17 00:00:00 2001 From: Jane Kamata Date: Wed, 25 Feb 2026 22:06:52 -0500 Subject: [PATCH 5/5] Updating disabled styling --- frontend/src/components/Button.tsx | 4 ++-- frontend/src/login/ForgotPassword.tsx | 2 +- frontend/src/sign-up/SignUpButton.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Button.tsx b/frontend/src/components/Button.tsx index edafeff1..a09c4ce7 100644 --- a/frontend/src/components/Button.tsx +++ b/frontend/src/components/Button.tsx @@ -22,8 +22,8 @@ export default function Button({ text, onClick, className, logo, logoPosition, d px-4 py-2 rounded-3xl font-medium text-black border-2 active:bg-primary-900 active:text-white flex items-center justify-center transition-opacity ${className} ${disabled - ? "cursor-not-allowed bg-primary-700 opacity-70" - : "bg-primary-900 hover:opacity-95"} + ? "cursor-not-allowed opacity-50" + : "hover:opacity-90"} `} > {logo && logoPosition === 'left' && diff --git a/frontend/src/login/ForgotPassword.tsx b/frontend/src/login/ForgotPassword.tsx index 983d36a4..b2326c62 100644 --- a/frontend/src/login/ForgotPassword.tsx +++ b/frontend/src/login/ForgotPassword.tsx @@ -36,7 +36,7 @@ const ForgotPassword = () => {
{/* Send Email Button */} -