diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..67b63fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Node modules +node_modules/ + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# OS files +.DS_Store +Thumbs.db + +# Environment +.env + +# VS Code +.vscode/ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..39f8e30 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,99 @@ +{ + "name": "SaveBook", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "react": "^19.2.3", + "react-router-dom": "^7.13.0" + } + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.3" + } + }, + "node_modules/react-router": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz", + "integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz", + "integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==", + "license": "MIT", + "dependencies": { + "react-router": "7.13.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1eb3ac6 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "react": "^19.2.3", + "react-router-dom": "^7.13.0" + } +} diff --git a/savebook/app/globals.css b/savebook/app/globals.css index 333fcbc..daeb521 100644 --- a/savebook/app/globals.css +++ b/savebook/app/globals.css @@ -9,3 +9,19 @@ input::-ms-reveal, input::-ms-clear { display: none; } + +/* Light mode default */ +body { + @apply bg-white text-gray-900; +} + +/* Dark mode */ +.dark body { + @apply bg-gray-900 text-gray-100; +} + +/* Hide default browser password reveal button */ +input::-ms-reveal, +input::-ms-clear { + display: none; +} diff --git a/savebook/components/common/Navbar.js b/savebook/components/common/Navbar.js index b836db6..20f6004 100644 --- a/savebook/components/common/Navbar.js +++ b/savebook/components/common/Navbar.js @@ -10,6 +10,21 @@ export default function Navbar() { const [isScrolled, setIsScrolled] = useState(false); const [isClient, setIsClient] = useState(false); const { isAuthenticated, user, logout, loading } = useAuth(); + const [theme, setTheme] = useState("light"); + +useEffect(() => { + if (theme === "dark") { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } +}, [theme]); + + + const toggleTheme = () => { + setTheme(theme === "light" ? "dark" : "light"); +}; + // Handle client-side mounting useEffect(() => { @@ -169,21 +184,39 @@ export default function Navbar() { )} ) : ( - // Not authenticated - show login/signup buttons -