From f375d543953ab53a3d15879b91e415226cf86a38 Mon Sep 17 00:00:00 2001 From: Terence Lo Date: Mon, 24 Feb 2025 15:23:05 -0800 Subject: [PATCH 01/20] fix reactAxe ts error --- frontend/eslint.config.mjs | 7 ++++++- frontend/src/vite-env.d.ts | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 frontend/src/vite-env.d.ts diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 1c25763c..4d84a018 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -28,7 +28,12 @@ export default [ "no-console": "warn", indent: ["error", 2], "no-irregular-whitespace": "error", - "prettier/prettier": "error", + "prettier/prettier": [ + "error", + { + endOfLine: "auto", + }, + ], "react/no-unescaped-entities": "off", "@typescript-eslint/no-unused-vars": ["error"], "tailwindcss/no-contradicting-classname": "error", diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..87da5bc1 --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1,10 @@ +/// + +interface ImportMetaEnv { + readonly VITE_APP_TITLE: string; + // more env variables... +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} From 2ca56d9b8a844ce57b19ccb8aeadd0072e941999 Mon Sep 17 00:00:00 2001 From: Bitian Zhang <86077274+bzzz-coding@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:25:12 -0800 Subject: [PATCH 02/20] Added Tailwind Button Components (#641) * Added Tailwind Button Components * Updated Buttons.tsx with clsx * Refactored button components --- frontend/package-lock.json | 14 +++ frontend/package.json | 1 + frontend/src/pages/Demo/DemoTailwind.tsx | 67 +++++++++++++- frontend/src/tw-components/Buttons.tsx | 113 +++++++++++++++++++++++ frontend/tailwind.config.js | 1 + 5 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 frontend/src/tw-components/Buttons.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a1d0cbf0..1ac3f2e4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "@popperjs/core": "^2.11.6", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", + "clsx": "^2.1.1", "react-hook-form": "^7.46.1", "react-popper": "^2.3.0", "vite-tsconfig-paths": "^4.3.1" @@ -3540,6 +3541,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -12930,6 +12939,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 73d8e4b2..a82f5797 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -70,6 +70,7 @@ "@popperjs/core": "^2.11.6", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", + "clsx": "^2.1.1", "react-hook-form": "^7.46.1", "react-popper": "^2.3.0", "vite-tsconfig-paths": "^4.3.1" diff --git a/frontend/src/pages/Demo/DemoTailwind.tsx b/frontend/src/pages/Demo/DemoTailwind.tsx index 54759963..652be178 100644 --- a/frontend/src/pages/Demo/DemoTailwind.tsx +++ b/frontend/src/pages/Demo/DemoTailwind.tsx @@ -1,14 +1,77 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import Typography from "tw-components/Typography"; +import { Button, IconButton } from "tw-components/Buttons"; const DemoTailwind = () => { + // Add a setDarkMode for testing dark mode styles + const [darkMode, setDarkMode] = useState(false); + + useEffect(() => { + if (darkMode) { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } + }, [darkMode]); + return (
+
+ + Buttons + + + + + {/* Regular Buttons, active is the default state */} + + Active + +
+ + + {/* Medium is the default*/} + + + + +
+ + {/* Disabled Buttons */} + + Disabled + +
+ + +
+ + {/* Hover & Active/Focused States */} + + Hover, Focused and Active + +
+ + + +
+ + {/* Icon Buttons */} + + Search Icon + +
+ + +
+
+
Typography Demo (Title 1 - Roboto Bold 48/137% +0) - Title Styles (Title 2 - Roboto Bold 36/137% +0) diff --git a/frontend/src/tw-components/Buttons.tsx b/frontend/src/tw-components/Buttons.tsx new file mode 100644 index 00000000..8d0d3fc5 --- /dev/null +++ b/frontend/src/tw-components/Buttons.tsx @@ -0,0 +1,113 @@ +import React from "react"; +import clsx from "clsx"; +import Typography from "tw-components/Typography"; + +const buttonSizes = { + small: "px-[24px] h-[32px]", + "small-long": "px-[40px] h-[32px]", + medium: "px-[32px] h-[42px]", + "medium-long": "px-[48px] h-[42px]", + large: "px-[40px] h-[51px]", + "large-long": "px-[56px] h-[51px]", + "icon-only": "px-[24px] h-[42px]", +}; + +type ButtonSize = keyof typeof buttonSizes; + +type BaseButtonProps = { + size?: ButtonSize; + disabled?: boolean; + className?: string; + children?: React.ReactNode; + onClick?: () => void; +}; + +// Shared styles +const baseButtonStyles = + "transition-all duration-200 flex items-center justify-center rounded-[64px] bg-blue-dark text-white hover:bg-blue-dark-hover focus:bg-blue-dark-focused focus:outline-none active:bg-blue-dark-focused disabled:bg-grey disabled:text-white disabled:cursor-not-allowed"; + +// Dark mode styles for enabled buttons +const enabledDarkModeStyles = + "dark:bg-white dark:text-blue-dark dark:hover:bg-grey-light dark:focus:bg-[#D9DBDF] dark:active:bg-[#D9DBDF] dark:disabled:bg-grey dark:disabled:text-grey-light"; + +// Base Button, no text, just styling +const BaseButton: React.FC = ({ + size = "medium", + disabled = false, + className, + children, + onClick, +}) => { + return ( + + ); +}; + +// Default Button, extends base button, adds typography +const buttonTypography: Record< + Exclude, + React.ElementType +> = { + small: Typography.Title7, + "small-long": Typography.Title7, + medium: Typography.Title6, + "medium-long": Typography.Title6, + large: Typography.Title5, + "large-long": Typography.Title5, +}; + +type ButtonProps = Omit & { + size?: Exclude; + children: React.ReactNode; +}; + +const Button: React.FC = ({ + size = "medium", + children, + ...props +}) => { + const TextComponent = buttonTypography[size]; + return ( + + {children} + + ); +}; + +// Icon Button, extends base button, adds static svg +type IconButtonProps = Omit; + +const IconButton: React.FC = (props) => { + return ( + + + + + + ); +}; + +export { Button, IconButton }; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index d6a6985e..7541c68e 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,5 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { + darkMode: "class", // Enables dark mode with a class content: [ "./src/pages/Demo/DemoTailwind.tsx", "./src/pages/Authentication/*.tsx", From 6cc026d78744fbc15e43f7d376d99ac57a424a6b Mon Sep 17 00:00:00 2001 From: Terence Lo Date: Mon, 24 Feb 2025 18:26:22 -0800 Subject: [PATCH 03/20] rm children prop --- frontend/src/tw-components/CookieBanner.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/tw-components/CookieBanner.tsx b/frontend/src/tw-components/CookieBanner.tsx index a8e71781..0d91c25d 100644 --- a/frontend/src/tw-components/CookieBanner.tsx +++ b/frontend/src/tw-components/CookieBanner.tsx @@ -7,8 +7,7 @@ import Cookies from "js-cookie"; import { IconButton } from "components/components"; import { iconX } from "assets/images/images"; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function CookieBanner(props: { children: React.ReactNode }) { +function CookieBanner() { const [hidden, setIsHidden] = useState( Cookies.get("cookieConsent") !== undefined, ); From 6a3a1c107c571b614fc6c65197017b811a221d86 Mon Sep 17 00:00:00 2001 From: Terence Lo Date: Mon, 24 Feb 2025 18:26:57 -0800 Subject: [PATCH 04/20] proxy dev api calls to django server --- docker-compose.yml | 3 +++ frontend/vite.config.mts | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ed4ed34c..4cd01664 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -48,6 +48,9 @@ services: container_name: vite env_file: - dev/dev.env + environment: + - VITE_APP_SERVER_URL=django://django:8000 + - VITE_APP_CLIENT_URL=vite://vite:5175 ports: - "5175:5175" develop: diff --git a/frontend/vite.config.mts b/frontend/vite.config.mts index 25057249..2feb224e 100644 --- a/frontend/vite.config.mts +++ b/frontend/vite.config.mts @@ -1,10 +1,16 @@ -import { defineConfig } from "vite"; +import { defineConfig, loadEnv } from "vite"; import react from "@vitejs/plugin-react"; import tsconfigPaths from "vite-tsconfig-paths"; import svgr from "vite-plugin-svgr"; import { resolve } from "path"; -export default defineConfig(() => { +export default defineConfig(({ mode }) => { + process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }; + + const SERVER_URL = `${ + process.env.VITE_APP_SERVER_URL ?? "http://localhost:8000" + }`; + return { //to resolve relative file paths for sass (no plugin) resolve: { @@ -22,6 +28,13 @@ export default defineConfig(() => { host: true, port: 5175, origin: "http://127.0.0.1:5175", + proxy: { + "/api": { + target: `${SERVER_URL}/api`, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ""), + }, + }, watch: { usePolling: true, }, From ae7a233fb5ea6d454044d40eb0166fcdb129d64a Mon Sep 17 00:00:00 2001 From: Terence Lo Date: Mon, 24 Feb 2025 18:57:36 -0800 Subject: [PATCH 05/20] add django:8000 host --- dev/dev.env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/dev.env.example b/dev/dev.env.example index fb338e0f..6439921b 100644 --- a/dev/dev.env.example +++ b/dev/dev.env.example @@ -9,7 +9,7 @@ POSTGRES_PASSWORD= ENVIRON=dev DEBUG=True SECRET_KEY= -DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] +DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] django SQL_ENGINE=django.db.backends.postgresql SQL_DATABASE= SQL_USER=postgres From 9a52cd50bff54497d444082d1548260c27777bc2 Mon Sep 17 00:00:00 2001 From: Terence Lo Date: Sun, 2 Mar 2025 19:49:27 -0800 Subject: [PATCH 06/20] fix eslint error --- frontend/src/tw-components/CookieBanner.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/tw-components/CookieBanner.tsx b/frontend/src/tw-components/CookieBanner.tsx index 0d91c25d..f23a2feb 100644 --- a/frontend/src/tw-components/CookieBanner.tsx +++ b/frontend/src/tw-components/CookieBanner.tsx @@ -25,10 +25,9 @@ function CookieBanner() {