-
+
+
+
Settings
+
+
+ {!isCollapsed && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
);
}
diff --git a/client/src/components/profileSettings/toggleNotification/index.css b/client/src/components/profileSettings/toggleNotification/index.css
new file mode 100644
index 0000000..e33b257
--- /dev/null
+++ b/client/src/components/profileSettings/toggleNotification/index.css
@@ -0,0 +1,39 @@
+.toggle-container {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ margin-bottom: 1rem;
+}
+
+.toggle-switch {
+ width: 60px;
+ height: 30px;
+ border-radius: 30px;
+ background-color: #ccc;
+ position: relative;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+}
+
+.toggle-switch.off {
+ background-color: #372a43;
+}
+
+.toggle-switch.on {
+ background-color: #be9fdb;
+}
+
+.toggle-thumb {
+ width: 26px;
+ height: 26px;
+ background-color: white;
+ border-radius: 50%;
+ position: absolute;
+ top: 2px;
+ left: 2px;
+ transition: transform 0.3s ease;
+}
+
+.toggle-switch.on .toggle-thumb {
+ transform: translateX(30px);
+}
diff --git a/client/src/components/profileSettings/toggleNotification/index.tsx b/client/src/components/profileSettings/toggleNotification/index.tsx
new file mode 100644
index 0000000..94e0913
--- /dev/null
+++ b/client/src/components/profileSettings/toggleNotification/index.tsx
@@ -0,0 +1,32 @@
+import React, { useState, useEffect } from 'react';
+import './index.css';
+
+function ToggleNotification() {
+ const [notificationsEnabled, setNotificationsEnabled] = useState(true);
+
+ const handleOnClick = () => {
+ const newValue = !notificationsEnabled;
+ localStorage.setItem('notificationsEnabled', JSON.stringify(newValue));
+ setNotificationsEnabled(newValue);
+ };
+
+ useEffect(() => {
+ const savedValue = localStorage.getItem('notificationsEnabled');
+ if (savedValue !== null) {
+ setNotificationsEnabled(JSON.parse(savedValue));
+ }
+ }, []);
+
+ return (
+
+ );
+}
+
+export default ToggleNotification;
diff --git a/client/src/tool/index.tsx b/client/src/tool/index.tsx
index 795cf43..a798e55 100644
--- a/client/src/tool/index.tsx
+++ b/client/src/tool/index.tsx
@@ -42,6 +42,48 @@ const keepTheme = () => {
}
};
+/**
+ * Helper function to set the website's text size.
+ * @param textSize - The string object which identifies the text size.
+ */
+const setTextSize = (textSize: string): void => {
+ localStorage.setItem('textSize', textSize);
+ document.documentElement.className = textSize;
+};
+
+/**
+ * Helper function to store a user's text size so it is kept when browser reopened.
+ */
+const keepTextSize = (): void => {
+ const textSize = localStorage.getItem('textSize');
+ if (textSize) {
+ setTextSize(textSize);
+ } else {
+ setTextSize('medium');
+ }
+};
+
+/**
+ * Helper function to set the website's colorblind mode.
+ * @param colorblindMode - The string object which identifies the colorblind mode.
+ */
+const setColorblindMode = (colorblindMode: string): void => {
+ localStorage.setItem('colorblindMode', colorblindMode);
+ document.documentElement.className = colorblindMode;
+};
+
+/**
+ * Helper function to store a user's colorblind mode so it is kept when browser reopened.
+ */
+const keepColorblindMode = (): void => {
+ const colorblindMode = localStorage.getItem('colorblindMode');
+ if (colorblindMode) {
+ setColorblindMode(colorblindMode);
+ } else {
+ setColorblindMode('false');
+ }
+};
+
/**
* Helper function to format the day of the month with leading zero if necessary.
* It returns a string representing the day of the month with a leading zero if it's less than 10.
@@ -155,4 +197,14 @@ const handleHyperlink = (text: string) => {
return
{content}
;
};
-export { getMetaData, setTheme, keepTheme, handleHyperlink, validateHyperlink };
+export {
+ getMetaData,
+ setTheme,
+ keepTheme,
+ setTextSize,
+ keepTextSize,
+ setColorblindMode,
+ keepColorblindMode,
+ handleHyperlink,
+ validateHyperlink,
+};
diff --git a/package-lock.json b/package-lock.json
index cc40e71..c11a6aa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -27,7 +27,8 @@
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^4.0.1",
- "remark-math": "^6.0.0"
+ "remark-math": "^6.0.0",
+ "ts-node": "^10.9.2"
}
},
"client": {
@@ -39,6 +40,7 @@
"axios": "^1.7.9",
"highlight.js": "^11.11.1",
"katex": "^0.16.21",
+ "lucide-react": "^0.487.0",
"mongodb": "6.12.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -2239,7 +2241,6 @@
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
@@ -2252,7 +2253,6 @@
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
@@ -4696,28 +4696,24 @@
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/@types/babel__core": {
@@ -6651,7 +6647,6 @@
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"acorn": "^8.11.0"
@@ -8535,7 +8530,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/cross-spawn": {
@@ -9416,7 +9410,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "devOptional": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
@@ -16602,6 +16595,15 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lucide-react": {
+ "version": "0.487.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.487.0.tgz",
+ "integrity": "sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
@@ -16642,7 +16644,6 @@
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "devOptional": true,
"license": "ISC"
},
"node_modules/makeerror": {
@@ -27528,7 +27529,6 @@
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
@@ -27572,7 +27572,6 @@
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/tsconfig-paths": {
@@ -28170,7 +28169,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/v8-to-istanbul": {
@@ -29202,7 +29200,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6"
diff --git a/package.json b/package.json
index 7726711..fea9aa6 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^4.0.1",
- "remark-math": "^6.0.0"
+ "remark-math": "^6.0.0",
+ "ts-node": "^10.9.2"
}
}